NeptuneAI-博客中文翻译-二-
NeptuneAI 博客中文翻译(二)
用预先训练好的变形金刚构建搜索引擎:一步一步指南
我们都用搜索引擎。我们搜索关于最好的商品、一个好去处的信息,或者回答我们想知道的任何问题。
我们也非常依赖搜索来检查电子邮件、文件和金融交易。很多这样的搜索交互都是通过文本或语音转换成语音输入来实现的。这意味着大量的语言处理发生在搜索引擎上,所以 NLP 在现代搜索引擎中扮演着非常重要的角色
让我们快速看一下搜索时会发生什么。当您使用查询进行搜索时,搜索引擎会收集与该查询匹配的文档的排序列表。要做到这一点,首先应该为文档和其中使用的词汇构建一个“索引,然后用于搜索和排列结果。对文本数据进行索引和对搜索结果进行排名的一种流行形式是 TF-IDF 。
NLP 的深度学习模型的最新发展可以用于此。例如,谷歌最近开始使用 BERT 模型对搜索结果进行排名并显示片段。他们声称这提高了搜索结果的质量和相关性。
有两种类型的搜索引擎:
- 通用搜索引擎,如 Google 和 Bing,抓取网页,并通过不断寻找新网页来覆盖尽可能多的网页。
- 企业搜索引擎,我们的搜索空间被限制在一个组织内已经存在的一个较小的文档集。
第二种形式的搜索是你在任何工作场所都会遇到的最常见的用例。看下图就清楚了。
您可以在 transformers 中使用最先进的句子嵌入,并在下游任务中使用它们来实现语义文本的相似性。
在本文中,我们将探索如何构建一个基于向量的搜索引擎。
为什么你需要一个基于矢量的搜索引擎?
基于关键字搜索引擎面临以下问题:
- 具有双重含义的复杂查询或单词。
- 长搜索查询。
- 不熟悉重要关键字的用户检索最佳结果。
基于向量(也称为语义搜索)的搜索通过使用 SOTA 语言模型找到文本查询的数字表示来解决这些问题。然后,它在高维向量空间中对它们进行索引,并测量查询向量与索引文档的相似程度。
让我们看看预训练模型能提供什么:
- 他们生产高质量的嵌入,因为他们在大量的文本数据上被训练。
- 他们不会强迫你创建一个自定义的记号赋予器,因为变形金刚有它们自己的方法。
- 它们非常简单方便来微调模型以适应你的下游任务。
这些模型为文档中的每个标记生成一个固定大小的向量。
现在,让我们看看如何使用预训练的 BERT 模型来构建搜索引擎的特征提取器。
步骤 1:加载预先训练的模型
!wget https://storage.googleapis.com/bert_models/2018_10_18/uncased_L-12_H-768_A-12.zip
!unzip uncased_L-12_H-768_A-12.zip
!pip install bert-serving-server --no-deps
对于这个实现,我将使用 BERT uncased。还有其他可用的 bert 变体——BERT-as-a-service 使用 BERT 作为句子编码器,并通过 ZeroMQ 将其作为服务托管,让您只需两行代码就可以将句子映射为固定长度的表示。如果您希望避免客户端-服务器架构引入的额外延迟和潜在模式,这将非常有用。
步骤 2:优化推理图
为了修改模型图,我们需要一些低级的张量流编程。因为我们使用的是 bert-as-a-service,所以我们可以使用一个简单的 CLI 界面来配置推断图。
(用于此实现的 tensorflow 版本是 tensorflow==1.15.2)
import os
import tensorflow as tf
import tensorflow.compat.v1 as tfc
sess = tfc.InteractiveSession()
from bert_serving.server.graph import optimize_graph
from bert_serving.server.helper import get_args_parser
MODEL_DIR = '/content/uncased_L-12_H-768_A-12'
GRAPH_DIR = '/content/graph/'
GRAPH_OUT = 'extractor.pbtxt'
POOL_STRAT = 'REDUCE_MEAN'
POOL_LAYER = '-2'
SEQ_LEN = '256'
tf.io.gfile.mkdir(GRAPH_DIR)
carg = get_args_parser().parse_args(args=['-model_dir', MODEL_DIR,
'-graph_tmp_dir', GRAPH_DIR,
'-max_seq_len', str(SEQ_LEN),
'-pooling_layer', str(POOL_LAYER),
'-pooling_strategy', POOL_STRAT])
tmp_name, config = optimize_graph(carg)
graph_fout = os.path.join(GRAPH_DIR, GRAPH_OUT)
tf.gfile.Rename(
tmp_name,
graph_fout,
overwrite=True
)
print("nSerialized graph to {}".format(graph_fout))
看看上面代码片段中的几个参数。
对于每个文本样本,基于 BERT 的模型编码层输出形状为[ sequence_len,encoder_dim ]的张量,每个输入令牌一个向量。为了获得固定的表示,我们需要应用某种类型的池。
POOL_STRAT 参数定义了应用于编码器层数 POOL_LAYER 的池策略。默认值**‘REDUCE _ MEAN’**对序列中所有记号的向量进行平均。当模型没有微调时,这种特殊的策略最适合大多数句子级的任务。另一个选项是 NONE ,在这种情况下不应用池。
SEQ _ 莱恩对模型处理的序列的最大长度有影响。如果想让模型推理速度几乎线性提升,可以给更小的值。
运行上面的代码片段会将模型图和权重放入一个 GraphDef 对象中,该对象将在 GRAPH_OUT 序列化为一个 pbtxt 文件。该文件通常比预训练模型小,因为训练所需的节点和变量将被移除。
让我们使用序列化的图来构建一个使用 tf 的特征提取器。估计器 API。我们需要定义 2 件事情:输入 _fn 和模型 _fn 。
input_fn 将数据获取到模型中。这包括执行整个文本预处理管道,并为 BERT 准备一个 feed_dict。
每个文本样本被转换成一个 tf。示例实例,具有在输入名称中列出的必要特征。bert_tokenizer 对象包含了单词表并执行文本处理。之后,示例在 feed_dict 中按照特性名称重新分组。
import logging
import numpy as np
from tensorflow.python.estimator.estimator import Estimator
from tensorflow.python.estimator.run_config import RunConfig
from tensorflow.python.estimator.model_fn import EstimatorSpec
from tensorflow.keras.utils import Progbar
from bert_serving.server.bert.tokenization import FullTokenizer
from bert_serving.server.bert.extract_features import convert_lst_to_features
log = logging.getLogger('tensorflow')
log.setLevel(logging.INFO)
log.handlers = []
GRAPH_PATH = "/content/graph/extractor.pbtxt"
VOCAB_PATH = "/content/uncased_L-12_H-768_A-12/vocab.txt"
SEQ_LEN = 256
INPUT_NAMES = ['input_ids', 'input_mask', 'input_type_ids']
bert_tokenizer = FullTokenizer(VOCAB_PATH)
def build_feed_dict(texts):
text_features = list(convert_lst_to_features(
texts, SEQ_LEN, SEQ_LEN,
bert_tokenizer, log, False, False))
target_shape = (len(texts), -1)
feed_dict = {}
for iname in INPUT_NAMES:
features_i = np.array([getattr(f, iname) for f in text_features])
features_i = features_i.reshape(target_shape).astype("int32")
feed_dict[iname] = features_i
return feed_dict
tf。估算器有一个特性,使它们在每次调用 predict 函数时重建和重新初始化整个计算图。
因此,为了避免开销,我们将将生成器传递给预测函数,生成器将在一个永无止境的循环中为模型生成特征。
def build_input_fn(container):
def gen():
while True:
try:
yield build_feed_dict(container.get())
except:
yield build_feed_dict(container.get())
def input_fn():
return tf.data.Dataset.from_generator(
gen,
output_types={iname: tf.int32 for iname in INPUT_NAMES},
output_shapes={iname: (None, None) for iname in INPUT_NAMES})
return input_fn
class DataContainer:
def __init__(self):
self._texts = None
def set(self, texts):
if type(texts) is str:
texts = [texts]
self._texts = texts
def get(self):
return self._texts
model_fn 包含模型的规格。在我们的例子中,它是从我们在上一步中保存的 pbtxt 文件中加载的。这些特征通过输入映射明确映射到相应的输入节点。
def model_fn(features, mode):
with tf.gfile.GFile(GRAPH_PATH, 'rb') as f:
graph_def = tf.GraphDef()
graph_def.ParseFromString(f.read())
output = tf.import_graph_def(graph_def,
input_map={k + ':0': features[k] for k in INPUT_NAMES},
return_elements=['final_encodes:0'])
return EstimatorSpec(mode=mode, predictions={'output': output[0]})
estimator = Estimator(model_fn=model_fn)
现在我们已经准备好了,我们需要进行推理。
def batch(iterable, n=1):
l = len(iterable)
for ndx in range(0, l, n):
yield iterable[ndx:min(ndx + n, l)]
def build_vectorizer(_estimator, _input_fn_builder, batch_size=128):
container = DataContainer()
predict_fn = _estimator.predict(_input_fn_builder(container), yield_single_examples=False)
def vectorize(text, verbose=False):
x = []
bar = Progbar(len(text))
for text_batch in batch(text, batch_size):
container.set(text_batch)
x.append(next(predict_fn)['output'])
if verbose:
bar.add(len(text_batch))
r = np.vstack(x)
return r
return vectorize
bert_vectorizer = build_vectorizer(estimator, build_input_fn)
bert_vectorizer(64*['sample text']).shape
o/p: (64, 768)
第四步:用投影仪探索向量空间
使用矢量器,我们将为来自 Reuters-221578 基准语料库的文章生成嵌入。
为了探索和可视化三维嵌入向量空间,我们将使用一种称为 T-SNE 的降维技术。
首先让我们得到文章嵌入。
from nltk.corpus import reuters
import nltk
nltk.download("reuters")
nltk.download("punkt")
max_samples = 256
categories = ['wheat', 'tea', 'strategic-metal',
'housing', 'money-supply', 'fuel']
S, X, Y = [], [], []
for category in categories:
print(category)
sents = reuters.sents(categories=category)
sents = [' '.join(sent) for sent in sents][:max_samples]
X.append(bert_vectorizer(sents, verbose=True))
Y += [category] * len(sents)
S += sents
X = np.vstack(X)
X.shape
运行上述代码后,如果你在 collab 中遇到任何问题,比如:" Resource reuters not found。请使用 NLTK 下载程序获取资源。
…然后运行以下命令,其中-d 后面的相对路径将给出文件解压缩的位置:
!unzip /root/nltk_data/corpora/reuters.zip -d /root/nltk_data/corpora
生成的嵌入的交互式可视化可在嵌入投影仪上获得。
通过链接,你可以自己运行 t-SNE ,或者使用右下角的书签加载一个检查点(加载在 Chrome 上有效)。
要重现用于该可视化的输入文件,请运行下面的代码片段。然后将文件下载到您的机器上,并上传到投影仪。
with open("embeddings.tsv", "w") as fo:
for x in X.astype('float'):
line = "t".join([str(v) for v in x])
fo.write(line+'n')
with open('metadata.tsv', 'w') as fo:
fo.write("LabeltSentencen")
for y, s in zip(Y, S):
fo.write("{}t{}n".format(y, s))
这是我用投影仪捕捉到的。
from IPython.display import HTML
HTML("""
<video width="900" height="632" controls>
<source src="https://storage.googleapis.com/bert_resourses/reuters_tsne_hd.mp4" type="video/mp4">
</video>
""")
使用生成的特征构建监督模型非常简单:
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
Xtr, Xts, Ytr, Yts = train_test_split(X, Y, random_state=34)
mlp = LogisticRegression()
mlp.fit(Xtr, Ytr)
print(classification_report(Yts, mlp.predict(Xts)))
精确 | 回忆 | f1-分数 | 支持 | |
---|---|---|---|---|
步骤 5:构建搜索引擎
假设我们有一个 50,000 个文本样本的知识库,我们需要根据这些数据快速回答查询。如何从文本数据库中检索出与查询最相似的结果?答案之一可以是最近邻搜索。
我们在这里解决的搜索问题可以定义如下:
给定向量空间中的一组点SM和一个查询点Q∈M, 求距离 S 到 Q 最近的点。在向量空间中有多种方法来定义 【最接近】——我们将使用欧几里德距离。
要构建文本搜索引擎,我们将遵循以下步骤:
- 对知识库中的所有样本进行矢量化——这就给出了 S 。
- 向量化查询——这给出了 Q 。
- 计算 Q 和 S 之间的欧几里德距离 D 。
- 按升序排序D-提供最相似样本的索引。
- 从知识库中检索所述样本的标签。
我们可以为 Q 和 S: 创建占位符
graph = tf.Graph()
sess = tf.InteractiveSession(graph=graph)
dim = X.shape[1]
Q = tf.placeholder("float", [dim])
S = tf.placeholder("float", [None, dim])
定义欧几里德距离计算:
squared_distance = tf.reduce_sum(tf.pow(Q - S, 2), reduction_indices=1)
distance = tf.sqrt(squared_distance)
获取最相似的指数:
top_k = 10
top_neg_dists, top_indices = tf.math.top_k(tf.negative(distance), k=top_k)
top_dists = tf.negative(top_neg_dists)
from sklearn.metrics.pairwise import euclidean_distances
top_indices.eval({Q:X[0], S:X})
np.argsort(euclidean_distances(X[:1], X)[0])[:10]
第六步:用数学加速搜索
在 tensorflow 中,这可以按如下方式完成:
Q = tf.placeholder("float", [dim])
S = tf.placeholder("float", [None, dim])
Qr = tf.reshape(Q, (1, -1))
PP = tf.keras.backend.batch_dot(S, S, axes=1)
QQ = tf.matmul(Qr, tf.transpose(Qr))
PQ = tf.matmul(S, tf.transpose(Qr))
distance = PP - 2 * PQ + QQ
distance = tf.sqrt(tf.reshape(distance, (-1,)))
top_neg_dists, top_indices = tf.math.top_k(tf.negative(distance), k=top_k)
上式中 PP 和 QQ 实际上是各自向量的平方 L2 范数。如果两个向量都是 L2 归一化的,则:
PP = QQ = 1
进行 L2 归一化会丢弃关于矢量幅度的信息,这在很多情况下是你不想做的。
相反,我们可能会注意到,只要知识库保持不变——PP——其平方向量范数也保持不变。因此,我们可以只做一次,然后使用预先计算的结果,而不是每次都重新计算,从而进一步加快距离计算。
让我们一起努力。
class L2Retriever:
def __init__(self, dim, top_k=3, use_norm=False, use_gpu=True):
self.dim = dim
self.top_k = top_k
self.use_norm = use_norm
config = tf.ConfigProto(
device_count = {'GPU': (1 if use_gpu else 0)}
)
self.session = tf.Session(config=config)
self.norm = None
self.query = tf.placeholder("float", [self.dim])
self.kbase = tf.placeholder("float", [None, self.dim])
self.build_graph()
def build_graph():
if self.use_norm:
self.norm = tf.placeholder("float", [None, 1])
distance = dot_l2_distances(self.kbase, self.query, self.norm)
top_neg_dists, top_indices = tf.math.top_k(tf.negative(distance), k=self.top_k)
top_dists = tf.negative(top_neg_dists)
self.top_distances = top_dists
self.top_indices = top_indices
def predict(self, kbase, query, norm=None):
query = np.squeeze(query)
feed_dict = {self.query: query, self.kbase: kbase}
if self.use_norm:
feed_dict[self.norm] = norm
I, D = self.session.run([self.top_indices, self.top_distances],
feed_dict=feed_dict)
return I, D
def dot_l2_distances(kbase, query, norm=None):
query = tf.reshape(query, (1, 1))
if norm is None:
XX = tf.keras.backend.batch_dot(kbase, kbase, axes=1)
else:
XX = norm
YY = tf.matmul(query, tf.transpose(query))
XY = tf.matmul(kbase, tf.transpose(query))
distance = XX - 2 * XY + YY
distance = tf.sqrt(tf.reshape(distance, (-1, 1)))
return distance
我们可以将这种实现用于任何矢量器模型,而不仅仅是 BERT。它在最近邻检索方面非常有效,能够在双核 colab CPU 上每秒处理几十个请求。
在构建机器学习应用时,你需要考虑一些额外的方面:
您如何确保解决方案的可扩展性?
选择正确的框架/语言。
使用正确的处理器。
收集和存储数据。
输入管道。
模特培训。
分布式系统。
其他优化。
资源利用和监控。
展开。
你如何训练、测试和部署你的产品模型?
创建一个可用于下载和处理数据的笔记本实例。
准备数据/预处理它,你需要训练你的 ML 模型,然后上传数据(例如:亚马逊 S3)。
使用您的训练数据集来训练您的机器学习模型。
将模型部署到端点,重新格式化并加载 csv 数据,然后运行模型以创建预测。
评估 ML 模型的性能和准确性。
旁注–通过实验跟踪简化 ML
一个工具可以照顾你所有的实验跟踪和协作需求——Neptune . ai
Neptune 记录您的整个实验过程——探索笔记本、模型训练运行、代码、超参数、指标、数据版本、结果、探索可视化等等。
这是 MLOps 的元数据存储,为进行大量实验的研究和生产团队而构建。专注于 ML,把元数据管理留给 Neptune。要开始使用 Neptune,请访问他们广泛的指南。
像 Neptune 这样的 ML 元数据存储是 MLOps 栈的重要组成部分。在您构建模型时,它负责元数据管理。
它记录、存储、显示、组织、比较和查询 ML 模型生命周期中生成的所有元数据。
您可以使用 ML metastore 来跟踪、组织和比较您在 ML 实验中关心的一切。
Neptune 集成了所有你喜欢的框架和工具——最流行的集成之一是直接通过 TensorBoard 完成的 Tensorflow/Keras 。
结论
使用 BERT 搜索的主要探索领域是相似性。文档的相似性、推荐的相似性以及查询和文档之间的相似性,用于返回和排列搜索结果。
如果你能使用相似性来解决这个问题,并得到非常精确的结果,那么你就能很好地搜索到你的产品或应用。
我希望你在这里学到了新东西。感谢阅读。不断学习。
用 BERT 嵌入构建情感分类系统:经验教训
情感分析,通常被称为观点挖掘/情感分类,是利用计算语言学、文本分析、自然语言处理从源材料中识别和提取主观信息的技术。它经常被用来评估一个演讲者或作者对一个主题的观点或一篇文章的整体语境极性。情感分析的结果通常是表示文本情绪(例如,积极、消极、中性)的分数或二进制值。
情感分析是市场营销和产品空间中最重要的概念之一。它帮助企业识别客户对其产品和服务的反应。现在,每一个提供产品或服务的企业都提供用户反馈服务,用户可以自由地发表他们对服务的感受。然后使用机器学习和深度学习情感分析技术,这些企业分析客户对他们的产品是积极还是消极,以便他们可以做出适当的商业决策来改善他们的业务。
通常有三种不同的方法来实现情感分类系统:
**基于规则的方法:**在这种方法中,使用一组预定义的规则来对文本的情感进行分类。不同的单词集合首先被标记为三个不同的类别。比如“开心”、“优秀”等词语。被赋予一个积极的标签。像“血统”、“平均”等词。被分配了一个中性的标签,最后,像“悲伤”、“不好”等词。被赋予了一个负面的标签。如果在文本中检测到这些词中的任何一个,那么它被分类到给定的情感类别之一中。
基于 ML 的方法:基于规则的方法不能识别诸如讽刺和挖苦、多种类型的否定、单词歧义和文本中的多极等事物。例如,“太好了,你又迟到了”,是一个带有负面情绪的句子,但是这个句子被归类为正面情绪的可能性更高。由于这个原因,企业现在专注于基于 ML 的方法,其中不同的 ML 算法在预先标记的文本的大数据集上训练。这些算法不仅关注单词,还关注其在不同场景中的上下文以及与其他单词的关系。不同的方法,如基于单词包的模型、基于 LSTM 的模型、基于变压器的模型等。,用于对文本情感进行分类。
**混合方法:**这种方法是上述两种方法的结合,可以同时使用基于规则和基于 ML 的方法进行情感分类系统。
在过去的几年中,基于 ML 的方法之一是基于变压器的模型,如 BERT。一种预训练的基于变压器的神经网络模型,称为 BERT(来自变压器的双向编码器表示),已经在各种自然语言处理应用程序上获得了前沿性能,包括情感分析。BERT 可以理解给定文本的上下文,这使它成为情感分析的一个很好的候选对象。
The model architecture of the Transformer | Source
BERT 考虑短语中单词的双向上下文的能力是另一个显著的优点。一个单词的上下文以前只考虑它前面的单词,但是 BERT 模型也考虑它后面的单词。这增强了它在情感分析中的性能,并帮助它更好地理解单词的含义。
在本文中,您将看到我在研究情感分类模型时学到的一些东西。
从使用 BERT 构建情感分类中获得的经验教训
你可能会困惑的一件事是,如何准确地使用 BERT 嵌入进行情感分类。要回答这个,你需要先了解一下一击学习或者零击学习的概念。
在这种方法中,您使用预先训练的 BERT 模型来获得不属于训练的新数据的嵌入。当你没有足够的数据来训练任何深度学习模型时,这种方法是最合适的。然后,这些嵌入被用作任何分类模型的输入,如逻辑回归、SVC、CNN 等。以进一步将它们分类为情绪类别之一(消极、中立和积极)。
The architecture of BERT embedding, based sentiment classification system| Source: Author
是时候讨论我在处理这个用例时学到的东西了,这样当你遇到这些挑战时你就知道该怎么做了。
处理多语言数据
问题 1:预处理多语言数据
数据预处理是任何基于 ML 或 AI 的项目的基石。您用于 ML 的每个数据集都需要以某种方式进行处理。例如,在情感分类等 NLP 用例中,您需要通过删除停用词和一些常规词(如 the、he、you 等)来预处理文本。,因为这些单词对机器没有任何意义。此外,还有某些预处理阶段,如删除电子邮件 id、删除电话号码、删除特殊字符、词干或词汇化等。,用于为模型训练清理数据。
对于英语来说,这似乎很容易,因为通用语言已经有了很大的发展,但是对于多语言数据,您将无法确定,因为这些语言具有不同的语法结构、词汇和习惯表达方式。这使得训练一个能够同时准确处理多种语言的模型变得困难。此外,一些语言使用非拉丁字符,这可能会导致预处理和建模方面的问题,这包括中文、阿拉伯语、日语等语言。
解决办法
有效地预处理多语言数据是 ML 模型在现实世界数据中表现更好的原因。对于这种多语言数据,您需要准备不同的停用词、常规词、词汇化/词干化词等列表。这可能很耗时。感谢 NLTK 和 Scipy 库为所有数据预处理任务提供了一个语料库列表。您需要加载您正在使用的语言的语料库,并使用不同的函数对数据进行预处理。此外,要删除特殊字符(非拉丁单词),您需要手动准备一个函数,确定哪些字符不是文本的一部分,并显式删除它们。
问题 2:多语言数据建模
如今,大多数产品都内置了多语言功能。随着越来越多的地区和非地区的人可以使用它,这使得企业得以发展。但是这种支持多种语言的特性也产生了为情感分类创建不同的 ML 模型的问题。在处理用于情感分类的多语言数据时会出现一些问题:
- 语法结构、词汇和习惯表达因语言而异。由于这一点,训练一个可以同时准确处理几种语言的模型可能具有挑战性。
- 用几种语言收集和注释大量的数据可能会花费大量的时间和金钱。因此,用足够的数据来训练模型以产生高性能可能是具有挑战性的。
- 由于几种语言的嵌入空间可能不直接相关,因此在多语言嵌入中比较不同语言的嵌入可能具有挑战性。
- 情感标注是一项主观任务,可能会因标注器而异,尤其是跨语言,这会导致标注不一致,从而影响模型的性能。
英语是通用语言,所有原始语言模型通常都是用英语训练的。因此,处理多语言数据可能相当具有挑战性。
解决办法
问题强调得够多了,现在让我们讨论多语言数据的解决方案。当您开始处理语言模型时,您通常更喜欢预先训练的模型,因为您可能没有足够的数据和资源来从头开始训练它。寻找一个语言指定的模式,如法语,德语,印地语等。几年前,这是很困难的,但多亏了 HuggingFace ,现在你可以找到在多种语言语料库上为不同任务训练的不同模型。使用这些模型,您可以处理情感分类任务,而不必从头开始训练模型。
The dual encoder architecture | Source
或者,您可以使用多语言嵌入模型,如语言无关的 BERT 句子嵌入(LaBSE)。多语言嵌入模型是一种有效的工具,它将用于语言理解的语义信息与将各种语言的文本编码到公共嵌入空间的能力结合起来。这使得它可以用于各种下游任务,包括文本分类、聚类等。该模型可以为 109 种语言生成语言无关的跨语言句子嵌入。使用 MLM 和 TLM 对 170 亿单语短语和 60 亿双语句子对的预训练来训练该模型,产生即使在训练期间没有可用数据的低资源语言中也是有效的模型。想了解这款车型的更多信息,可以参考这篇文章。
另一种方法是将文本从一种语言翻译成另一种语言。这可以通过使用机器翻译工具来完成,如谷歌翻译或 T2 微软翻译。然而,这种方法会在翻译中引入错误,并且还会丢失原始文本的一些细微差别。
最后,如果每种语言都有足够的数据,另一种策略是为每种语言训练不同的模型。使用这种方法,您可以更好地为目标语言优化模型,并获得更好的性能。
处理文本中的讽刺、讽刺、否定、歧义和多极
问题
讽刺、讽刺、多种类型的否定、单词歧义和多极都可能导致情感分类中的困难,因为它们可以改变句子或短语的预期含义。挖苦和讽刺可以使积极的陈述显得消极,或者使消极的陈述显得积极。否定也可以改变一个陈述的情绪,例如一个包含“不是”这个词的句子,它可以颠倒句子的意思。单词歧义会使确定句子的预期情感变得困难,因为一个单词可能有多种含义。多极还会导致情感分类困难,因为一个文本可以同时包含多种情感。这些问题会使得情感分类器难以准确地确定文本的预期情感。
解决办法
讽刺、讽刺、多种类型的否定、单词歧义和文本中的多极在情感分类中可能难以检测,因为它们可以改变句子或短语的含义。解决这些问题的一种方法是使用自然语言处理技术的组合,如情感词汇,以及机器学习算法来识别指示讽刺或讽刺的模式和上下文线索。
此外,整合额外的数据源,如社交媒体对话或客户评论,可以帮助提高情感分类的准确性。另一种方法是使用预先训练的模型,如 BERT,它已经在大规模数据集上进行了微调,以理解文本中单词的上下文和含义。这也是为什么 BERT 是情感分类的明智选择的主要原因之一。
训练数据中的潜在偏差
问题
用于情感分析的训练数据通常是人类标记的文本,其中人类检查特定的句子或段落,并为其分配标签,如负面、正面或中性。然后,这些数据被用于训练模型和进行推理。由于数据是由人类准备的,数据很可能会有人类偏见。例如,“我喜欢被忽视”可能被标记为负面例子,“我可以非常有雄心壮志”可以被标记为正面例子。当在这种类型的数据上训练模型时,模型可能偏向某些文本而忽略其他文本。
解决办法
为了解决训练数据中的潜在偏差,您可以从去偏差技术开始。一些技术,例如对抗性去偏置,可以应用于嵌入以减少对特定敏感属性的偏置,这可以通过向模型添加目标来实现,该目标阻止模型使用特定敏感属性来进行预测。此外,通过在训练过程中考虑种族、性别或宗教等敏感属性,公平意识训练方法可用于解决模型中的偏见。这些方法可以减少敏感属性对模型预测的影响。
您还可以准备一个单词字典,并将它们标记为不同的类别,这样标记数据的人就可以在注释中保持一致。最后,使用各种评估指标,如人口统计均等、机会均等和个人公平,这有助于识别和评估模型中的潜在偏差。
对您的数据使用预先训练的 BERT 模型
问题
在处理 NLP 任务(如情感分类)时,最大的困惑之一是,是应该从头开始训练模型,还是使用预先训练好的模型。由于我们在本文中关注的是 BERT 模型,这些问题的强度会更大,因为 BERT 是一个非常大的模型,需要大量的数据、时间和资源来从头训练它。
如果任务与为其训练预训练模型的任务相似,并且用于微调模型的数据集很小,则使用预训练的 BERT 模型可能是一个不错的选择。在这种情况下,可以使用小数据集在情感分类任务上对预训练模型进行微调。与从头开始训练模型相比,这可以节省大量时间和资源。
但是,如果任务与训练预训练模型的任务明显不同,或者如果用于微调模型的数据集很大,则从头训练 BERT 模型可能更有效。这将允许模型学习手头任务的更多具体特征,并避免预训练模型中的潜在偏差。此外,如果您想从头开始训练模型,在选择合适的硬件架构或平台来这样做时会有很多困惑。
解决办法
所以,现在你知道在什么条件下使用什么技术,但是这仍然没有说明如何使用这些模型。同样,你不必担心预训练的模型,因为 HuggingFace 为你提供了许多用于不同任务的预训练模型,如情感分类、翻译、问答系统、 t ext 生成等。你只需要前往 HuggingFace 库,搜索特定任务和语言的模型,你就会有一个相同的预训练模型列表。此外,如果数据集包含不同的语言,使用预训练的多语言 BERT 模型(如 mBERT)会给出更好的结果。
如果没有预训练的模型可用于您的用例,那么您需要自己准备数据,并使用迁移学习或从头开始训练模型。但是有一个问题,从一开始训练一个模型或者使用迁移学习可能需要大量的时间、精力和成本。因此,您需要设计一个适当的管道来有效地训练模型。
- 1 训练 BERT 模型的最常见方法是使用预训练模型作为特征提取器(冻结模型的参数),并为我们的特定任务训练另一个简单的线性模型,该模型具有少得多的可用训练数据。
- 2 还有一个就是在预训练的模型中替换几层,在你的自定义数据上对其进行训练,用于所选的任务。最后,如果这两种方法没有给出好的结果(这是非常罕见的情况),您可以从头开始训练模型。
关注像 BERT 这样的大型复杂模型的训练也很重要,如果不使用现代 MLOps 工具,这可能会很困难。在训练这些模型时,很难跟踪实验、监控结果、比较不同的运行等。使用像 neptune.ai 这样的工具,您可以跟踪您在整个项目中尝试的模型及其参数,并比较不同的训练运行,以选择最佳的模型参数。此外,这些工具使您能够直观地检查结果,以便对 BERT 训练做出更明智的决策。
Neptune 还提供了一个监控仪表板(用于培训),用于监控 BERT 或任何模型的学习曲线和准确性。此外,它还能让您了解训练期间 CPU、GPU 和内存的硬件消耗情况。因为 transformer 模型非常精密,实验跟踪仪表板使您能够立即看到意外的行为,并且由于它们的配置和代码跟踪特性,您可以简单地查看它。在所有这些功能的帮助下,使用迁移学习或从头开始训练 BERT 模型变得非常容易。
要了解更多关于如何有效训练 BERT 模型的信息,可以参考这篇文章。
**注意:**使用预先训练的模型,在你的数据上微调模型,并从头开始训练模型,所有这些都只需要为文本数据生成嵌入,然后将其传递给分类模型用于情感分类。
用 BERT 嵌入测试情感分类的性能
问题
一旦你有了通过 BERT 模型生成的嵌入,下一步你要关注的是使用分类模型进行情感分类。作为这种分类的一部分,您可以尝试不同的分类器,并根据不同的性能度量来确定哪一个最适合您。
ML 开发者可能犯的一个大错误是在评估分类模型时总是依赖准确性。在真实世界的情感分类用例中,可能存在类别不平衡的问题,其中一个类别的样本与其他类别相比在数量上占优势。
这可能导致扭曲的度量,例如少数类的高准确性但低性能。此外,一些短语或句子可能有歧义,可以有不同的解释。这可能导致模型的预测情绪和真实情绪之间的不匹配。最后,情绪可以通过多种方式表达,如文字、表情符号和图像,一个模型可能在一种模式下表现良好,而在另一种模式下表现不佳。
解决办法
由于存在类别不平衡、主观性、模糊性和多模态情感的问题,因此不建议仅使用一种性能指标,而是使用指标的组合,并考虑数据集和任务的具体特征和限制。评估情感分类模型最常用的指标是精度、召回率和F1-分数。此外,还使用了受试者工作特征曲线下面积( AUC-ROC )和混淆矩阵。
除了选择多种度量标准,您还应该关注模型测试策略。为此,您需要将数据集分为训练数据集、验证数据集和测试数据集。训练和验证数据集分别用于模型训练和运行时模型评估,而测试数据显示模型的真实性能。
最后,您需要确保数据注释和准备工作做得正确,否则,即使您的模型给出了正确的预测,它也不会与标记的预测相同。所以要确保注释是正确的,并且是统一的。
部署和监控
问题
最后,一切都是为了在某个地方部署 ML 模型,以便最终用户可以使用它们。与诸如基于单词包的模型、基于 LSTM 的模型等其他机制相比。基于 Transformer 的模型(比如 BERT)非常大,需要一些额外的资源来存放模型。
与所有其他基于 ML 的模型一样,BERT 模型也期望相同类型的预处理输入来生成准确的嵌入。因此,您需要确保将相同的预处理阶段应用于测试数据,就像应用于训练数据一样。最后,部署模型是不够的,您需要监控这个基于 BERT 的模型几个月,以了解它是否如预期的那样执行,或者它是否有进一步改进的空间。
解决办法
部署情感分类模型有几种解决方案。你可以使用一个预先训练好的模型,并在你的特定数据集上对其进行微调,然后将其部署在云平台上,如 AWS 、谷歌云或 Azure 。您还可以使用深度学习框架(如 TensorFlow 或 PyTorch)构建自定义模型,并将其部署在具有特定于平台的服务(如 TensorFlow Serving 或 PyTorch Serve )的云平台上。
此外,使用预先训练的模型并将其部署在平台无关的服务上,如拥抱脸的变形金刚或 TensorFlow.js 是最佳选择之一。您还可以构建一个定制模型,并使用诸如 TensorFlow Lite 或 OpenVINO 之类的工具将其部署在本地服务器或设备上。最后,您可以使用诸如 Flask 或 FastAPI 之类的工具用 web 服务包装情感分类模型。
您还需要确保训练和测试数据预处理阶段是相同的,以便做出准确的预测。您不能期望您的模型在生产中产生与在培训中产生的结果相同的结果。一些问题如模型漂移和数据漂移会导致模型性能不佳。这就是为什么您需要在部署后的几个月中监控整个解决方案管道、数据质量和模型性能。
这种监控可以告诉您您的模型是否按照预期执行,或者您是否需要重新训练模型以获得更好的性能。像多米诺、超智 AI 、阿里泽 AI 等工具。,可以帮助您确保生产中的数据质量,并帮助您使用仪表板监控情感分类系统的性能。
结论
读完这篇文章后,您现在知道什么是情感分类,以及为什么组织关注这个用例来增加他们的业务。虽然有不同的方法来进行情感分类,但是基于变压器的模型在这个领域中被高度使用。您已经看到了为什么 BERT 模型是情感分类的正确选择的不同原因。最后,您已经看到了我在处理这个用例时遇到的不同挑战和学到的东西。
从头开始训练一个 BERT 模型或者为嵌入生成对它进行微调可能不是一个好主意,除非您有足够的数据量、良好的硬件资源和预算来这样做。相反,尝试使用不同的预训练模型(如果有的话)进行相同的操作。这篇文章的目的是向你展示我所面临的不同问题和我所学到的知识,这样你就不需要在同样的问题上花费太多的时间。尽管由于模型和库版本的变化,您可能会面临一些新的问题,但是本文涵盖了所有问题中最关键的问题。
参考
- https://www . semantic scholar . org/paper/Attention-is-All-you-Need-vas Wani-sha zeer/204e 3073870 FAE 3d 05 BC C2 f 6 A8 e 263 d9 b 72 e 776
- https://analyticsindiamag . com/how-do-zero-shot-one-shot-and-less-shot-learning-different/
- https://huggingface.co/
- https://ai . Google blog . com/2020/08/language-agnostic-Bert-sentence . html
- https://neptune.ai/blog/tips-to-train-nlp-models
- https://docs.neptune.ai/tutorials/monitoring_training_live/
- https://Neptune . ai/blog/how-to-monitor-your-models-in-production-guide
用 Kuba Cieś lik 构建可视化搜索引擎
原文:https://web.archive.org/web/https://neptune.ai/blog/building-visual-search-engines-with-kuba-cieslik
这篇文章最初是 MLOps Live(T1)的一集,这是一个互动的 Q(T2)环节,在这里,ML 从业者回答来自其他 ML 从业者的问题。
每集都专注于一个特定的人工智能主题,在这一集里,我们采访了 Kuba Cieś lik, tuul.ai 的创始人兼人工智能工程师,讨论了构建视觉搜索引擎的问题。
你可以在 YouTube 上观看:
视频
或者作为播客在以下位置收听:
但如果你更喜欢书面版本,这里有!
您将了解到:
1 什么是视觉搜索?
- 2 视觉搜索和 OCR 有什么不同?
- 设计视觉搜索引擎时要记住的事情
- 视觉搜索中嵌入的重要性
- 5 视觉搜索引擎评测
- 将视觉搜索引擎与其他产品整合
- 7 构建可视化搜索引擎的基本工具栈
- 8 扩展视觉搜索系统
- 9 …还有更多!
- 好吧,我们开始吧。
**萨宾:**大家好。欢迎来到 飞行大队李 ve 。我叫萨宾,和我一起的是我的搭档主持人斯蒂芬。这是今天与我们嘉宾的互动问答环节,他是构建视觉搜索引擎的专家。首先,我很荣幸向您介绍我们的嘉宾,机器学习和数据科学工程师 Kuba Cieslik 。欢迎你库巴。你愿意简单介绍一下自己吗?
**库巴:**当然可以。大家好。很高兴能参加这个活动。我是一名机器学习工程师,在构建 ML 产品和 ML 解决方案方面有几年的经验。碰巧的是,在过去的一两年里,我专注于构建视觉搜索解决方案,总的来说,计算机视觉是我在这个领域感兴趣的主要话题。
萨宾:你现在在做什么事情?
目前,我正在研究一个非常有趣的话题,至少,每当我把这个话题告诉别人时,都会激起一些兴趣。本质上,我在研究动物的面部识别。你可以想象自己在用手机,它能认出你。现在所有的手机都有这种功能,它们可以根据摄像头或面部摄像头识别你,本质上是我们试图为动物建立的类似功能,在这种情况下,跟踪动物变得更加重要。
在某些情况下,使用 NFC 标签等其他技术手段并记下现在正在使用的东西是不实际的,不管出于什么原因,我们现在已经有了这种技术,或者我们希望将这种技术提高到我们能够从单张或多张照片中识别动物个体的水平。
什么是视觉搜索?
萨宾:好吧,很酷。不是让你为难,但如果可能的话,我们希望你能在一分钟内解释一下视觉搜索。这是一个挑战。
**库巴:**对我来说,我会把这个问题当成任何搜索问题。
每当我们想到搜索某样东西时,我们都想检索相关信息,通常,这是通过文本来完成的,至少,这是我们习惯的方式,或者我们习惯的方式,但本质上,视觉搜索只是这个问题的一个子集,它使用特定的视觉信息。它可以是视频,可以是图像,可以是图画,不管它是什么,对人类来说,它是一个视觉的东西。这就是问题所在。
萨宾:好吧。我认为那确实在一分钟之内。干得好。
视觉搜索引擎用例
Stephen: 很有意思,库巴,你在视觉搜索和搜索引擎方面的想法。我就从高层次来说,你今天看到的人们通常使用的视觉搜索引擎的一些例子是什么,他们不知道它背后的技术是什么?
我认为这项技术现在开始越来越流行,而且也越来越好。例如,我认为这种技术带来惊人效果的主要例子实际上是谷歌镜头,这是最常用的,也可能是最先进的技术,当然,这是一种非常重要的销售方式和营销方式。你基本上可以指向任何东西并给它拍照,谷歌会试图找到它并把你重定向到你能买到它们的地方,当然,这是开发它的一个非常重要的原因,但还有其他事情。
肯定有所有这些视觉搜索引擎,Pinterest 非常擅长这一点,本质上他们围绕这种只是去看看的沉浸式感觉建立了一个产品,你不必键入 match,你只需点击任何对你有吸引力的东西,然后它会尝试向你建议你可能想要的东西,因为最终,意图是非常微妙的。
当你搜索一张图片时,很难理解它的意图。你对图案感兴趣吗?你是对这个物体本身感兴趣,还是可能是完全不同的东西?通常,为了用视觉搜索做出好的搜索,你通常还需要一些关于用户想要什么的上下文。
我会说。但是,当然,就像其他光谱上的其他事物一样,比如面部识别,它们是完全不同的,在那里你本质上只有一个有效的答案,你有一个验证或识别问题,这项技术依赖于问题的另一个光谱,但是用来解决它的技术实际上是非常相似的。
视觉搜索和 OCR 有什么不同?
斯蒂芬:好的。仍然在高层次上,再次,我认为视觉搜索引擎的方式,我认为更像是不同技术的组合,这可能像 OCR 技术,所有这些技术。我这样想是不是错了,或者有哪些不同的技术实际上可以组成一个可视化搜索引擎?
Kuba: 我不确定我是否明白你的意思,但我认为在组合多个东西方面,那么往往你想要的实际上是使用多模态信息,你也使用提供的文本,这是上下文信息,然后搜索,然后是视觉部分本身。我不确定,也许你可以就这个问题详细说明一下。
斯蒂芬:好的。我的意思是,比如 Google Lens,我们把 Google Lens 也算进去吧。当我想到 Google lens 时,作为一个初学者,当然,我会将 Google 视为后台发生的一些 OCR 类型的技术。我们是不是说,为了建立一个合适的视觉搜索引擎,必须有 OCR 技术,然后必须有一些视觉技术?
Kuba: 我认为 OCR 对许多解决方案都很重要,例如,也许你们中的一些人知道有一个叫 Vivino 的应用程序用于葡萄酒标签扫描,你可以通过两种方式来完成,你可以解决将葡萄酒瓶与你想要找到的实际瓶子相匹配的问题,你可以通过 OCR 技术来帮助自己,所以实际上阅读瓶子上的文字可以帮助你,对吗?
如果有一些文本,可能会这样,但是当然,有没有文本的标签,并且在大多数情况下,拥有组合解决方案或后备解决方案是非常重要的。这就是我所说的,当我说这很少是一个纯粹的视觉问题时,通常是一个视觉加一些东西的问题,大多数情况下,不像那些识别验证问题,实际上没有任何其他背景。
斯蒂芬:好吧。明确一下,视觉搜索技术和 OCR 技术的区别就在于它的上下文,理解图像的上下文,是吗?
**库巴:**是的。嗯,实际上是看图像,因为 OCR 只是用来实际查找文本,然后尝试对文本做一些事情。当我们训练模型通过视觉理解来对网络进行视觉理解时,我们想要的不仅仅是这些,我们想要在图像中找到特征,找到联系,这些图像不是那么清晰,也不可能用文本来描述。更重要的是,我们没有世界上大多数图像的文字。
什么是三联网络培训?
Sabine: 好的,我想我们有空间回答来自社区的问题。这对我来说是新的。这些三元网络你的基线三元网络训练是什么?使用它时,人们可能希望注意什么?
**库巴:**三连音训练是一种特殊类型的公制学习。这是度量学习的一部分,我们试图学习一个度量函数,这通常是通过比较两个事物来实现的。例如,对于人脸,我们可以训练这样的模型,你展示一个网络,就像同一个人的两张照片和另一个人的第三张照片,然后一个模型将学习在同一个人的一些空间中保持接近图像,并将其推离其他图像。
实际上有很多很好的框架,我想到的是——特别是在 PyTorch 中,我用得最多的是 PyTorch 度量学习,是的,它实际上实现了新解决方案步骤中的大多数创新,你可能会——新论文或新损失函数,无论你想要什么。我真的推荐它,它非常好,也许我们稍后会添加一个链接,但它会在那里。
设计视觉搜索引擎:要记住的事情
Sabine: 你有什么关于视觉搜索的小技巧吗,比如清单之类的?
**库巴:**对,一个清单。我想我真的会弄清楚问题到底是什么,正在解决什么,以及如何设置它,因为有些事情我们可能想从学习三重学习网络中学习,有些事情我们可能需要从纯无人监督的方式或从排名标签中学习。我认为,最终,它归结为从图像中学习有意义的特征的问题,以及这些特征实际上应该是什么,因为这是非常具体的问题,对吗?
很多时候,搜索引擎就像是通过一个预先训练好的网络传递一些图像,然后从中产生的特征会对这个数据样本进行聚类,这是真的,但如果它按照你认为它应该的方式进行聚类,那就是另一回事了,对吗?例如,如果网络是在 1000 个类上训练的,我的意思是,它在对不同类型的对象进行分组方面很好,但在区分它们方面不会很好,所以使用这种预训练网络的模型可能不是最棒的,例如,对相似的服装进行排序或试穿,这么说是因为它从未真正理解不同类型服装的概念。
它可能仍然非常有用,但大多数时候,我们想要从中获得的这种类型的附加信息,至少需要新的数据和附加标签。这是棘手的部分,这将是主要的考虑因素,但当然,如果我们对某个问题了解得更多,那么我们就可以想得更多。
Sabine: 但你仍然会根据新数据对预训练进行微调,对吗?
**库巴:**可以,当然可以,可以。使用预先训练好的网络几乎总是可行的,对吗?而不是从零开始,所以这是肯定的。
嵌入在视觉搜索中的重要性
斯蒂芬:库巴,我很想插话。我认为嵌入在这个领域非常非常重要,当然,在构建可视化搜索引擎的时候。在你看来,在处理视觉搜索引擎技术时,好的和主题相关的嵌入的重要性是什么?
Kuba: 我认为这只是我之前所说的一点,即它是针对特定问题的,尽管一些非常通用的搜索引擎可能看起来不是这样,但如果我们想要建立非常具体的解决方案,我认为这就是现在正在使用的方法。例如,如果我们想要对时尚有好的建议,那么我们需要专注于它,甚至非常具体地专注于某一种服装类型,以使它正确。
举个例子,在我的工作中,同样的事情发生了,如果你只是使用预先训练好的网络来做牛脸的嵌入,那么它根本就不能工作,对吧,因为这样的网络没有理由去学习区分一个牛和另一个牛的东西,人脸也是一样。这就像我们现在拥有的运作良好的 Face ID 技术。
它之所以有效,是因为它是在十亿张脸上训练过的,所以这就是为什么它是相关的。这并不像你有一个神奇的方法来创建一个在各种情况下都能很好工作的嵌入,你需要以某种方式控制它。
为视觉搜索训练良好的嵌入
斯蒂芬:是的,我只是很快地跟进一下,这些情况下你有标签,你在面部训练,你有标签。我认为有相当多的用例,你不能像你希望的那样访问标签。在没有标签的情况下,你如何训练一个非常好的嵌入?
**库巴:**有,无标签。是的,这是个好问题。没有标签,当然,你的选择有限,对不对?假设您有一个用例,与您通常在数据集中找到的图像相比,它非常新。例如,来自工厂的东西可能是一些数据量有限的用例,那么我认为当前的方法,特别是在不断增长的自我监督学习领域,在这里非常有帮助。
你实际上可以用一种自我监督的方式来改进嵌入和训练嵌入。本质上,你只需要收集数据,然后网络,有不同类型的工作方式。自我监督学习是如何工作的。就像最直观的,最直观的方法一样,它们已经不怎么被使用了,但我认为出于解释的目的,它们更好。
例如,你训练一个在图像中显示间隙的网络。你切掉缺口,然后你告诉,“是的,缺口里有什么?”或者你让网络给图像上色,这也是你可以自我监督的事情,然后希望从中学习一些东西,但是新的方法,他们使用了一点更复杂的技术。举例来说,你基本上处理成对的图像,其中一个由于增强而有点畸形,然后你试图学习对于技术上不同的图像来说是相同的嵌入。
这对网络来说非常具有挑战性,因为它必须理解图像的内容。是的,用这样的嵌入进行训练,使用这样的嵌入,肯定会提高分数,或者不管你的问题是什么。是的,但这也有不好的一面。没有多少人大规模使用它,他们通常很难训练,自我监督的网络也没有融合。他们有很多诡计,我会说这是最后的手段。
视觉搜索引擎的评价
斯蒂芬:这看起来确实是一个很难解决的问题。评估过程是什么,你如何评估你训练的这个特定的模型或这个特定的问题,你在某种程度上满足了那些要求?
是的,我认为这尤其取决于你有什么问题。如果这是一个排名问题,那么,当然,你有一些方法给正在发生的事情打分。例如,我会假设视觉搜索,如 Pinterest 或 Google Lens,肯定可以标记它,并且可以有一些基本事实。你知道点击了什么或者用户点击了什么吗?在识别和再识别等领域,我们通常只使用最高的准确度。这是最重要的因素,因为如果你是一次性的,在大多数情况下,这是没有帮助的。没关系。很多时候,是不对的。这将是重要的事情。
将可视化搜索引擎与其他产品集成
Lev 想知道,Kuba 是否认为以一种直观的方式将像 Google Lens 这样的视觉搜索与其他应用程序和产品集成已经恰当地发生了?有什么想法吗?
Kuba: 整合像谷歌镜头这样的东西,并制造一种产品,从本质上来说,我认为许多公司肯定会试图改善他们的购物体验,这肯定会发生,而且很流行。甚至像 H & M 这样的大型时尚公司也在他们的应用程序中加入了这一功能。当然,他们没有与谷歌镜头集成,他们有一些内置的解决方案来解决这个问题,但他们有一些解决方案让你扫描一些东西并查询他们的库存。这肯定会发生,这看起来是一个非常有效的用例,具有很高的价值,货币价值。
视觉搜索引擎在生产中的问题
Sabine: 当你把视觉搜索用于生产时会怎么样?需要注意的是,你在那里面临的一些常见问题是什么?
当然,最大的问题之一是你需要意识到改变模型的成本是很高的,我认为,这比正常的机器学习的成本要高一些,因为正常的机器学习如果你改变了模型,那就是推荐。那么对于未来的推荐,你用一个新的模型,不一定要为了过去而改变,或者你为了过去而重新计算。
对于视觉搜索,每次你想使用一个新的模型,你必须重新计算所有图像的所有人员。想象一下,大规模地做这件事,我不知道,例如,谷歌是如何做的,或者他们的引擎多久做一次,或者如果有,我很难讲。这绝对是你需要注意的事情。
如果你改变模型,它将改变嵌入。然后他们大部分时间就变得不可比了。这是关键的一步,当然,还有一个大问题,特别是在大规模的应用程序中,就是数据库的大小。如果你在数百万张图片中进行查询,也许这没什么大不了的,但是在数千万张图片中进行查询可能会成为一个问题,并且可能会很快变得昂贵。
有很多方法可以缩小范围。你通常不需要也不想和所有的东西做比较。我敢肯定,如果我使用谷歌镜头,他们会给我安装一个特殊的过滤器,因为他们已经知道我的所有信息,他们不必扫描所有照片。是的,这绝对是非常非常关键的两件事。
构建时尚的可视化搜索引擎
Sabine: 你自己有过为时尚构建可视化搜索引擎的经验吗?
**库巴:**是的。我研究了一些解决方案,试图从 Instagram 中挖掘信息。本质上,理解并建立一个可视化的搜索引擎,搜索我们从 Instagram 中挖掘的数据。这是一个非常有趣的用例,因为 instagram 通常是不可搜索的。你可以通过标签进行基本的搜索,仅此而已。如果你想在数百万或数千个 Instagram 个人资料中进行搜索,即使是基本的文本搜索也无法真正发挥作用。我们挖掘这些数据,然后通过一些管道进行可视化搜索。
例如,如果你想用某件衣服和一件衣服的图像来查询数据库,我们想看看谁发布了符合这一点的东西。出于各种原因,这当然很重要。负责产品营销、购买和定价的人员。社交媒体在很多情况下都很重要。
我们在其他领域也这样做。社交媒体监控现在只是暂时的事情。社交媒体监控,说到时尚,也是现在的事情。例如,有些公司只做这些。
Sabine: 在 Oluwa Sim 的聊天中,我们有一个关于这个时尚项目的问题。如果你能告诉我们更多的信息,你能解释一下你使用视觉搜索来部署那个时尚项目的过程吗?
**库巴:**大致来说,有两个组成部分。现在相关的组件是索引部分。这是因为,当然,其中一部分是在挖掘和搜集数据,然后将数据输入到一些数据库中。每当一张新图片出现时,我们实际上会运行检测来检测图片上的某些服装类型,因为如果你在 Instagram 上想象一张时尚图片,它通常会有多个项目。很难建立一个对时尚有全球性理解的系统,而我们却没有。
当然,也有公司致力于为你推荐一套服装,或者这件衣服是否适合你,但这是一个不同的问题。在我们的例子中,我们有模型做检测和分割,首先是物品。这些物品可以是裤子、连衣裙、帽子、t 恤等等。到最后,服装的种类就没那么多了。如果你仔细想想,我认为它们是 18 个封面,非常多的服装。
然后这些是从图像中提取出来的。你可以把它想象成一幅图像被分割成 N 幅图像。然后你需要跟踪并保存那些分段的部分。您还需要存储那些单独项目的嵌入,因为您永远不知道最终将如何检索它们。也许您只是针对某个类型运行查询。
例如,如果有人想在所有这些图片中找到一件相似的衣服,那么您将选择我正在寻找衣服,并且您将只在这个索引中寻找嵌入。我们可以缩小范围,但也许不行。也许可以扩大搜索范围。本质上,如你所见,一旦你挖掘了一张图片,以后,它可能会变成比这张更多的数据。这是需要注意的事情。
当然,也有不同的策略。你可以把不同事物的嵌入结合起来,得到这个时尚小时的全球描述符。最后,这是一个创建数据湖的过程,但对于图像,您可以。你还不知道你将如何使用它。您希望轻松访问它,并且不希望重新计算,因为运行分割和检测模型实际上是管道中最昂贵的时刻之一。你先做一次,然后再考虑什么样的解决方案可行。
Stephen: 还是关于时尚行业的使用案例,我认为 Andrea 在 YouTube 上提出了一个很棒的问题,从软件工程的角度来看,你是如何将你的图片从 Instagram 不同的图片抓取到视频训练集的,这个过程对你来说是什么样的?
**库巴:**对,这个问题问得好。这个项目已经做了很长时间了,我不确定这是否仍然有效,但我会直说,因为 Instagram,当然,不喜欢抓取和挖掘,他们会反击你,但通常最简单的方法就是使用一个池,怎么叫呢?它们被称为 HTTP 代理。你实质上是出租服务,通过世界上不同的地方代理你的请求。
从工程的角度来看,这实际上很容易,因为他们给你一个端点,你可以通过它重定向所有的流量,通常,有服务做得很好。你可以向这个特定的用户发出一个请求,他们会通过中国或其他国家的服务器重定向这个请求。他们会继续这样做,继续保持平衡,继续使用不同的服务器。
这种情况一直持续到 Instagram 的 API 完全关闭。我想这仍然有效,对吗?我的意思是,唯一不起作用的是,如果有私人帐户,你不登录就无法访问,那么,当然,它会工作,但如果你需要登录,那么你就有问题了。我们的直觉是,我们想要获取数据的账户是开放的,因为它们来自其他公司,来自有影响力的大公司,他们不想让自己的账户成为私有账户。
训练视觉搜索模型的最大挑战
**斯蒂芬:**牛逼。我认为我们有一个来自社区的非常好的问题,这也是我一直在想的,来自 Mashhad。我希望我把你的名字念对了。不管怎样,这是个很好的问题。比如,你在为视觉搜索模型训练模型时遇到的最大挑战是什么?你有没有尝试用一些新的技术来对抗它们?就计算机、你使用的技术等等而言,你在寻找什么?
**库巴:**我明白你的问题了。
我不知道我是否能回答这个问题,因为这是一个非常非常宽泛的问题,但我认为最重要的是,像往常一样,就像几乎所有的计算机视觉和机器学习一样,数据,对吗?获取正确的数据通常是最大的挑战。如果你在收集数据,那当然是一个问题。
如果你没有,如果你已经有数据,那么以正确的方式标记数据,如果是半标记或者如果是通过标记人来标记,那么这是你真正认为需要思考很多很多的关键步骤。我的意思是,因为如果你做错了,代价会很高,这是我能给的最好的建议。因为以后的训练,取决于我们谈论的模型。
例如,三元组和这种类型的三元组、四元组或连体类型的网络相对难以训练,因为它们存在以正确的方式对三元组进行采样的问题。数据集中的类越多,问题就越严重,但它们是针对非常大的数据集的。这就是你必须使用的,如果你有相当大的数据集用于学习良好的嵌入,你可以从本质上选择的是用于面部检测,面部识别,面部识别的网络,所以 DeepFace,ArcFace,CosFace。
它们是像分类网络一样被训练的网络,但是在损失函数中,你实际上学习到的嵌入比使用常规交叉熵分类更大地分离它们。这些都非常有效,你可以看到,例如,通过检查最近比赛中的地标识别,例如,在 Kaggle 上,它们也在那里被使用,在这场比赛中数据集是巨大的。
这项用于面部识别的技术实际上基本上是一样的,基础也是一样的,当然,像往常一样,在 Kaggle 上,有很多诡计在上面进行,但基础是面部识别技术应用于地标匹配的问题。从外部来看,这似乎是一个完全不同的问题,但解决方案是相同的,并且非常非常有效。那些 ArcFace CosFace 网络,它们实际上相对容易训练,不像交叉熵分类那么容易,但是接近它。
为视觉搜索选择训练架构
斯蒂芬:我有两个后续问题,如果我错了,也许你可以纠正我,我在想,你如何选择,比如说,你如何决定你要训练的训练架构,因为我假设你要处理大量的数据集。因此,当您处理大型数据集时,您如何确定训练过程是什么样的呢?
Kuba: 我认为,就像这里一样,当谈到训练和这个问题时,特别是当我们谈论这个 ArcFace 或类似分类的网络时,最终,你有多少个标签,所以假设你的数据集中有一百万个 id 或人或地标。这意味着你的最后几层在网络中变得越来越大,如果它们不适合一个模型,你就无能为力,然后你在多个设备上分割模型,你仍然要继续训练它。
如果人们不得不在数百万个 id 上进行训练,我会说,这已经很重要了,但其他网络,如果你想学习,更多地采用这种三胞胎训练的度量学习方法,那么就没有限制。我的意思是,最大的限制将是批量大小,这不一定是疯狂的大,但你没有这么大的模型,这是我的方式。
可视化搜索的数据转换方法
Stephen: 我们有几个来自社区的问题。我很想问一下,在这个领域,有没有比其他人用得更多的常见转换方法?
库巴:转变和什么?
斯蒂芬:根据你的数据论证过程等等。
库巴:我不认为这真的有什么作用。如今,你所看到的绝对是闪亮的,当谈到,例如,Kaggle,以我的经验来看,那些剪裁方法比以往任何时候都更受关注。它们也很新,所以本质上就像剪切图像的一部分,它们被使用得相当多,但除此之外,增强永远是你拥有的数据的情况。
例如,我使用的动物图片需要非常小心哪些没有意义,哪些转换有意义。如果你有大量的数据,那么你也知道你可以使用较少的增强。例如,对于这个地标,如果有人对正在发生的任何新事情感兴趣,我认为在视觉搜索和匹配方面,这些比赛真的是一个很好的学习资源,你可以看到在上次视觉地标匹配比赛中的增强非常小。他们使用非常基本和非常低的程度,扩增。
Stephen:Kuba,就在我们准备结束这个话题的时候,有没有我们应该寻找的矢量相似工具和解决方案的潮流,比如说景观?那研究角度是什么?目前那个领域的研究进展如何?
Kuba: 我的意思是,对于数据相似性,现在有很多解决方案,从一些付费开始,一些免费开源。他们都有一些报价,但其中一些是建立在现有的数据库之上。我想我会给任何一个刚开始做这个的人推荐的是,如果你没有达到你需要搜索的一些巨大规模的百万以上的向量,我认为那些使用你已经拥有的数据库的解决方案,最有可能,例如, Postgres 。
Postgres 中肯定内置了一个引擎,当然,它们不是官方的,但它们就像是使用一些数据库作为持久层的服务。如果它们符合您在堆栈中已有的内容,我会使用它们,对吗?因为将这些嵌入存储在其他数据所在的地方总是好的,因为这将为您提供更多的查询选项。
如果您的规模确实很大,并且您知道自己会回头,那么您可以购买托管服务并支付费用。然后你需要为每个指数付费。通常,对于每个索引和它在内存中占用的空间,因为大多数索引都是从 RAM 中运行的。您需要为大索引选择实例。
Stephen: 构建与购买的解决方案也是软件行业的一个话题。仅谈您的日常工作流程,您使用的基本工具堆栈是什么?你在构建一个可视化搜索引擎时使用的是什么技术?
我使用 Python 和 PyTorch,为了相似性,我想我现在尝试了大多数大的提供商,他们中的许多都很不错。从管理的解决方案来看,松果也是相当不错的选择。除此之外,对于日常工作,Python、PyTorch 和 Fast API 帮助我构建了我目前正在构建的大部分东西。
扩展视觉搜索系统
Stephen: 我认为另一个经常讨论的问题是,思考如何构建可以扩展到我们正在解决的任何问题的东西。从建立一个基线系统的方法,发展到能看到很多用户的方法,比如说,可能不是谷歌的规模,雅虎的规模,必应的规模,或者类似的方法,而是对用户有用的方法。如何从仅仅构建概念证明过渡到可扩展的东西?
Kuba: 我认为概念证明是,我会说,让我们假设概念证明可以是一个简单的东西,你把你的笔记本,你的嵌入索引实际上是在 NumPy 的内存中,你只需要用一个查询做一个点积,就这样。这可能是你非常非常基本的情况。然后,无论何时你移动,你都需要考虑诸如你将如何开始在模型本身上工作之类的事情,你需要继续考虑持久化和更新嵌入。
每当你发布一个新的模型,你需要慢慢地工作,最终,你拥有的管道,当然,如果你达到一个非常大的规模,那么你需要考虑这个问题的所有可扩展性问题。但是有解决方案可以帮助你。无论管理与否。例如,有一些矢量搜索引擎,你可以把它们部署成一个导航图,你已经准备好了。你有自己的服务可以集成,这当然是一种方式。
但我认为规模、查询大小或其他数据集可能更重要,因为它们将决定您需要重新计算所有内容的次数和频率,这很好。
其他问题
Sabine: 在聊天中,Lev 问了我们一个问题,如果你熟悉的话,谁想知道 Kuba 觉得 Beams 视觉搜索与 Google Lens 匹配如何?
**库巴:**这个问题问得好。我真的不知道。我认为梁已经在这里一段时间了,但是的,谷歌一肯定,这是非常好的。这真的很神奇,因为最近,我想在一家我非常喜欢的酒店里找一把椅子,在世界上所有的椅子中,我第一次就找到了,我觉得这太令人印象深刻了。
是的,我们这里有一些用户在聊天中寻求建议。我们有 Chimobe 询问关于建立一个在线市场平台的图像验证系统。
我会试着找出这可能是什么问题。我在市场上看到的一个问题是,比如说,你在易贝或其他地方可能会遇到的问题是,类别的数量不是恒定的。这是一个有效的问题,因为如果它不是常数,这意味着你不能只使用简单的分类,因为否则,我会说,“好吧,我在卖一个被分类为板的板,”然后它在一些 UI 中有所帮助。
对于一个新的类别,你不会马上支持它。如果您使用任何度量学习或相似性方法,您可以做的是您将只需要一个新类别的实例。如果有人问什么,她没有找到类别,但她把它放在价值类别或一些精彩的经理,网站做到了。然后,我们有一个与新类别相关联的图像。
这就是一次性学习的典型问题。然后我们可以通过良好的嵌入来做到这一点。我们要做的不是把它作为一个分类问题,而是在未来,我们会把一张新图片和所有类别的图片进行比较,选择最接近的一张。那么你就解决了类别数量变化的问题。这是我在市场上看到的问题,但也许这个人可以详细说明这是什么意思。
Sabine: 是的,我们有和我们一起通话的人。
好吧,我问的是你有,就像亚马逊一样,人们上传他们产品的图片,他们在网上卖什么。现在有些人可能会犯错误,或者他们可能想上传一台笔记本电脑,然后他们将这台笔记本电脑命名为一个人,这是一种误导。现在,我们如何验证这些上传,知道有 N 个产品,但我们不知道这个人在特定时间可能上传的特定产品是什么?这是不是意味着我们必须不断下载产品类别才能得到这样的结果?
**库巴:**好的,我理解问题是说一个用户选择了一个类别出错,然后图片没有在反映这个类别。是这种情况吗?
Chimobean: 对,对。现在,产品类别正在为此使用机器学习模型,这意味着我们必须下载各种图像来进行验证,以训练我们的模型。
Kuba: 我正在想办法弄清楚我是否得到了问题。在这种情况下,你说的下载是什么意思?我的意思是,因为在我看来,这要么是一个分类问题,要么是比较问题,所以是相似性问题。如果您已经为该任务训练了模型,那么您可以根据类别来验证输入。我不确定我是否理解了这个问题。或许有人对此有看法?也许有人对此有不同的理解。
Sabine: 这可能是一个如何着手建立数据集的问题,你需要首先训练模型并验证它们?
Chimobean: 是的。我们要从不同的类别中获取数据吗?明天,有人可能会出现并上传一个可能不在我们数据中的类别,一个我们的模型没有训练过的特定产品。这就是我要问的。我们现在如何验证这一点?
库巴:我想这是我之前说过的,现在仍然有效。最后,对于固定数量的类,您可以对不固定的类进行分类。在你的情况下,本质上是类别,然后你会本质上找出这个新图像的嵌入,你会看到它不太适合任何类别,或者距离会很远,然后你可能会打电话,“嘿,也许这个类别和这个图像之间没有匹配。”我认为,这将是一个有效的方法。
把它包起来!
斯蒂芬:当然,我想我们的时间不多了,但这真的是一次很好的谈话。我认为你可以继续留在 MLOps 社区。听众和观众们,如果你们还没有加入 MLOps 社区,你们可以在这里加入。
萨宾:是的,我们今天就要结束了。如果你的问题没有得到回答,也不用担心。你可以在计算机视觉频道或 neptune.ai 频道随时联系我们。非常感谢每一个提问的人,也非常感谢库巴加入我们,回答我们所有燃烧的视觉搜索问题。我们将在两周后带着我们的下一集 MLOps Live 回来。两周内,我们将邀请雅格布·塔利亚布埃来讨论所有合理规模的事情。
Sabine: Yes, we’ll be wrapping up here today. No worries if you didn’t get your question answered. You can always reach out to us on slack in the Computer Vision channel or in the neptune.ai channel. Thank you very much to everyone who asked questions, and thank you very much, Kuba, for joining us and answering all our burning visual search questions. We will return in two weeks with our next episode of MLOps Live. We will be having Jacopo Tagliabue on to discuss all things reasonable scale MLOps, in two weeks.
Neptune.ai 入选 2022 CB Insights AI 100 最有前途的人工智能初创公司名单
原文:https://web.archive.org/web/https://neptune.ai/blog/cb-insights-100-most-promising-ai-startups
自从我宣布我们已经筹集了 800 万美元的首轮融资才过了几个星期,现在我带来了更多的好消息。
Neptune.ai 已被提名为 2022 年 CB Insights AI 100 最有前途的人工智能初创公司名单。我们在实验跟踪和版本控制类别中得到了认可。
CB Insights 团队从 7,000 多家公司中挑选了 100 家私营市场供应商。他们是根据包括 R&D 活动、专有马赛克分数、市场潜力、业务关系、投资者概况、新闻情绪分析、竞争格局、团队实力和技术新颖性在内的因素选择的。
在前 100 名中有很多伟大的创业公司——祝贺他们!我不禁注意到,只有几家公司来自欧洲,所以我很高兴海王星是其中之一。
很高兴在列表中看到我们的一些客户和用户(例如 InstaDeep 团队,我们甚至有机会与他们一起创建了一个案例研究)。
被 CB Insights 关注是一种激励,但对 Neptune.ai 作为一家公司也很重要。去年我们第一次登上报告后,来自世界各地的 100 多家风投公司找到了我们。它在筹集最后一轮投资时帮了我们很大的忙。
而对于海王星用户来说又意味着什么呢?
您可以预期我们将利用这种认识来开发我们的工具,并创建更好的开发人员体验。这包括:
- 更快的反馈到特征循环,
- 改进了我们的网络用户界面体验,
- 与 MLOps 生态系统中的工具进行更多集成,
- 更好的文档。
过去几周对我们来说特别好。但我相信我们不会慢下来。
我们将更加努力地工作,继续让实验跟踪和模型注册为世界各地的 ML 团队“工作”。
数据科学家和 ML 开发者的 ClearML 替代方案
原文:https://web.archive.org/web/https://neptune.ai/blog/clear-ml-alternatives
端到端 MLOps 工具是一个大杂烩。我们中的一些工程师喜欢一个工具,它连接每一个资源、插件、集成、ML 操作,并使这一切自动化。其他人则不然。
ClearML 是一个流行的端到端平台,在一个统一的环境中连接所有的数据科学工具。这是一套开源工具,用于自动准备、执行和分析机器学习实验。实验管理工具跟踪参数、作业、工件、指标、调试数据、元数据,并在一个清晰的界面中记录所有信息。这是一个拥有一切的重量级工具。
微软、脸书、英特尔、三星、亚马逊、索尼和英伟达等科技行业巨头使用 ClearML 来运行他们的机器学习和数据科学业务。但是这就使得 ClearML 成为最佳选择了吗?
在这篇文章中,我们将探索为什么大公司的工程师喜欢 ClearML,并分析 10 种工具,它们为要求苛刻的 ML 工程师或数据科学家提供不同级别的功能。
什么是 ClearML?
ClearML 消除了与整个机器学习生命周期相关的耗时且容易出错的任务。ML 开发者和数据科学家可以只关注数据和训练。
它跟踪我们记录工作、可视化结果、重现、调整和比较实验所需的一切。因此,我们可以实施自动化工作流程,如超参数优化和其他管道。
基于 Python 的 ClearML 包支持:
- frameworks like TensorFlow/TensorBoard, PyTorch, Keras, Fastai, Scikit-learn.
- 图书馆(熊猫、Plotly、AutoKeras)。
- 可视化工具(Matplotlib,Seaborn)。
- 存储(文件系统、S3、谷歌云存储和 Azure 存储)。
我们可以使用托管服务并部署一个自托管的 ClearML 服务器。它通过用于实验、显式报告、工作流自动化、优化(Optuna、HpBandster、random、grid 和自定义搜索策略)、模型和存储的类来改进 ML 开发。
ClearML 的三个最突出的特性是:
- ClearML 编排,
- ClearML 功能存储,
- 和 ClearML 部署。
ClearML 编排
ClearML Orchestrate 在一个简单的仪表板中为数据科学团队提供了对计算资源的自主权和控制权。它管理资源和集群分配,无需专门的 MLOps 团队成员。编排工具旨在根据您的需求进行扩展,它可以动态扩展以容纳数千个 GPU。它从基础架构中抽象出工作负载。您只需进行初始设置,然后工具会自动控制所有流程。您可以通过简单的界面自助安排我们自己的资源。您可以完全控制成本和 AI / ML 工作负载,使用作为完整 ClearML 套件一部分的工具。它保持高利用率,并在本地或云中节省资金。更不用说,它管理云爆炸,在我们需要时提供计算能力,同时控制成本。
ClearML 功能存储
ClearML 的特性库,加上自动化管道,使得 ML 操作速度超快。您可以在几分钟内为结构化和非结构化数据构建管道和实验。只需插入 ClearML 特性库,并添加一个简单的方法来管理和迭代 ML 实验的特性。只需几行代码就可以集成商店。结果可以组织结构化和非结构化的 DL 和 ML 操作。您可以接收任何类型的数据,包括图像和视频、激光雷达、音频、物联网传感器、前视红外等。将您的结构化数据源与基于传感器的数据相集成,以实现更全面的人工智能建模。
ClearML 特征库处理将任何来源的结构化和非结构化数据纳入特征库的所有工作。灵活性是巨大的。ClearML Orchestrate & ClearML Experiment 与特性库相结合,创建一个集成的数据反馈循环,根据真实世界的数据重新训练部署的模型。可以轻松地在生产环境中提供和部署特性。您还可以监控破损和漂移,这会对使用时间旅行/数据版本控制的精确训练数据集产生积极影响。
ClearML 部署
ClearML 将模型部署到任何环境中,并提供对它们的完全控制。Deploy 模块与 Experiment 和 Orchestrate 相连接,形成一个任何人都可以使用的完整工作流。它提供了广泛的工具来部署模型。只需单击一下鼠标,即可修改要部署的目标环境。它处理所有部署操作,因此您可以专注于训练准确的模型。借助 ClearML,您可以使用自己喜欢的工具和配置轻松地跨云、内部和突发环境进行部署。当我们可以运行实时测试时,管理基础设施对我们来说太酷了。我们可以简单而重复地运行和部署关键的 ML 应用程序。该模块为任何规模的部署提供了模型消耗、呼叫详细信息和服务器使用的完整可见性。通过与 CI/CD 集成,ClearML 可以灵活、动态地伸缩。
这对你来说很清楚。但并不是所有人都在 FAANGs 工作或使用 ClearML。即使您这样做了,有时您仍然可能需要其他工具。
因此,这里有 10 个工具可以作为 ClearML 不同部分的很好的替代品。
1.算法 a
Algorithmia 是一个企业 MLOps 平台。您可以使用它快速安全地交付模型,以便数据科学家可以专注于机器学习过程。Algorithmia 可以快速迁移生产的所有需求和流程,并以经济高效的方式完成。
说到模型部署,它支持多达 3900 多种框架和工具。它与 ML 开发的现有工具和技术栈一起工作。您可以在任何想要的地方部署您的模型——在云中、本地或混合环境中。
它涵盖了 ML 生命周期的所有阶段,并且自动化了部署和正确的版本控制。它还促进了支持性能监控需求的度量管道,并与监控、报告和警报工具相集成。
2.Cnvrg.io
如果您正在寻找一种替代方案,能够提供端到端的机器学习管道,并以最佳的可扩展性自动化模型构建和部署,那么 Cnvrg 就是您的合适平台。
Cnvrg 衡量机器学习从研究到生产的发展。它在一个地方拥有机器学习过程所需的所有工具,因此该环境对数据科学家来说更具生产力。
它为科学和工程提供了统一的平台 UI,以进行协作并创建高效的机器学习开发环境。模型管理的自动化消除了技术复杂性带来的痛苦,因此您可以将更多精力放在数据科学任务上。
基于容器的基础设施简化了复杂的任务,如跟踪、监控、配置、资源管理、服务基础设施、特征提取和模型部署。您可以利用云和内部资源来构建企业就绪的机器学习模型。它通过模块化、快速实验和生产就绪型基础设施加速人工智能开发,并具有原生 Kubernetes 集群编排和元调度器。
3.瓦罗海
Valohai 是一款 MLOps 工具,它可以自动完成一切工作——数据提取、准备,一直到生产中的模型部署。您可以高效、方便地训练、评估和部署模型,无需任何额外的手动工作,然后您可以自动重复该过程。
Valohai 促进了自动存储模型、实验和工件的端到端机器学习工作流。它还管理 Kubernetes 集群中已部署模型的监控。
它具有超级稳定的 MLOps 环境、框架和工具适配、超参数扫描、团队协作环境、带防火墙的安全环境以及实验和模型审计。
开发人员和科学家可以专注于定制模型开发,而不是基础设施和手动跟踪。Valohai 加快了您的工作,并且还支持数据、模型和实验的自动版本控制。
4.多轴
Polyaxon 可以成为 Clear.ml 的完美替代品。它可以自动化机器学习操作和基础设施,以便使用生产级 MLOps 工具来重现、自动化和扩展数据科学工作流。它有一个加速的、迭代的研究和模型创建方法。没有手动的基础设施工作,实验更加方便,并且您有无限的框架和工具选择。还有一个交互式工作区,其中有笔记本、可视化和仪表板。
您可以通过协作空间、资源分配、版本控制和可复制性、数据自治、超参数搜索&优化、最大化资源利用率、强大的界面、可扩展的基础设施、模块化、可扩展性、成本效益等获得有效的用户管理。这是一个相当丰富的包。
5.迟钝的人
Pachyderm 是一个动态数据科学平台,利用 Kubernetes 上端到端的 ML 管道来利用数据谱系。它是开源的,具有最少的可用功能,还有一个高级企业计划,具有最多的功能。
您可以使用任何框架和工具来构建和部署 ML 工作流。您将获得一流的企业级支持、丰富的 UI 控制面板、高级统计数据、TLS、用户访问管理和定制部署。它专注于数据;为数据科学家提供可扩展且灵活的方法来利用资源并从事研究和实验。
整个平台框架基于容器,使得数据环境具有可移植性,易于迁移到不同的云提供商。该工具构建于 Kubernetes 之上,为您提供了一条实现持续 ML 流程自动化和监控的生产之路。
检查最佳的厚皮动物替代品
6.海王星. ai
Neptune 是一个集中管理所有建模元数据的平台,换句话说,我们可以称之为 元数据存储 。该工具记录、存储、显示、组织、比较和查询您的所有 MLOps 元数据。这是一个最先进的平台,用于跟踪机器学习实验、记录指标、分析性能图表等等。
你得到了一个集中的协作中心,以有机的方式组织团队合作。您可以自定义用户界面,并在云或内部环境中管理用户。快速轻松地控制用户权限和访问。为了提高效率,Neptune 监控硬件资源以优化代码,这样您的资源就可以得到最大限度的利用。Neptune 是高度可扩展的,可以与您喜欢的框架和工具集成。
在 Neptune 中,你可以记录和学习任何你需要的机器学习元数据,在统一的 hub 中组织实验和模型训练。轻松比较模型和实验,实时监控 ML 实验的执行。生产的模型是可追踪和可复制的。UI 非常丰富,包括团队协作、仪表板定制、结果可视化、共享、工作区和项目结构化机制。总而言之,这是一个非常酷的工具。
7.H2O
H2O 是一个开源平台,用于制作最先进的模型和机器学习应用程序。这是一个使人工智能民主化的端到端平台,为每个人提供复杂的人工智能技术和易于使用的人工智能应用。人工智能混合云为成千上万的用例提供了一个统一的平台。您构建的模型可从任何内部基础架构扩展到云基础架构。
H2O 服务和流程易于定制和扩展。这是一个高质量的免费工具,为您提供数据操作、各种算法、交叉验证、超参数调整的网格搜索、功能排名和模型序列化。无人驾驶人工智能通过使用自动化来帮助你更快更有效地从事机器学习项目。
它支持最强大、最动态的统计&机器学习算法。大数据的分布式处理通过细粒度并行提供了巨大的速度,从而实现了最佳效率。叫做 Flow 的图形化笔记本让我们不用编码就能建立模型,但是我们也可以使用像 R 和 Python 这样的语言。
8.数据机器人
Datarobot 是一个人工智能平台,可以加速和自动化机器学习过程,有效地将数据转化为价值。你可以准备数据,进行实验,然后建立和验证机器学习模型。也支持时间序列模型。
部署后,Datarobot 会执行监控即服务。随着大量模型、数据准备步骤和参数的快速迭代,整个模型开发过程变得更加简单和高效。集中式的人工智能 UI 平台推动了更好的机器学习结果。Datarobot 是可扩展的,我们可以使用具有完全托管服务的云平台或内部环境。
该平台提供的关键功能是数据准备和探索、自动化模型创建和可解释的人工智能、无缝和自动化的机器学习操作、构建业务应用和用例跟踪。
9.大太酷
Dataiku 是一个强大的平台,它使数据访问民主化,使企业能够以人为中心的方式创建自己的人工智能之路。您可以获得用于数据准备、可视化、机器学习、数据操作、MLOps 等的工具和服务。
还有一个用于数据和模型分析的分析应用程序。主要焦点是企业级协作、治理、可解释性和架构。可视化流程服务允许您使用数据集构建数据管道,合并和转换数据集,以及构建预测模型。
Dataiku 的 ML 特性使用成熟的编码技术自动填充缺失值并将非数字数据转换为数字值。有一个集中的中心来启动项目和整个开发团队的协作。权限控制功能可用于控制用户对不同服务的访问。可视流程采用高级画布进行协作。该平台为可解释的 AI 提供了关键能力,包括关于特征重要性的报告、部分依赖图、亚种群分析和个体预测解释。
10.伊瓜苏
Iguazio 是一个数据科学平台,具有机器学习管道的端到端自动化,将 AI 解决方案转换为现实世界的商业解决方案。最先进的解决方案可以加速和扩展机器学习的开发、部署和管理。
您可以自动化整个 ML 流程,从数据收集、准备和培训,到快速部署和生产中的持续监控。您可以从任何来源获取数据,并在线和离线构建可重用的解决方案。Iguazio 使用 KubeFlow 进行工作流编排。平台 UI 在可扩展的无服务器 ML/DL 运行时上执行实验,具有自动跟踪、数据版本控制和持续集成/交付(CI/CD)支持。高效的架构有助于将模型和 API 从 Jupyter 笔记本或 IDE 部署到生产环境中,只需点击几下鼠标,然后持续监控模型性能并减少模型漂移。
结论
Clear.ml 是众多数据科学工具中的佼佼者,同时也是开源的。但是,上面提到的这些工具在不同的用例中同样有用,它们可以成为 clear.ml 的正确替代品。
自动化流程、可扩展性、统一设计、全局插件集成和其他关键功能使这些工具非常高效和有效地驱动机器学习项目来创建要部署的准确模型。您可以创建高质量的数据集并开发最先进的模型,这些模型可以使用功能强大的替代性 MLOps 工具轻松转换为业务成果。
参考
探索聚类算法:解释和用例
原文:https://web.archive.org/web/https://neptune.ai/blog/clustering-algorithms
聚类(聚类分析)是根据相似性对对象进行分组。聚类可用于许多领域,包括机器学习、计算机图形学、模式识别、图像分析、信息检索、生物信息学和数据压缩。
聚类是一个棘手的概念,这就是为什么有这么多不同的聚类算法。采用不同的聚类模型,并且对于这些聚类模型中的每一个,可以给出不同的算法。由一种聚类算法发现的聚类肯定不同于由不同算法发现的聚类。
在机器学习系统中,我们通常将示例分组作为理解数据集的第一步。将一个未标记的例子分组称为聚类。由于样本是未标记的,聚类依赖于无监督的机器学习。如果例子被标记,那么它就变成了分类。
如果您想了解各种集群算法之间的差异,那么集群模型的知识是基础,在本文中,我们将深入探讨这个主题。
什么是聚类算法?
聚类算法用于根据某些相似性对数据点进行分组。好的聚类没有标准。聚类使用未标记的数据确定分组。主要看具体用户和场景。
典型的集群模型包括:
- 连接性模型–如基于距离连接性构建模型的分层聚类。
- **质心模型—**类似 K 均值聚类,用单个均值向量表示每个聚类。
- 分布模型–这里,使用统计分布对集群进行建模。
- 密度模型–如 DBSCAN 和 OPTICS,它们将聚类定义为数据空间中的连通密集区域。
- 分组模型–这些模型不提供精确的结果。他们只提供分组信息。
- 基于图的模型–图中节点的子集,使得子集中每两个节点之间有一条边相连,这可以被视为集群的原型形式。
- 神经模型–自组织映射是最常见的无监督神经网络(NN)之一,它们的特征类似于上面的一个或多个模型。
请注意,有不同类型的集群:
- 硬聚类–数据点要么完全属于该聚类,要么不属于该聚类。例如,考虑具有四个组的客户细分。每个客户可以属于四个组中的任何一个。
- 软聚类–概率分数被分配给那些聚类中的数据点。
在本文中,我们将关注前四个模型(连接性、质心、分布和密度模型)。
聚类算法的类型以及如何为您的用例选择一种算法
让我们看看聚类算法的类型,以及如何为您的用例选择它们。
分层聚类算法(基于连通性的聚类)
层次聚类的主要思想是基于附近的对象比较远的对象更相关的概念。让我们仔细看看这些算法的各个方面:
- 该算法连接到“对象,以根据它们的距离形成“簇”。
- 一个集群可以通过连接到集群的各个部分所需的最大距离来定义。
- 树状图可以代表在不同距离上形成的不同聚类,解释了“层次聚类名称的由来。这些算法提供了一个聚类层次结构,这些聚类在一定距离处被合并。
- 在树状图中,y 轴标记聚类合并的距离。对象被放置在 x 轴旁边,这样簇就不会混合。
层次聚类是一系列以不同方式计算距离的方法。常见的选择有**单连锁聚类、完全连锁聚类、**和 UPGMA 。此外,分层聚类可以是:
- agglomerate–它从单个元素开始,然后将它们分组为单个簇。
- divisible–它从一个完整的数据集开始,并将其划分为多个分区。
凝聚层次聚类(AHC)
在这一部分,我将解释 AHC 算法,它是最重要的层次聚类技术之一。做到这一点的步骤是:
- 每个数据点被视为单个聚类。一开始我们有 K 个集群。开始时,数据点的数量也是 k。
- 现在,我们需要在这一步中通过连接 2 个最近的数据点来形成一个大的集群。这将导致总共 K-1 个集群。
- 现在需要将两个最接近的集群连接起来,以形成更多的集群。这将导致总共 K-2 个集群。
- 重复以上三个步骤,直到 K 变为 0,形成一个大的集群。没有更多要连接的数据点。
- 在最终形成一个大的集群之后,我们可以根据用例使用树状图将集群分成多个集群。
下图给出了层次聚类方法的概念。
AHC 的优势:
- AHC 很容易实现,它还可以提供对象排序,这可以为显示提供信息。
- 我们不必预先指定集群的数量。通过在特定级别切割树状图,很容易决定聚类的数量。
- 在 AHC 方法中,将创建更小的集群,这可能会发现数据中的相似性。
AHC 的缺点:
在开始的任何步骤中被错误分组的对象不能被撤销。
分层聚类算法不提供数据集的唯一分区,但是它们给出了可以从中选择聚类的层次结构。
他们没有很好地处理离群值。每当发现异常值时,它们将作为一个新的聚类结束,或者有时导致与其他聚类合并。
凝聚层次聚类算法是一种自下而上的聚类形式,其中每个数据点都被分配到一个聚类中。这些集群然后连接在一起。相似的聚类在每次迭代中被合并,直到所有的数据点都是一个大的根聚类的一部分。
聚类数据集
通过 Scikit-learn 开始使用 Python 中的集群很简单。一旦安装了这个库,就可以选择多种聚类算法。
我们将使用***make _ class ification***
函数从[*sklearn*](https://web.archive.org/web/20221206013350/https://scikit-learn.org/stable/modules/generated/sklearn.datasets.make_classification.html)
库中生成一个数据集,以演示不同聚类算法的使用。` make_classification '函数接受以下参数:
- 样本的数量。
- 特征的总数。
- 信息特征的数量。
- 冗余特征的数量。
- 从冗余要素和信息要素中随机抽取的重复要素的数量。
- 每个类的聚类数。
from numpy import where
from numpy import unique
from sklearn.datasets import make_classification
from sklearn.cluster import AgglomerativeClustering
import matplotlib.pyplot as plot
train_data, _ = make_classification(n_samples=1000,
n_features=2,
n_informative=2,
n_redundant=0,
n_clusters_per_class=1,
random_state=4)
agg_mdl = AgglomerativeClustering(n_clusters=4)
agg_result = agg_mdl.fit_predict(train_data)
agg_clusters = unique(agg_result)
for agg_cluster in agg_clusters:
index = where(agg_result == agg_cluster)
plot.scatter(train_data[index, 0], train_data[index,1])
plot.show()
Clusters obtained by Hierarchical Cluster Algorithm
分层聚类通常以描述性建模的形式使用,而不是预测性的。它不能很好地处理大型数据集,只能在某些情况下提供最佳结果。有时也很难从树状图上检测出正确的簇数。
基于质心的聚类算法/分区聚类算法
在质心/分区聚类中,个聚类由一个中心向量表示,该向量不一定是数据集的成员。即使在这种特定的聚类类型中,也需要选择 K 的值。这是一个优化问题:找到质心的数量或 K 的值,并将对象分配到附近的聚类中心。这些步骤需要以这样一种方式执行,使得离聚类的平方距离最大化。
使用最广泛的一种基于质心的聚类算法是 K-Means,它的一个缺点是你需要预先选择一个 K 值。
k-均值聚类算法
K-Means 算法使用特定的距离度量将给定的数据集分成预定义的(K)个聚类。每个簇/组的中心被称为质心。
K-Means 算法是如何工作的?
让我们看看 K-Means 算法是如何工作的:
- 最初,选择 K 个质心。选择正确的 k 值有不同的方法。
- 无序播放数据并初始化质心-随机选择 K 个数据点作为质心,无需替换。
- 通过计算分配给每个先前质心的所有样本的平均值来创建新质心。
- 随机初始化质心,直到质心没有变化,这样数据点对聚类的分配就不会改变。
- K-Means 聚类使用欧几里德距离来找出点之间的距离。
注意:K-Means 聚类的一个例子将在下面的用例部分用客户细分的例子来解释。
选择 K 的正确值有两种方法:肘法和剪影法。
手肘法
Elbow 方法选取值的范围,并从中选取最佳值。它计算不同 k 值的组内平方和(WCSS)。它计算平方点的和,并计算平均距离。
在上面的公式中,Yi 是对进行观测的质心。K 的值需要选择在 WCSS 开始减弱的地方。在 WCSS 对 K 的曲线图中,这显示为一个肘。
剪影法
使用平均聚类内距离(m)和每个样本的最近聚类距离(n)的平均值来计算轮廓得分/系数(SC)。
在上面的公式中,n 是数据点和该数据点不属于的最近聚类之间的距离。我们可以计算所有样本的平均 SC,并以此作为度量来决定聚类数。
SC 值的范围在-1 到 1 之间。1 表示聚类被很好地分开并且是可区分的。如果值为-1,则错误地分配了聚类。
以下是 K-Means 姿势相对于其他算法的一些优势:
- 实现起来很简单。
- 它可扩展到大规模数据集,对于大规模数据集也更快。
- 它非常频繁地适应新的例子。
K-Medians 是相对于 K-Means 算法的另一种聚类算法,除了使用中值重新计算聚类中心。在 K-Median 算法中,对异常值的敏感度较低,因为需要排序来计算大型数据集的中值向量。
K-Means 有一些缺点;该算法可以在不同的运行中提供不同的聚类结果,因为 K-Means 从聚类中心的随机初始化开始。获得的结果可能不会重复。
K-Means 算法带来的其他缺点是:
- 如果聚类具有类似球形的形状,K-Means 聚类擅长捕捉数据的结构。它总是试图围绕质心构建一个漂亮的球形。这意味着当聚类具有不同的几何形状时,K-Means 在聚类数据方面表现不佳。
- 即使数据点属于同一个聚类,K-Means 也不允许数据点彼此远离,它们共享同一个聚类。
- K-Means 算法对异常值很敏感。
- 随着维度数量的增加,可伸缩性会降低。
使用 K-Means 进行聚类时,需要记住以下几点:
- 在应用 K-Means 算法时将数据标准化,因为这将帮助您获得高质量的聚类,并提高聚类算法的性能。由于 K-Means 使用基于距离的度量来查找数据点之间的相似性,因此最好将数据标准化为标准偏差为 1,平均值为零。通常,任何数据集中的要素都有不同的测量单位,例如,收入与年龄。
- K-Means 赋予更大的聚类更多的权重。
- 用于选择聚类数量的肘方法不能很好地工作,因为对于所有的 k,误差函数减小。
- 如果聚类之间有重叠,K-Means 就没有内在的不确定性度量来确定属于重叠区域的样本分配给哪个聚类。
- k-表示即使数据不能被聚类,也要对其进行聚类,例如来自均匀分布的数据。
小批量 K 均值聚类算法
K-Means 是流行的聚类算法之一,主要是因为它具有良好的时间性能。当数据集的大小增加时,K-Means 会导致内存问题,因为它需要整个数据集。为此,为了降低算法的时间和空间复杂度,提出了一种叫做小批量 K-Means 的方法。
小批量 K-Means 算法试图以这样一种方式将数据放入主存储器中,即该算法使用随机选择的固定大小的小批量数据。关于小批量 K 均值算法,有几点需要注意:
通过从数据集中获得新的任意样本,在每次迭代中更新聚类(取决于聚类质心的先前位置),并且重复这些步骤直到收敛。
一些研究表明,这种方法节省了大量的计算时间,但代价是聚类质量略有下降。但是还没有进行深入的研究来量化影响聚类质量的聚类数量或它们的大小。
聚类的位置根据每批中的新点进行更新。
所做的更新是梯度下降更新,这明显比正常的批量 K-均值更快。
基于密度的聚类算法
基于密度的聚类将高示例密度的区域连接成聚类。这允许任意的形状分布,只要密集区域是相连的。对于高维数据和不同密度的数据,这些算法遇到了问题。按照设计,这些算法不会将离群值分配给聚类。
基于密度的噪声应用空间聚类
最流行的基于密度的方法是对有噪声的应用进行基于密度的空间聚类( DBSCAN )。它具有一个定义良好的集群模型,称为“密度可达性”。
这种类型的聚类技术连接满足特定密度标准(半径内最小数量的对象)的数据点。DBSCAN 聚类完成后,有三种类型的点:核心、边界、噪声。
如果你看上面的图,核心是一个点,它有一些(m)点在离它自己特定的(n)距离内。边界是在距离 n 处至少有一个核心点的点
噪点既不是边界也不是核心的点。需要分离聚类的稀疏区域中的数据点被认为是噪声和更宽的点。
DBSCAN 使用两个参数来确定如何定义集群:
- minPts :一个区域被认为是密集的,所需的最小点数是
***minPts***
。 - eps :为了定位任意点附近的数据点,使用
**eps (ε) 【T3
作为距离度量。**
下面是对 DBSCAN 算法的逐步解释:
- DBSCAN 从一个随机数据点(未访问的点)开始。
- 使用距离ε提取该点的邻域。
- 如果在该区域内有足够的数据点,并且当前数据点成为最新聚类中的第一个点,则聚类过程开始,否则该点被标记为噪声并被访问。
- 其εε距离邻域内的点也成为新群集中第一个点的同一群的一部分。对于添加到上述聚类中的所有新数据点,重复使所有数据点属于同一聚类的过程。
- 重复上述两个步骤,直到确定了群集中的所有点。聚类的 ε邻域内的所有点都被访问过并且被标记为。一旦我们完成了当前的聚类,就会检索和处理一个新的未访问点,从而进一步发现聚类或噪声。重复该过程,直到所有数据点都被标记为已访问。
DBSCAN 的一个令人兴奋的特性是它的低复杂度。它需要对数据库进行线性数量的范围查询。
DBSCAN 的主要问题是:
- 它希望通过某种密度下降来检测星团的边界。DBSCAN 连接高示例密度的区域。在处理形状奇怪的数据时,该算法优于 K-Means。
DBSCAN 算法的一个优点是:
- 它不需要预定义的集群数量。它还识别噪声和异常值。此外,该算法可以很好地找到任意大小和形状的聚类。
from numpy import where
from numpy import unique
from sklearn.datasets import make_classification
from sklearn.cluster import DBSCAN
import matplotlib.pyplot as plot
train_data, _ = make_classification(n_samples=1000,
n_features=2,
n_informative=2,
n_redundant=0,
n_clusters_per_class=1,
random_state=4)
dbscan_model = DBSCAN(eps=0.25, min_samples=9)
dbscan_model.fit(train_data)
dbscan_res = dbscan_model.fit_predict(train_data)
dbscan_clstrs = unique(dbscan_res)
for dbscan_clstr in dbscan_clstrs:
index = where(dbscan_res == dbscan_clstr)
plot.scatter(train_data[index, 0], train_data[index, 1])
plot.show()
Clusters obtained by DBSCAN Cluster Algorithm
基于分布的聚类算法
与统计学密切相关的聚类模型是基于分布模型的。集群可以被定义为属于相同分布的对象。这种方法非常类似于通过从分布中随机抽取对象来生成人工数据集。
虽然这些方法的理论方面相当不错,但这些模型都存在过度拟合的问题。
高斯混合模型
高斯混合模型( GMM )是一种基于分布的聚类类型。这些聚类方法假设数据由分布组成,例如高斯分布。在下图中,基于分布的算法将数据聚类成三个高斯分布。随着与分布的距离增加,该点属于该分布的概率降低。
GMM 可以像 K-Means 一样用来寻找聚类。一个点属于分布中心的概率随着离分布中心的距离增加而减小。下图中的条带显示概率降低。由于 GMM 包含了一个概率模型,我们也可以找到概率集群分配。当您不知道数据的分布类型时,您应该使用不同的算法。
Example of distribution-based clustering | Source
让我们看看 GMM 是如何计算概率并将其分配给数据点的:
- 一个 GM 是由几个 Gaussianss 组成的函数,每个 Gaussian 由 k ∈ {1,…,K}标识,其中 K 是聚类的个数。混合物中的每个高斯 K 由以下参数组成:
- 定义其中心的平均值μ。
- 定义其宽度的协方差σ。
- 定义高斯函数大小的混合概率。
这些参数可以在下图中看到:
为了找到协方差、均值、方差和聚类权重,GMM 使用了期望最大化技术。
假设我们需要分配 K 个聚类,即 K 个高斯分布,平均值和协方差值分别为μ1,μ2,..μk 和σ1,σ2,..σk,还有一个参数πI,代表分布密度。
为了定义高斯分布,我们需要找到这些参数的值。我们已经决定了聚类的数量,并指定了平均值、协方差和密度的值。接下来是期望步骤和最大化步骤,你可以在这个帖子中查看。
GMM 的优势
- GMM 相对于 K-Means 的一个优点是,K-Means 不考虑方差(这里,方差是指钟形曲线的宽度),GMM 返回数据点属于 K 个聚类中每个聚类的概率。
- 在重叠聚类的情况下,所有上述聚类算法都不能将其识别为一个聚类。
- GMM 使用概率方法,并为属于聚类的每个数据点提供概率。
GMM 的劣势
- 如果分布的数量很大或者数据集包含较少的观察数据点,混合模型在计算上是昂贵的。
- 它需要大型数据集,并且很难估计聚类的数量。
现在让我们看看 GMM 是如何对数据进行聚类的。下面的代码帮助您:
- 创建数据,
- 将数据拟合到“高斯混合”模型,
- 找到分配给聚类的数据点,
- 获取唯一的集群,以及
- 如下图所示绘制聚类图。
from numpy import where
from numpy import unique
from sklearn.datasets import make_classification
from sklearn.mixture import GaussianMixture
import matplotlib.pyplot as plot
train_data, _ = make_classification(n_samples=1200,
n_features=3,
n_informative=2,
n_redundant=0,
n_clusters_per_class=1,
random_state=4)
gaussian_mdl = GaussianMixture(n_components=3)
gaussian_mdl.fit(train_data)
gaussian_res = gaussian_mdl.fit_predict(train_data)
gaussian_clstr = unique(dbscan_res)
for gaussian_cluser in gaussian_clstr:
index = where(gaussian_res == gaussian_cluser)
plot.scatter(train_data[index, 0], train_data[index, 1])
plot.show()
Clusters obtained by Gaussian Mixture Model Algorithm
聚类在不同领域的应用
可以应用集群的一些领域有:
- 营销:客户细分发现。
- 图书馆:根据主题和信息对不同的书籍进行聚类。
- 生物学:不同种类的植物和动物之间的分类。
- 城市规划:根据区位分析房屋价值。
- 文档分析:各种研究数据和文档可以按照一定的相似性进行分组。标注大数据真的很难。在这些情况下,聚类有助于对文本进行聚类&并将其分成不同的类别。像 LDA 这样的无监督技术在这些情况下也有利于在大型语料库中发现隐藏的主题。
无监督建模方法的问题
以下是您在应用聚类技术时可能会遇到的一些问题:
- 结果可能不太准确,因为数据没有提前标注,输入数据也未知。
- 该算法的学习阶段可能需要很长时间,因为它会计算和分析所有可能性。
- 在没有任何先验知识的情况下,模型从原始数据中学习。
- 随着功能数量的增加,复杂性也会增加。
- 一些涉及实时数据的项目可能需要持续向模型提供数据,从而导致耗时且不准确的结果。
选择聚类算法时要考虑的因素
现在让我们来看看选择聚类算法时要考虑的一些因素:
- 选择聚类分析算法,使其能够很好地适应数据集。并非所有的聚类算法都可以有效地扩展。机器学习中的数据集可以有数百万个例子。
- 许多聚类算法通过计算所有样本对之间的相似性来工作。运行时间随着样本数 n 的增加而增加,在复杂度符号中表示为 O(n^2) 。 O(n^2) 当例子数以百万计时不实用。这里重点关注的是 K-Means 算法,其复杂度为 O(n),这意味着该算法与 n 成线性比例关系。
Python 中集群的不同实际用例
1.客户细分
我们将使用客户数据来看看这个算法是如何工作的。此示例旨在将客户分成几个组,并决定如何将客户分组,以增加客户价值和公司收入。这个用例通常被称为客户细分。
数据中的一些特征是客户 ID、性别、年龄、收入(以千美元为单位)以及基于消费行为和性质的客户消费分数。
安装依赖项:
!pip install numpy pandas plotly seaborn scikit-learn
import numpy as np
import pandas as pd
import matplotlib.pyplot as plot
import seaborn as sns
import plotly.express as pxp
import plotly.graph_objs as gph
from sklearn import metrics
from sklearn.metrics import silhouette_score
from sklearn.cluster import KMeans
data = pd.read_csv('Customers.csv')
data.head()
让我们从删除聚类过程中不需要的列开始。
data.drop('CustomerID', axis=1, inplace=True)
我们可以检查数据中列的分布,以了解数据在各个列中的分布情况。
plot.figure(figsize = (22, 10))
plotnum = 1
for cols in ['Age', 'AnnualIncome', 'SpendingScore']:
if plotnum <= 3:
axs = plot.subplot(1, 3, plotnum)
sns.distplot(data[cols])
plotnum += 1
plot.tight_layout()
plot.show()
现在,让我们创建一个条形图来检查特定年龄组的客户分布。您还可以应用同样的方法来可视化客户数量与支出分数的关系,以及基于年收入的客户数量。
age_55above = data.Age[data.Age >= 55]
age_46_55 = data.Age[(data.Age >= 46) & (data.Age <= 55)]
age_36_45 = data.Age[(data.Age >= 36) & (data.Age <= 45)]
age_26_35 = data.Age[(data.Age >= 26) & (data.Age <= 35)]
age_18_25 = data.Age[(data.Age >= 18) & (data.Age <= 25)]
x_age_ax = ['18-25', '26-35', '36-45', '46-55', '55+']
y_age_ax = [len(age_18_25.values), len(age_26_35.values), len(age_36_45.values), len(age_46_55.values),
len(age_55above.values)]
pxp.bar(data_frame = data, x = x_age_ax, y = y_age_ax, color = x_age_ax,
title = 'Count of customers per age group')
Result: Bar plot showing the distribution of customers in a particular age group
聚类最关键的一个方面是选择正确的 K 值。随机选择 K 可能不是一个好的选择。我们将使用肘法和轮廓评分来选择 k 值。
在我们的例子中,从下面的图表来看,通过肘方法找到的 K 的最佳值是 4。我们希望最大化聚类的数量,并限制每个数据点成为其聚类质心的情况。
x_input = data.loc[:, ['Age', 'SpendingScore']].values
wcss = []
for k in range(1, 12):
k_means = KMeans(n_clusters=k, init='k-means++')
k_means.fit(x_input)
wcss.append(k_means.inertia_)
plot.figure(figsize=(15,8))
plot.plot(range(1, 12), wcss, linewidth=2, marker='8')
plot.title('Elbow methodn', fontsize=18)
plot.xlabel('K')
plot.ylabel('WCSS')
plot.show()
让我们检查一下这个特殊实现的轮廓系数是怎样的。
from sklearn.metrics import silhouette_score
label = k_means.predict(x_input)
print(f' Silhouette Score(n=4): {silhouette_score(x_input,
label)}')
从下面的年龄与花费的对比图中,你可以看到一些集群没有很好的分离。簇之间的簇内距离几乎不显著,这就是为什么 n=4 的 SC 是 0.40,这是更小的。尝试不同的 K 值以找到最佳的聚类数。
k_means=KMeans(n_clusters=4)
labels=k_means.fit_predict(x_input)
print(k_means.cluster_centers_)
现在,让我们绘制一个图表来检查这些聚类是如何从数据中形成的。
plot.figure(figsize = (16, 10))
plot.scatter(x_input[:, 0], x_input[:, 1], c =
k_means.labels_, s = 105)
plot.scatter(k_means.cluster_centers_[:, 0],k_means.cluster_centers_[:, 1], color = 'red', s = 250)
plot.title('Customers clustersn', fontsize = 20)
plot.xlabel('Age')
plot.ylabel('Spending Score')
plot.show()
红点表示星团中心。
Clusters formed from Age versus SpendingScore using K-Means
这些数据形成了四个不同的集群。蓝色聚类代表消费得分较高的年轻客户,紫色聚类代表消费得分较低的老年客户。
可以遵循上面实施的类似步骤来聚类“年龄”对“年度收入”以及“支出分数”对“年度收入”。所有这三个都可以结合起来,用一个可以在 Jupyter 笔记本中找到的 3D 绘图来绘制。它还对相同的数据实现了不同的聚类算法。
2.图像压缩
图像压缩是一种在不降低图片质量的情况下应用于图像的压缩技术。图像尺寸的减小有助于将它们存储在有限的驱动器空间中。
为什么需要图像压缩技术?图像压缩有多种需求。压缩在医疗保健中至关重要,因为医疗图像需要存档,而且数据量非常大。
当我们需要提取和存储图像中最有用的部分(表示为嵌入)时,图像压缩可能是存储更多数据的非常有益的方法。
有两种图像压缩技术:
- 无损压缩:这种方法用于减小文件的大小,同时保持与压缩前相同的质量。文件可以恢复到原始形式,因为这种技术不会损害数据质量。
- 有损压缩:有损压缩是一种消除不明显数据的方法。它给照片一个更小的尺寸;有损压缩会丢弃图片中一些不太重要的部分。在这种类型的压缩技术中,被压缩的图像不能被恢复到它的原始图像,并且数据的大小改变。
让我们使用 K-Means 聚类来解决这个问题。
您可能已经知道,一幅图像由 3 个通道组成,、RGB ,每个通道的值都在**【0,255】**范围内。因此,一个特定的图像可能有 255255255 种不同的颜色。所以在我们输入图像之前,我们需要对它进行预处理。
我们将要处理的图像的大小是(1365,2048,3)。因此,对于每个像素位置,我们将有两个 8 位整数来指定红色、绿色和蓝色强度值。我们的目标是将它减少到 25 种颜色,并且只用这些颜色来表现照片。
下面导入了此任务所需的一些包:
import matplotlib.pyplot as plt
from matplotlib.image import imread
import pandas as pd
import numpy as np
import seaborn as sns
from sklearn.cluster import KMeans
从这里下载图片并读入。
img = imread('palace.jpg')
img_size = img.shape
重塑 2D 的形象。我们将 K-Means 算法应用于图片,并将每个像素视为一个数据点来选择使用什么颜色。这意味着将图像从高 X 宽 X 通道重塑为(高 X 宽)X 通道;我们将有 1365 x 2048 = 2795520 个数据点。
遵循这种方法将有助于我们使用 25 个质心来表示图像,并减少图像的大小。当我们使用质心作为像素颜色的查找时,会有一个相当大的不同,这将把每个像素位置的大小减少到 4 位,而不是 8 位。
X = img.reshape(img_size[0] * img_size[1], img_size[2])
运行 K 均值算法
上一节给出了 K-means 算法的详细说明。在本例中,我们将重点关注压缩部分。
km = KMeans(n_clusters=25)
km.fit(X)
使用质心来压缩图像。
X_cmpresd = km.cluster_centers_[km.labels_]
X_cmpresd = np.clip(X_cmpresd.astype('uint8'), 0, 255)
将 X_cmpresd 整形为与原始图像 128 * 128 * 3 相同的尺寸
X_cmpresd = X_cmpresd.reshape(img_size[0], img_size[1], img_size[2])
现在,将原始图像和压缩图像相邻绘制。
figre, axs = plt.subplots(1, 2, figsize = (14, 10))
axs[1].imshow(img)
axs[1].set_title('Initial image')
axs[0].imshow(X_cmpresd)
axs[0].set_title('Compressed one (25 colors)')
for axs in figre.axes:
axs.axis('off')
plot.tight_layout();
这里,我使用了 25 个质心。压缩图像看起来更接近原始图像(意味着真实图像的许多特征被保留)。使用更少的聚类数,我们会以牺牲图像质量为代价获得更高的压缩率。相似的颜色被分组到 k 个簇中(k = 25(不同的 RGB 值))。
3.数字分类
在这个实现中,我们将使用小批量 K-Means 来执行图像分类。聚类也可以用于图像分析。利用 Scikit-learn 和 MNIST 数据集,我们将研究小批量 K 均值聚类在计算机视觉中的应用。
安装依赖项:
pip install keras tensorflow
导入库:
import sys
import sklearn
import matplotlib
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
加载 MNIST 数据集。可以通过 Keras 买到。
figur, axi = plt.subplots(3, 3, figsize=(14, 14))
plt.gray()
for j, axs in enumerate(axi.flat):
axs.matshow(x_train[j])
axs.axis('off')
axs.set_title('number {}'.format(y_train[j]))
figur.show()
图像预处理
存储为 Numpy 数组的图像是二维数组。Scikit-learn 提供的小批量 K 均值聚类算法吸收了 1D 数组。因此,我们需要重塑形象。MNIST 包含 28 x 28 像素的图像;因此,一旦我们将它们成形为 1D 阵列,它们的长度将为 784。
X = x_train.reshape(len(x_train), -1)
Y = y_train
X = X.astype(float) / 255.
print(X.shape)
print(X[0].shape)
聚类
由于数据集的大小,我们使用 K-Means 的小批量实现。该算法需要更少的时间来拟合数据。MNIST 数据集包含整数 0-9 的图像。因此,让我们通过将聚类数设置为 10 来开始聚类。
from sklearn.cluster import MiniBatchKMeans
n_digits = len(np.unique(y_test))
print(n_digits)
kmeans = MiniBatchKMeans(n_clusters=n_digits)
kmeans.fit(X)
kmeans.labels_
分配聚类标签
Mini-Batch K-means 是一种无监督的 ML 方法,这意味着由算法分配的标签指的是每个阵列被分配到的聚类,而不是实际的目标整数。为了解决这个问题,让我们定义一些函数来预测哪个整数对应于每个聚类。
def cluster_labels_infer(kmeans, actual_lbls):
"""
returns: dictionary(clusters assigned to labels)
"""
infrd_labels = {}
for n in range(kmeans.n_clusters):
labels = []
index = np.where(kmeans.labels_ == n)
labels.append(actual_lbls[index])
if len(labels[0]) == 1:
counts = np.bincount(labels[0])
else:
counts = np.bincount(np.squeeze(labels))
if np.argmax(counts) in infrd_labels:
infrd_labels[np.argmax(counts)].append(n)
else:
infrd_labels[np.argmax(counts)] = [n]
return infrd_labels
def data_labels_infer(X_labels, clstr_labels):
"""
Depending on the cluster assignment find the label
predicted labels are returned for each array
"""
pred_labels = np.zeros(len(X_labels)).astype(np.uint8)
for l, clstr in enumerate(X_labels):
for key, val in clstr_labels.items():
if clstr in val:
pred_labels[i] = key
return pred_labels
让我们测试上面写的函数来预测哪个整数对应于每个集群。
clstr_labels = cluster_labels_infer(kmeans, Y)
input_clusters = kmeans.predict(X)
pred_labels = data_labels_infer(input_clusters, clstr_labels)
print(pred_labels[:20])
print(Y[:20])
评估和优化聚类算法
利用上面返回的函数,我们可以确定算法的准确性。由于我们使用聚类算法进行分类,准确性成为一个重要的衡量标准。一些度量可以直接应用于集群,而不考虑相关联的标签。使用的指标有:
之前,我们在选择 K 的特定值时做了假设,但情况可能并不总是如此。让我们将小批量 K-Means 算法适用于不同的 K 值,并使用我们的指标评估性能。计算模型指标的函数定义如下。
from sklearn import metrics
def calculate_metrics(estimator, data, labels):
print('Number of Clusters: {}'.format(estimator.n_clusters))
print('Inertia: {}'.format(estimator.inertia_))
print('Homogeneity: {}'.format(metrics.homogeneity_score(labels, estimator.labels_)))
现在我们已经定义了指标,让我们为不同数量的集群运行模型。
clusters = [10, 16, 36, 64, 144, 256]
for n_clusters in clusters:
estimator = MiniBatchKMeans(n_clusters = n_clusters)
estimator.fit(X)
calculate_metrics(estimator, X, Y)
cluster_labels = cluster_labels_infer(estimator, Y)
predicted_Y = data_labels_infer(estimator.labels_, cluster_labels)
print('Accuracy: {}n'.format(metrics.accuracy_score(Y, predicted_Y)))
让我们使用 256 作为分类数在测试集中运行模型,因为它对于这个特定的数字有更高的准确性。
X_test = x_test.reshape(len(x_test),-1)
X_test = X_test.astype(float) / 255.
kmeans = MiniBatchKMeans(n_clusters = 256)
kmeans.fit(X)
cluster_labels = cluster_labels_infer(kmeans, Y)
test_clusters = kmeans.predict(X_test)
predicted_labels = data_labels_infer(kmeans.predict(X_test),
cluster_labels)
print('Accuracy: {}n'.format(metrics.accuracy_score(y_test,
predicted_labels)))
可视化集群质心
质心是每个聚类中有代表性的点。如果我们处理 A,B 点,质心就是图上的一个点。因为我们使用长度为 784 的数组,所以我们的质心也是长度为 784 的数组。我们可以将这个数组重新整形为 28×28 像素的图像,并绘制出来。
kmeans = MiniBatchKMeans(n_clusters = 36)
kmeans.fit(X)
centroids = kmeans.cluster_centers_
images = centroids.reshape(36, 28, 28)
images *= 255
images = images.astype(np.uint8)
cluster_labels = cluster_labels_infer(kmeans, Y)
fig, axs = plt.subplots(6, 6, figsize = (20, 20))
plt.gray()
for i, ax in enumerate(axs.flat):
for key, value in cluster_labels.items():
if i in value:
ax.set_title('Inferred Label: {}'.format(key))
ax.matshow(images[i])
ax.axis('off')
fig.show()
这些图形显示了该群集最具代表性的图像。
Result: Most representative image for each cluster
随着聚类数量和数据点数量的增加,计算时间的相对节省也会增加。只有当集群数量巨大时,节省的时间才会更加明显。只有当聚类数较大时,批量大小对计算时间的影响才更明显。
聚类数的增加降低了小批量 K-均值解与 K-均值解的相似性。随着集群数量的增加,分区之间的一致性会降低。这意味着最终的分区不同,但质量更接近。
聚类度量
有一些评估标准可以用来检查通过您的聚类算法获得的聚类有多好。
同质性得分
同质性度量:如果所有聚类只包含属于单一类别的数据点,则聚类结果满足同质性。该指标独立于标签的绝对值。它被定义为:
同质性得分介于 0 和 1 之间。低值表示同质性低,1 代表完全同质的标签。
当 Ypred 的知识减少了 Ytrue 的不确定性时,变小(h → 1),反之亦然。
完美的标记是同质的。进一步将类分成更多聚类的非完美标记可以是同质的。来自一个聚类中不同类别的样本不满足同质标记。
完整性分数
仅当给定类的数据点是同一聚类的一部分时,聚类结果才满足完整性。
这个度量是不对称的,所以从上面的等式中切换 label_true 和 label_pred 将返回不同的同质性得分。这同样适用于同质性得分;切换 label_true 和 label_pred 将返回完整性分数。
完美的标签是完整的。将所有类成员分配到相同聚类的非完美标记仍然是完整的。如果班级成员分散在不同的集群中,分配就无法完成。
衡量分数
V-measure 聚类标记给出了一个基本事实。V 测度是同质性和完备性之间的调和平均值。
这个度量是对称的。将' label_true '与' label_pred '切换将返回相同的值。当真实情况未知时,该度量有助于计算对同一数据集的两种独立标注分配技术的接受度。
分数范围在 0-1 之间。1 代表完全完整的标签。
示例:
from sklearn import metrics
true_labels = [2, 2, 3, 1, 1, 1]
pred_labels = [1, 1, 2, 3, 3, 3]
metrics.homogeneity_score(true_labels, pred_labels)
Output: 1.0
metrics.completeness_score(true_labels, pred_labels)
Output: 1.0
(1 stands for perfectly complete labeling)
metrics.v_measure_score(true_labels, pred_labels)
Output: 1.0
-------------------------------------------------------------------
true_labels = [2, 2, 3, 6, 1, 1]
pred_labels = [1, 1, 2, 3, 2, 1]
metrics.homogeneity_score(true_labels, pred_labels)
Output: 0.58688267143572
metrics.completeness_score(true_labels, pred_labels)
Output: 0.7715561736794712
metrics.v_measure_score(true_labels, pred_labels)
Output: 0.6666666666666667
调整后的 rand 分数
可以使用 Rand 指数(RI)计算两个聚类之间的相似性,方法是对所有样本对进行计数,并对真实聚类和预测聚类中分配到不同或相同聚类中的样本对进行计数。然后使用以下方案将 RI 分数“根据机会调整”为 ARI 分数。
ARI 是一种对称度量:
请参考链接获取详细的用户指南
调整后的相互信息分数
调整后的互信息(AMI)分数是对互信息分数的调整,以考虑机会。这说明了这样一个事实,即无论是否有更多的信息共享,具有许多聚类的 2 个聚类的互信息得分通常更高。
对于两个集群 U 和 V,AMI 为:
有关用户指南,请参考链接。 GitHub repo 有这篇文章的数据和所有笔记本。
摘要
这篇博客涵盖了聚类、图像压缩、数字分类、客户细分、不同聚类算法的实现和评估指标等最关键的方面。希望你们在这里学到了新东西。
感谢阅读。继续学习!
参考
- https://scikit-learn.org/stable/modules/clustering.html
- https://towards data science . com/the-5-clustering-algorithms-data-scientists-need-to-know-a36d 136 ef 68
- https://medium . datadriveninvestor . com/k-means-clustering-for-imagery-analysis-56c 9976 F16 b 6
- https://imaddabbura.github.io/post/kmeans-clustering/
- https://www . geeks forgeeks . org/ml-mini-batch-k-means-clustering-algorithm/
- https://sci kit-learn . org/stable/modules/generated/sk learn . metrics . v _ measure _ score . html # sk learn . metrics . v _ measure _ score
- https://www . ka ggle . com/niteshyadav 3103/customer-segmentation-using-k means-HC-DBS can
- https://www . LinkedIn . com/pulse/Gaussian-mixture-models-clustering-machine-learning-cheruku/
ML 团队的代码和笔记本版本控制[工具]
原文:https://web.archive.org/web/https://neptune.ai/blog/code-and-notebook-versioning-for-ml-teams-guide
作为一名数据科学家或机器学习工程师,你可能经历过这种情况:
你开始在你的 Jupyter 笔记本上写代码,做你的探索,预处理你的数据,建立你的模型并保存它们…但是然后你失去了跟踪哪个代码和笔记本版本是最好的。
有传统的工具,像 git 和其他源代码和笔记本版本管理系统,但是它们并不特别适合在开发和实验阶段提高 ML 团队的生产力。
这就是为什么在这篇文章中,我将列出一些工具,它们将为你和你的团队提供一个更有条理的平台,让你拥有和使用不同版本的实验笔记本,提高你的生产力和效率(包括你整个团队的生产力和效率)。
到本文结束时,您应该已经:
- 了解对您的笔记本进行版本管理的必要性。
- 了解选择笔记本版本控制工具时要考虑的因素。
- 了解管理笔记本和代码版本的 5 大工具。
选择笔记本版本管理工具或平台时,以下是需要考虑的最重要的几点:
- **笔记本检查点/提交:**您应该能够恢复到您版本化的笔记本中以前的检查点,并比较不同检查点之间的变化。
- **比较不同的笔记本:**你应该能够比较不同笔记本之间的差异和变化。
- **团队协作:**您应该能够通过共享、笔记本中的评论和聊天功能(这样可以避免不必要的会议)、笔记本中的结果描述、笔记本版本与团队进行的实验之间的直接链接以及其他协作功能,在各种笔记本版本上与队友高效协作。
- **定价选项:**工具/平台是免费的还是付费的?付费工具有哪些选择和不同的方案?它们与开源工具相比如何?
以下是对您的笔记本进行版本管理以有效管理实验的 5 大工具。
Neptune.ai | 评论 NB | SageMaker Studio | nedime | 彗星 | |
---|---|---|---|---|---|
笔记本检查点/提交
|
提供存储笔记本检查点的支持。
|
与 GitHub 集成良好,但不存储检查点文件。
|
存储笔记本检查点,跟踪新提交。
|
跟踪每个新的检查点并提交。
|
不存储或跟踪检查点文件或提交。
|
|
笔记本对比功能
|
支持比较不同笔记本和笔记本版本。
|
仅跟踪一个笔记本中的更改,但不提供跨笔记本版本比较。
|
为笔记本提供笔记本差异支持,但不支持跨笔记本版本比较。
|
可以比较不同笔记本和版本,甚至可以将所有改动合并到一个笔记本中。
|
不提供笔记本对比功能。
轻松共享和跟踪笔记本数据,从笔记本作者到描述、上次保存检查点的时间以及相关实验。
|
非常适合笔记本代码审查和无缝团队协作。
|
受限笔记本链接分享选项,只有 AWS 授权用户,不能在笔记本内发表评论进行团队交流。
|
不支持链接共享,但与现有 Git 工作流集成良好。
|
团队协作有利于机器学习项目管理 SaaS。
|
| | | 免费用于开源和教学目的,10 人以下的团队起价 79 美元。 |
AWS 用户免费,但您需要为运行笔记本工作负载的计算实例付费。
|
开源;完全免费。
|
为个人用户提供免费的有限功能,最多 5 人的团队起价 179 美元。
|
现在,让我们详细回顾一下。
如果你正在寻找一个可以管理你所有实验元数据和你团队开发过程的平台,只需看看 Neptune.ai. Neptune 现在是 MLOps 的元数据存储,为运行大量实验的研究和生产团队构建。它对于管理不同的笔记本版本也非常有用,并在一个选项卡中向您显示不同的笔记本版本以及它们的创建者。Neptune.ai 客户端也可以帮助您管理本地笔记本电脑。
使用 Neptune.ai 的笔记本检查点/提交
Neptune.ai 不仅可以有效地管理各种笔记本版本,还可以管理每个笔记本的检查点文件,以便您可以跨检查点跟踪更改和差异。
您还可以比较两个检查点之间的差异和变化。
使用 Neptune.ai 平台比较不同的笔记本
除了比较检查点,您还可以比较来自不同或相同实验的不同笔记本版本。通过这种方式,你和你的团队可以做出最明智的决策,包括其他功能,如跟踪日志、指标和来自实验的其他元数据,所有这些都由 Neptune.ai 提供
与 Neptune.ai 的团队协作
除了将所有不同的笔记本版本放在一个地方,包括元数据(执行时间、实验指标),Neptune.ai 还通过向不同的笔记本版本添加描述,以类似 git 的格式保持您的组织和协作。
Neptune.ai 提供了一个丰富的可视化仪表板,让您和您的团队了解谁在您的 ML 实验笔记本的任何特定阶段工作,他们最后一次工作的时间,以及他们对笔记本的易读描述,因此您可以一目了然。
您可以与团队中的任何人共享您的笔记本版本仪表板。这可以帮助您的团队保持高效工作,并从笔记本电脑版本中快速获取最相关的详细信息。
如果需要优先在内部运行所有工作负载,Neptune.ai 也可以在内部托管,以便您的团队进行协作。
Neptune.ai 的定价选项
现在你可能会认为这个高效的笔记本版本管理平台的成本很高,对吗?幸运的是,它没有。如果你想将该平台用于你的个人项目,或者工作或研究,Neptune.ai 免费为你提供 100GB 的存储空间,用于存储你的实验笔记本和元数据。
如果你有一个教育机构或者非营利组织,Neptune 免费向你的团队提供他们的整个平台。对于商业机构来说,是有偿的。
如果你在大公司工作,担心每月的费用,你可以随时联系 Neptune.ai,获得更定制的方案。点击查看价格选项。
Neptune.ai 入门
迫不及待想开始?太好了!事实上,您现在就可以查看笔记本管理选项卡,并通过点击此处来使用它。如果你喜欢,注册,让它成为你的。
ReviewNB 是数据科学社区中最流行的 Jupyter 笔记本工具之一。这是一个 GitHub 验证的应用程序,为笔记本电脑提供了完整的代码审查工作流程。它与 Git 和 Github 很好地集成在一起,并有目的地围绕审查笔记本中的代码而构建。
笔记本检查点/提交
因为 ReviewNB 与 GitHub 集成得很好,所以在相互比较时,它提供了各种检查点、提交(甚至是拉请求)之间的丰富差异。您可以直接从您或团队中的任何其他人那里看到任何提交或拉取请求的丰富笔记本差异。
使用 ReviewNB 比较不同的笔记本
遗憾的是,使用 ReviewNB,您无法比较不同笔记本之间的变化,只能在一个特定的笔记本中进行比较。例如,您可能想要比较使用特定类型预处理的笔记本版本与使用不同类型预处理的笔记本版本。这在 ReviewNB 中是做不到的(如果需要的话 Neptune 会做)。
使用 ReviewNB 进行团队协作
ReviewNB 是在团队协作的基础上构建的。事实上,在他们的主页上,你会注意到该平台针对数据科学协作进行了简化。通过代码审查等功能,ReviewNB 使数据科学团队能够轻松地在任何笔记本单元上撰写评论,提出澄清性问题,并在笔记本单元的上下文中提供反馈。
对于每个打开的新评论或评论,团队可以通过电子邮件直接获得通知。您可以在笔记本 diff 上发表评论以讨论更改,打开每个新评论的讨论主题,并跟踪对话主题。
如果您需要在内部运行所有工作负载,还可以在内部托管 ReviewNB,以便您的团队进行协作。要进行设置,您可以在这里请求安装。
评论的定价选项
ReviewNB 是免费的,可以开源使用,也可以用于教育目的(如果你有*)。edu* 邮箱,也可以报名参加免费发售。最多 10 个用户的小团队每月 79 美元,最多 30 个用户的企业每月 249 美元。与 Neptune.ai 选项一样,对于具有无限功能的大型组织,您可以联系团队。
ReviewNB 入门
如果你有一个有效的 GitHub 账户,你可以在这里注册。文档组织得很好,便于你开始使用。
根据官方网站,亚马逊 SageMaker Studio 提供了一个单一的基于网络的可视化界面,您可以在其中执行所有 ML 开发步骤,将数据科学团队的生产力提高了 10 倍。
SageMaker Studio 为您提供了对构建、训练和部署模型所需的每个步骤的完全访问、控制和可见性。显然,它是由 AWS 云提供支持的,因此您只能通过适当的 AWS 授权来访问它。
使用 AWS SageMaker Studio 的笔记本检查点/提交
就像普通的 Jupyter 笔记本一样,SageMaker studio 允许您手动保存笔记本检查点,因此您可以根据需要恢复它们。检查点文件存储在 S3 存储桶中,它是在您创建新环境时自动创建的。您可以使用检查点比较功能来查看最新笔记本版本和检查点文件之间的更改。所有的笔记本元数据也由 Amazon SageMaker 管理。
如果从 Git 存储库中打开一个笔记本,您可以查看该笔记本和上一次 Git 提交之间的差异。
使用 aws pagemaker studio 比较不同的笔记本电脑
同样使用 AWS SageMaker studio,您不能比较不同笔记本之间的变化,而只能在一个特定的笔记本中通过使用任何笔记本差异功能(在 studio 中)来进行比较。
检查一下 SageMaker Sudio 和 Neptune 有什么区别
使用 aws pagemaker studio 进行团队协作
使用 AWS SageMaker,您可以执行所有 ML 开发活动,包括笔记本、实验管理、自动模型创建、调试以及模型和数据漂移检测。你可以和你的队友分享你的亚马逊 SageMaker Studio 笔记本。共享的笔记本是副本,您不能修改共享的原始笔记本。
要让您的团队成员进行更改,他们必须为您的原始笔记本创建一个新副本。如果您想要共享您的最新版本,您必须创建新的快照,然后共享它。您也可以决定不包括单元运行的输出。
它有一个很好的 GitHub 集成特性,您可以包含到包含笔记本的 Git 存储库的链接,然后您和您的同事可以协作并为同一个 Git 存储库做出贡献。您的共享选项也非常安全,因为您可以为您希望能够访问您的共享笔记本的特定同事提供 IAM 身份验证。
有了 SageMaker studio,你就不会像我们在 Neptune.ai 和 ReviewNB 上看到的那样,有闲功夫在同事分享的笔记本上留下评论。如果你想做些改变,你必须创建一个新的笔记本副本,这本身就相当有压力和低效。
AWS SageMaker Studio 的定价选项
使用 AWS Studio SageMaker 是免费的,但您需要为运行笔记本的计算实例支付标准 SageMaker 价格。
aws pagemaker studio 入门
要访问 AWS SagMaker Studio,您必须拥有一个 AWS 帐户,IAM 授权访问 SageMaker。您可以观看 Julien Simons 的网上研讨会,了解 SageMaker studio 的其他产品。您可能希望检查定价,以了解您的免费层或组织计费是否支持任何标准实例。
nbdime 提供了区分和合并笔记本的工具。它是完全开源的,可以在本地工作。它很容易安装非常有用的文件,并有一个活跃的社区。
使用 nbdime 的笔记本检查点/提交
Nbdime 与“git”版本控制有很好的集成,您可以设置它与本地“git”客户端一起工作,因此 git diff & git merge 命令使用 nbdime。ipynb 文件。通过 git 集成,您可以在本地使用 Jupyter 笔记本,并在提交到存储库之前运行“git diff”来查看笔记本发生了什么变化。
使用 nbdime 比较不同的笔记本电脑
使用 nbdime,您可以以终端友好的方式比较两个或更多笔记本版本之间的差异,甚至可以合并多个笔记本,冲突会自动解决。在比较笔记本、图表或其他数据之间的差异时,您也可以获得丰富的视觉体验。
使用 nbdime 的团队协作
凭借其与“git”和“nbmerge”三路合并笔记本自动解决冲突的出色集成,“nbdime”可能是 Jupyter 笔记本最好的完全免费版本控制工具,尤其是对于已经熟悉 git 的团队而言。
nbdime 的定价选项
“nbdime”是完全开源的,对各种规模的团队都是免费的。唯一的缺点是您只能在本地使用它,但是如果您和/或您的团队已经将 git 整合到您的工作流中,采用它应该不是一件麻烦的事情。
` nbdime '入门
` nbdime '很容易安装。开始的最好地方是文档。
我们对代码和笔记本进行版本控制的最后一个工具是 Comet。Comet let's 数据科学团队跟踪、比较、解释和优化他们的实验和模型,为机器学习带来效率、透明度和可再现性。它提供了一个自托管和基于云的元机器学习平台,让数据科学家和团队跟踪、比较、解释和优化实验和模型。
探索彗星和海王星的区别
使用 Comet 的笔记本检查点/提交
就版本化笔记本的体验而言,Comet 达不到上面列出的其他选项。与 Neptune.ai 相比,您的检查点文件也不会被保存。
我认为 Comet 实际上是版本化 Python 代码的最佳工具(从这个列表中的一组工具中),并且可以比较各种代码实验中所做更改的差异(当您想要将实验推向生产时,这非常有用)。然而,对于笔记本电脑来说,从数据探索到模型构建,不同的团队在不同的项目阶段工作,它在提供丰富的 Jupyter 笔记本体验方面不如 Neptune.ai 这可能会使团队协作和沟通变得困难。
使用 Comet 的团队协作
Comet 是在开发和生产中管理机器学习项目的最佳工具之一。您可以与您的队友共享您的版本化笔记本,但 Jupyter 笔记本的功能和支持是有限的。您只知道有限的信息,如谁编写了什么笔记本、执行时间、各种版本等等。虽然 Comet 保存了使用 Jupyter 笔记本运行的实验的执行顺序代码,但合作者可以轻松地复制任何实验。
Comet 会自动与项目的 git 库集成,所以如果您的团队已经习惯了“git”工作流,集成 Comet 会很容易。
Comet 的定价选项
对于上面列出的所有选项,Comet 是最昂贵的平台。虽然它对单个用户是免费的,但是如果你有一个团队并且想要额外的功能,你可能每月要支付 179 到 249 美元。
你可能想仔细考虑一下你的选择。您可以点击查看定价页面了解更多信息。
Comet 入门
要开始使用 Comet,你必须注册他们的一个定价计划。除了 Neptune.ai 的文档之外,文档是我见过的最有条理的文档之一。
最后的想法和下一步
我真的希望这篇文章能帮助你理解对你的实验笔记本进行版本控制的必要性,并选择一个适合你或者你和你的团队的平台。
我鼓励你根据自己的需求选择一个平台,在接下来的几天里使用,看看它是否适合你和/或你的团队。
参考
- 如何对 Jupyter 笔记本进行版本控制|作者 Amit Rathi |走向数据科学
- 亚马逊 SageMaker Studio——机器学习的第一个 IDE 亚马逊 Web 服务
- NBD ime-Jupyter 笔记本的区分和合并-NBD ime 3 . 0 . 0 . B1 文档
- FAQ——彗星
- 彗星企业:两分钟演示
变压器综合指南
原文:https://web.archive.org/web/https://neptune.ai/blog/comprehensive-guide-to-transformers
你有一张写有文字的纸,你想建立一个模型,可以把这些文字翻译成另一种语言。你如何处理这个问题?
第一个问题是文本的可变大小。没有线性代数模型可以处理不同维数的向量。
处理这类问题的默认方式是使用单词袋模型( 1 )。在这个模型中,数据将是一个巨大数量的向量,与一种语言的字数一样大,并且大多数向量元素将是零,因为大多数术语在本文中没有使用。为了最小化计算向量的大小,我们只存储呈现单词的位置。
然而,单词袋模型忽略了单词的顺序,而这是至关重要的。例如:“为了生活而工作和“为了工作而生活”是不同的为了保持数据的顺序,我们将增加图的维度( n-gram )来将顺序添加到我们的等式中。
在 n-gram 模型中,一个词的概率取决于( n-1 )之前的评论,这意味着模型不会与早于( n-1 )的词相关联。为了克服这一点,我们将不得不增加 n,这将成倍增加计算复杂度( 2 )。
所以,这是我们目前的问题:
- 文本的可变长度。
- 应用词袋模型后的海量数据。
- 当我们增加维度时,计算成本增加。
似乎我们需要一个新的模型,它不依赖于单词袋。这就是 RNN 模型发挥作用的地方。
递归神经网络(RNN)
RNN 与 n-gram 模型相同,只是当前输入的输出将取决于之前所有计算的输出。RNN 有其内部状态,作为一种记忆。它非常适合自然语言处理和语音识别。
Character Level Language model based on RNN [source]
该图显示了在某个时间(t+6)的输入取决于每个先前步骤的隐藏状态和当前输入。它允许网络保存以前学习的参数的历史,并使用它来预测下面的输出,这克服了单词顺序的问题,并消除了计算成本,因为我们将在我们的模型中单独传递单词。
这种模式看似完美,但在实践中却存在一些问题( 5 ):
- 消失或爆炸梯度问题。
- 我们不能并行计算,因为输出取决于之前的计算。
好吧,RNN 模型并不完美。因此,它被进一步修改以克服这些缺陷。
长短期记忆(LSTM)
这种特殊的 RNN 增加了一种遗忘机制,因为 LSTM 单位被分成细胞。每个单元格有三个输入:
- 电流输入,
- 隐藏状态,
- 上一步的记忆状态( 6 )。
这些输入通过门:
- 输入门,
- 忘了盖特吧,
- 输出门。
门调节进出细胞的数据。
遗忘门决定何时记忆,何时跳过先前隐藏状态的输入。这种设计主要是为了克服消失和爆炸梯度的问题。
Computing the hidden states in LSTM [source]
LSTM 能够克服 RNN 模型中的消失和爆炸梯度,但是仍然存在从 RNN 模型继承的问题,例如:
- 没有并行化,我们仍然有数据的顺序路径,甚至比以前更复杂。
- 硬件资源还是个问题。
这些解决方案不足以克服内存和并行性问题。所以,是时候引入另一种模式了。
变形金刚(电影名)
在前面的章节中,我们介绍了我们面临的问题,以及一些解决部分问题的建议方案。但是仍然有研究的空间。
我们提到了序列到序列翻译的变长问题,这个问题还没有解决。
为了解决这个问题,2017 年推出了一种依赖于注意力机制的模型。我们不是单独处理标记,而是将文本分成段,并学习它们之间的依赖关系。
这个模型是基于另一个架构设计的,由两个主要组件组成。
输入首先通过编码器。
该编码器将接受可变长度的输入,并将其转换为固定长度的隐藏状态。
然后,隐藏状态将通过第二个组件,这是一个解码器,将固定长度的状态转换为可变长度的输出。
这种架构被称为 编解码架构 ( 4 )。
Encoder-decoder architecture [source]
Sequence to sequence learning [source]
在 Transformers 中,输入标记被转换为向量,然后我们添加一些位置信息(位置编码),以便在模型的并发处理过程中考虑标记的顺序。
变形金刚修改了这个模型,使其能够抵抗我们之前讨论的问题,对编码器和解码器都使用了堆叠自关注和完全连接的层。
**编码器:**由一堆多个相同的层组成,每层包含两个子层,多头自关注机制后跟残差连接,简单的全连接前馈网络。
**解码器:**由多层堆叠而成,每层三个子层;前两层与编码器层相同,第三层是对编码器堆栈输出的多头关注。
The transformer architecture [source]
注意机制
这个模型的灵感来自于人类的视觉系统( 7 )。当大脑从眼睛接收大量信息输入,超过大脑一次处理的能力时,眼睛感觉系统中的注意力线索使人类能够关注眼睛接收的一小部分。
我们可以将这种方法应用于手头的问题。如果我们知道了能够影响我们翻译的部分,我们就可以专注于那些部分,忽略其他无用的信息。
这将影响系统的性能。当你在读这篇文章的时候,你在关注这篇文章,而忽略了这个世界的其他部分。这伴随着一种可以被称为机会成本的成本。
我们可以从不同类型的注意力机制中进行选择,比如注意力集中和全连接层。
在注意力集中中,对注意力系统的输入可以分为三种类型:
- 键(非暴力提示),
- 查询(意志提示),
- 值(感官输入)。
我们可以将关键字和查询之间的注意力权重可视化。值和密钥是编码器的隐藏状态,查询是前一个解码器的输出。
Visualizing the attention weight matrix (source)
标度点积注意力
缩放的点积是评分函数的更有效的计算设计。
我们用相同的向量长度(d)计算输入查询(Q)和键(K)的点积。然后,我们对它们进行缩放,以确保方差保持不同的向量长度,然后应用 softmax 函数来获得值(V)的权重。
成比例的点积注意力&多头注意力来源
多头注意力
我们并行执行单点乘积注意 h 时间。
w 是键、查询和值的权重,O 是输出线性变换。
多头注意力在我们的模型中用于:
- 解码器层;Queries 是前一个解码器层的输出,Keys 是编码器的输出。
- 编码器自我关注层;关键字、查询和值来自编码器的前一层。
自我关注
一种特殊的注意机制,其中的查询、键和值都来自同一个源。当序列长度(n)小于表征维度(d)时,自我注意(内部注意)比循环层更快。
自我注意被用来学习一个句子中不同单词的相关性,来计算同一个句子的表示。
位置式前馈网络
编码器和解码器的每一层都包含完全连接的前馈网络,该网络利用两个线性变换和一个 ReLU 激活函数的相同前馈网络来变换每个位置中的表示。
嵌入和 softmax
将输入和输出记号转换成模型维度的向量,并将解码器的输出转换成预测概率。
位置编码
由于该模型没有递归和卷积,因此添加了一个层来利用序列顺序。在编码器和解码器堆栈的末尾,注入的信息包含关于令牌在该序列中的相对或绝对位置的信息。
普通变压器概述
Vanilla Transformer 是克服 RNN 模型缺点的一个很好的模型,但是它仍然有两个问题:
- **有限的上下文依赖:**对于字符级语言建模,发现该模型优于 LSTM。然而,由于模型被设计为在几百个字符的独立固定长度段上进行训练,并且没有在段之间进行关联的信息,这引入了一个问题,即没有保存超过配置的上下文长度的长期依赖信息。有限的上下文相关性也使得该模式不能与几个片段之前出现的任何单词相关联。
- **上下文碎片:**在每个片段的前几个符号中,没有存储上下文信息,因为模型是为每个片段从头开始训练的,这导致了性能问题。
因此,我们仍然需要另一种增强来解决这些问题并克服这些缺点。
Vanilla Transformer with a segment of 4 [source]
变压器-XL
transformer XL 是 transformer 的更新版本(它特别长)。它是从 vanilla Transformer 派生出来的,但是引入了递归机制和相对位置编码。
在 Transformer-XL 中,模型将保留以前学习的段的隐藏状态,并将其用于当前段,而不是从头开始计算每个段的隐藏状态。
该模型解决了传统变压器模型中引入的问题,并克服了长期依赖性问题。另一个优点是,它还解决了由使用最近初始化的或空的上下文信息引起的上下文碎片问题。因此,新模型现在可以用于字符级语言建模和单词级建模。
重现机制
为了保持段之间的依赖性,Transformer-XL 引入了这种机制。Transformer-XL 将像普通的 Transformer 一样处理第一段,然后在处理下一段时保持隐藏层的输出。
递归也可以加快评估速度。我们可以使用先前的分段表示,而不是在评估阶段从头开始计算。
因此,每个图层的输入将是以下内容的串联形式:
- 前一层的输出,与 vanilla Transformer 中的相同(下图中的灰色箭头)。
- 先前处理的隐藏层输出(下图中的绿色箭头)作为扩展上下文。
Transformer-XL with a segment length of 4 [source]
相对位置编码
循环机制似乎可以解决我们所有的问题。然而,递归机制引入了另一个问题:存储在隐藏状态中的位置信息从前面的段中重复使用。
如同在普通转换器中一样,由位置编码步骤提供的位置信息可以使我们从不同的片段中获得一些具有相同位置编码的标记,尽管它们在位置和重要性上有所不同。
该模型中添加的基本概念只是对隐藏状态中的相对位置信息进行编码,足以知道每个键与其查询之间的位置偏移,并且足以进行预测。
变压器 XL 摘要
Transformer-XL 将递归和注意力机制相结合,将遭受上下文碎片和有限上下文依赖的 vanilla transformer 模型转换为词级语言建模,并通过添加递归机制和相对位置编码来提高其评估速度。
这导致长期依赖性增强。根据 Transformer-XL 的原始论文,它可以学习比 RNNs 长 80%的依赖性,比 vanilla transformers 长 450%,并在长序列和短序列上实现比 vanilla transformer 快 1800+倍的更好性能。
该模型在 TensorFlow 和 PyTorch 中实现,可用开源。
压缩变压器
保持所有这些隐藏状态的一个缺点是,它增加了参与每个时间步的计算成本,以及保持所有这些信息的存储成本。
已经创建了几种方法来减少注意力的计算成本,例如稀疏访问机制,但是这并没有解决存储成本。
压缩变压器是变压器的简单扩展,灵感来自睡眠的概念。众所周知,睡眠可以压缩记忆,从而提高推理能力。
压缩变换器利用注意力从过去中选择信息,然后将其压缩到压缩记忆中。这种压缩是通过用损失函数训练的神经网络来完成的,以保持相关信息。
Compressive transformer [source]
压缩功能
建立在变压器 XL 之上。XL 为每个层保留过去的激活,只有当它们过时时才丢弃它们。实现压缩模型是为了压缩旧的内存,而不是丢弃它们。
该模型使用多种压缩函数:
- 最大/平均池。
- ID 卷积。
- 扩张卷积。
- 最常用。
合用被认为是最快和最简单的。最常用的压缩函数受差分神经计算机中垃圾收集机制的启发,数据按其平均使用量存储。卷积压缩函数需要训练一些权重。
压缩变压器总结
压缩变换有助于长程建模。如果这不适用于您的项目,那么压缩变换不会增加任何好处。
从下面的比较中可以看出,结果非常接近 transformer-XL,但是在优化内存使用方面有很大的好处。
Comparison results from the original paper [source]
改革家
用对位置敏感的散列法代替点积注意力,这将模型的复杂度从 O(L2)变为 O(对数),并使用残差层的可逆版本而不是使用标准残差层。这些变化降低了计算成本,并使模型在更快的同时与变压器模型的状态竞争。
结论
仅此而已。我们探索了三种类型的变形金刚模型,希望现在能弄清楚它们为什么会复活。
受人类视觉和记忆的启发,这些模型让我们更接近真正像人脑一样工作的模型。我们离它还很远,但是变形金刚是朝着正确方向迈出的一大步。
感谢阅读!
关于变形金刚的其他资源
机器学习行业中的计算机视觉-12 大最佳资源以及如何使用它们来跟随当前趋势
原文:https://web.archive.org/web/https://neptune.ai/blog/computer-vision-resources
为了站在机器学习的最新趋势的顶端,你需要很快。事情瞬息万变。在计算机视觉中,事情发生得更快。人和机器产生数百万的视觉效果——视频、图像、gif、迷因……
拿这个来说——根据这些统计数据,Instagram 用户每天上传超过 1 亿张照片和视频。那就是**每分钟 69444 万条帖子!**想象一下,为了收集解释和理解视觉世界所需的所有数据,算法需要处理多少张图片。
但是让我们言归正传。有了这些数据,机器学习行业的计算机视觉正在快速发展。因此,为了帮助您掌握最新趋势,我们收集了最好的资源。开始了。
PyImageSearch 是由 Adrian Rosebrock 博士创建的网站,他是专业的计算机视觉/深度学习开发人员和研究员。他创建了这个社区来帮助其他学生、开发者和研究人员提高计算机视觉水平。
他向其他人展示了如何以实用的方式掌握计算机视觉和深度学习,而不是一头扎进理论中
怎么用?浏览一下网站,选择你想做的。您可以从 4 种类型的资源中选择:
- 一步一步的指导开始、变好、掌握计算机视觉、深度学习和 OpenCV。
- 根据你的兴趣浏览不同的 k 主题
- 书籍和课程由 Adrian 编写和创作
- 学生的成功故事通过几个有趣的案例研究和评论来检验它是否是你所需要的
- 博客提供文章、指南、教程或采访
老而金,Reddit 从不让人失望!这个主题是对从图像处理、机器学习到信号处理的各个领域感兴趣或有经验的成员的家园。它帮助人们解决疑问,分享有用的相关信息。
非常简单——使用过滤器快速搜索特定主题,或者让自己沉浸在无限滚动中😉只是要小心,很容易迷失在所有的内容里。
让我们暂时继续关注 Reddit。在这里,你在机器学习线程中搜索与计算机视觉相关的一切。
使用它可以快速查找特定的问题、查询或讨论。您可以将搜索限制在最佳结果、帖子、社区和用户。快速但有效。
谷歌是使用人工智能的先驱之一。那么,为什么不跟随它来查看最新的趋势和信息呢?它拥有来自谷歌人工智能的所有最新消息,并定期更新由谷歌研究人员撰写的新帖子,他们与世界分享他们的工作。
无论你是需要灵感、寻找特定信息,还是只想了解谷歌正在发生的事情,你都可以在博客上自由搜索你想要的东西。使用标签和档案来缩小你的搜索范围。
在这里,你可以找到来自脸书研究人员的见解,他们致力于提高人们对脸书产品的体验。在该网站上,您可以找到有关计算机视觉的最新出版物、文章、新闻和视频。
你可以研究人们,接触他们(名单很长!):
- 浏览出版物,
- 看博客,
- 报名参加活动,
- 甚至找不到工作。
你也可以使用额外的资源——下载和项目,并检查访问研究人员和博士后项目。
Tombone 的计算机视觉博客有关于深度学习、计算机视觉和塑造人工智能未来的算法的一切。
这是要求的绝佳资源。作者是亚马逊机器人人工智能的高级研究科学家,他在博客上发布了很棒的内容并分享了他的知识。
尽管偶尔会有新内容发布,但定期查看博客还是值得的。要么看一些旧帖子,要么等新帖子。这是一个简单的博客,里面有大量有用和有趣的信息。
一个有趣的人写的有趣的博客!它应该在你的计算机视觉和机器学习的最佳资源列表中。作者(拥有计算机视觉博士学位以及神学硕士和哲学硕士学位!)写了关于计算机视觉世界中发生的有趣事情。
为了让你体验一下,下面是博客中排名前五的帖子(根据读者和作者)。
只要看看博客,看看是否有你感兴趣的东西。
分析 Vidhya 是一个网站,在那里你可以找到所有类型的关于 ML 的信息,包括计算机视觉。在这一类别中,你可以阅读不同的关于该主题的深入的、经过充分研究的文章。
请务必查看网站,了解其他有趣的信息、课程和更多内容!
“走向数据科学”是一个受欢迎的媒体社区,它帮助成千上万的人交流思想,并扩大对数据科学的理解。
当谈到计算机视觉时,TDS 有一整个类别专门用于这个主题。不同的作者在扣人心弦的文章中贡献和分享他们的知识和见解。请务必检查它以及其他类别。每天都有新文章出现!
Hackernoon 是计算机视觉爱好者的另一个有用资源。像其他网站一样,它有一个专门针对这个主题的类别。所有的文章都是由这方面的专家写的。
别忘了通过网站查看其他与技术相关的故事!这是所有 ML 爱好者的伟大网站。
谁不知道大名鼎鼎的 KDNuggets!这是最受欢迎的网站之一,在这里你可以找到所有类型的资源。从的文章、的新闻,到的研究论文、和的工作岗位。内容总是新鲜的,引人入胜的,专业的。
这个网站以“计算机视觉”为标签,向你展示所有相关的文章。
你也可以注册他们的时事通讯,以跟上最新的趋势。
在我们的博客档案中,你可以找到由经验丰富的专业人士撰写的关于计算机视觉的文章。看看他们,学习新的技能,加深你的知识,并发现其他人是如何做实验的。
永远新鲜,随时准备好让你下次阅读时拿起它!😉
但这还不是全部!您可以在我们的博客上找到更多不同类别的信息,浏览资源,甚至注册我们的工具来控制您的 ML 实验!
把它包起来
所以正如你所看到的,跟随当前的趋势是很困难的。
有大量的资源、大量的阅读和大量的练习。将您最喜爱的网站加入书签,永远保持领先!
处理概念漂移的最佳实践
原文:https://web.archive.org/web/https://neptune.ai/blog/concept-drift-best-practices
你训练了一个机器学习模型,在几个看起来不错的指标上验证了它的性能,你将它投入生产,然后发生了一些不可预见的事情(像新冠肺炎这样的疫情到来了),模型预测变得疯狂。想知道发生了什么?
你成了一种叫做概念漂移现象的受害者。
但是不要难过,因为我们每个人都会遇到这种情况。
希腊哲学家赫拉克利特说:“变化是生活中唯一不变的东西。”
在动态的世界里,没有什么是不变的。当涉及到数据时尤其如此。从真实来源生成的数据会随着时间的推移改变其基本分布。
例如,考虑电子商务中的产品推荐系统。你认为一个在新冠肺炎之前被训练的模型,在新冠肺炎·疫情期间会同样有效吗?由于这些不可预见的情况,用户行为发生了很大的变化。大多数用户都专注于购买日常必需品,而不是昂贵的小玩意。所以,用户行为数据发生了变化。与此同时,在这种情况下,由于市场上许多产品缺货,我们看到用户的购物模式完全不同。
通常这些数据的变化会使建立在旧数据上的模型与新数据不一致,这个问题被称为“概念漂移”。
在本文中,我们将讨论:
注意:
你可能想看看我们博客上的其他文章:
在一个新的标签中打开它们,然后继续阅读关于概念漂移的内容🙂
漂移这个概念是什么意思?
由于数据流非常不可预测,因此概念漂移是流式数据的最不希望但普遍的属性。由于概念漂移,挖掘技术(如分类或聚类)的性能会随着误分类机会的增加而降低。因此,有必要识别数据中的这种漂移,以获得准确有效的结果。”
(参考:调查大数据流中概念漂移的方法
Fig 1: Life cycle of predictive model
在预测建模中(如上图所示),我们基于历史数据构建一个监督模型,然后使用训练好的模型对看不见的数据进行预测。在这个过程中,模型学习目标变量和输入特征之间的关系。
Fig 2: Trained model failed to correctly predict on out of corpus test data
例如,垃圾邮件分类器,它根据电子邮件的正文预测电子邮件是否是垃圾邮件。机器学习模型学习目标变量(垃圾邮件或非垃圾邮件)和垃圾邮件中出现的关键字集之间的关系。这些关键词集可能不是恒定不变的,它们的模式随着时间而变化。因此,基于旧电子邮件集的模型不再适用于新的关键字模式。如果是这种情况,那么需要对当前数据集进行模型重新训练。
Fig 3: Performance of model over time (Reference)
此图描绘了模型随时间推移的性能,正如您看到的模型性能(通过 F1 分数衡量)随着时间的推移而恶化。这种现象被称为模型衰减。当性能降低到阈值以下时,该模型在重新标记的数据集上重新训练。这就是解决模型衰减问题的方法。如果这个问题得不到解决或监控,那么模型的性能将会不断下降,到某个时候,模型将不再适用。
一般来说,模型衰减可能由于以下类型的移动而发生。
- **协变量移位:**自变量的移位。
- **先验概率移位:**目标变量的移位。
- **概念漂移:**自变量与目标变量之间关系的漂移。
概念漂移与协变量转移
考虑一个在退休人员观看的电影上训练的电影推荐模型,当该模型用于为儿童推荐电影时,它会给出良好的准确性吗?不会的。原因是这两个群体之间的兴趣和活动有很大的差距。所以,这个模型在这些条件下会失效。训练集和测试集中数据分布的这种变化被称为协变量移位。
Fig 4: Difference in distribution between train and test dataset in case of Covariate Shift (Reference)
协变量偏移发生的主要原因是样本选择偏差和非平稳环境。
- 样本选择偏差: It 是指数据收集或标注过程中的系统性缺陷,导致训练样本从待统一建模的总体中不一致地选取。
- **不稳定的固定环境:**当训练环境与测试环境不同时,无论是由于时间还是空间的变化,都会出现这种情况。
协变量转移和概念漂移都是降低模型性能的原因,但两者应该区别对待。因此,必须区分协变量转换和概念漂移,并根据协变量转换或概念漂移或两者的存在进行预防。
数据漂移与概念漂移
在大数据世界中,每时每刻都会产生数十亿的数据。当我们长时间从一个来源收集数据时,数据本身可能会发生变化,这可能是由多种原因造成的。这可能是由于数据中噪声的动态行为,也可能是由于数据收集过程中的变化。
当数据发生变化时,这个问题被称为数据漂移,而目标变量上下文中的变化被称为概念漂移。这两种漂移都会导致模型衰减,但需要分别解决。
概念漂移的例子
- 个性化:无论是电子商务、电影推荐还是个人助理系统,个性化是大多数以客户为中心的企业取得成功的关键。在电子商务中,个性化系统试图描述用户的购物模式,并在此基础上提供个性化的搜索结果或推荐相关产品。由于不可预见的情况,用户的购物行为可能会随着时间的推移而改变,这可能是由于生活事件如结婚、搬迁到不同的地理位置,也可能是由于像新冠肺炎这样的疫情。这个事件彻底改变了用户的购物习惯。由于这些因素,今天构建的个性化系统可能在几年后不再适用,这是由于概念漂移的问题。
- 预测:预测是我们预测未来趋势的一个研究领域。它广泛用于金融、天气和需求预测。通常,这些类型的模型是使用历史数据构建的,并且期望捕捉历史数据中存在的趋势和季节性,以便在未来遵循。但是由于不可预见的情况,趋势可能会改变,这可能会导致概念漂移。在天气数据中,有一种季节性变化发生得极其缓慢。在其他类型的应用程序中,这些类型的更改通常要慢得多。但是,随着时间的推移,它会使现有的模式过时。
如何监控概念漂移
Fig 5: Concept drift monitoring system
下图描述了监控概念漂移的一般方法:
- 首先,收集和整理训练数据集,
- 然后模型在那上面被训练。
- 该模型对照由人类专家管理的黄金数据集进行持续监控。
- 如果性能分数降低到阈值以下,则会触发警报来重新训练模型。
如图 2 所示,主要有 3 种概念漂移,每种现象需要不同的方法来检测(并监控变化)。
Fig 6: Types of concept drift
- 突如其来的:由于不可预见的情况,如新冠肺炎疫情事件影响了电子商务、医疗保健、金融、保险等多个行业,概念漂移突然发生。这种突然的变化可能会在短短几周内发生。这种漂移通常是由一些外部事件驱动的。如果没有主动的监控系统来检测数据漂移,那么在重大事件后对概念漂移的存在进行快速评估是很自然的。
- **渐变:**这种漂移需要很长时间才会发生,对于许多用例来说,这是很自然的事情。例如,通货膨胀可以影响定价模型,而定价模型可能需要很长时间才能产生重大影响。渐进或有时称为增量变化,通常在时间序列模型中通过捕捉季节性变化来解决,如果不解决,这是一个值得关注的问题,需要解决。
- **周期性:**这种漂移是周期性发生的,可能在一年的某个特定时间。例如,在黑色星期五、万圣节等活动期间,用户的购物模式与一年中的其他时间相比有所不同。因此,在该事件期间,使用了专门针对黑色星期五数据训练的不同模型。重复出现的模式很难监测,因为模式的周期性也可能是动态的。
基于存在的概念漂移的类型,有多种方法来监控概念漂移。
一些最突出的方法是:
- 长时间监控模型的性能。例如,可以监控 F1 分数作为准确性指标,如果分数长时间下降,则这可能是概念漂移的信号。
- 监控分类置信度(仅适用于分类)。预测的置信度得分反映了数据点属于预测类的概率。 两个窗口平均置信度得分的显著差异代表概念漂移的发生。
如何防止观念漂移
现在,最大的问题是这个问题是否可以避免,有哪些方法可以防止它的发生。
一个理想的概念漂移处理系统应该能够:
- 快速使适应概念漂移,
- 对噪声具有鲁棒性并将其与概念漂移区分开来,
- 识别并处理模型性能中的重大偏差。
概括地说,有 5 种方法可以解决概念漂移。
- 在线学习当模型一次处理一个样本时,学习者动态更新。事实上,大多数现实生活中的应用程序都是在流数据上运行的,在线学习是防止概念漂移的最重要的方法。
- 定期重新训练可在不同情况下触发的模型,如一旦模型性能下降到指定阈值以下,或一旦两个数据窗口之间的平均置信度观察到重大漂移。
- 定期对有代表性的子样本进行再训练。如果检测到概念漂移的存在,使用类似实例选择的方法选择总体的子样本,其中样本代表总体,并遵循与原始数据分布相同的概率分布。然后,在人类专家的帮助下明确地重新标记这些数据点,并在精选的数据集上训练模型。
- 具有模型加权的集成学习其中多个模型被集成,并且输出通常是单个模型输出的加权平均值。
- 特征丢弃是处理概念漂移的另一种方式。一次使用一个特征建立多个模型,并去除 AUC-ROC 响应不达标的那些特征。
在线学习
在机器学习中,模型通常在批量设置中训练,其中学习者在一批数据上一次性优化。这导致了一个静态模型,该模型假设自变量和目标变量之间的静态关系。因此,经过很长时间后,这种模型可能需要重新训练,以从新数据中学习模式。
在现实生活中,大部分的应用程序工作在实时流数据馈送上,其中模型一次处理一个样本,因此可以动态更新。这个过程被称为在线学习或增量学习,这有助于模型避免概念漂移,因为新数据被用于不断更新模型假设。
这一过程使我们能够从大量数据流中学习,并可以无缝地应用于时间序列预测、电影或电子商务推荐系统、垃圾邮件过滤等应用。
Fig 6: Types of concept drift
在在线学习中,观察一系列实例,一次一个,这些实例在时间间隔上可能不是等间距的。因此,在每个时间戳 t,我们都标记了历史数据,(X [1] ,……X [t] )。使用这些历史数据(X [1] ,…,X [t] )或其子样本来建立一个模型,比如 L [t] 。
当下一个数据点 X [t] +1 到达时,使用 L [t] 预测目标变量(y [t] +1)。一旦下一个实例 X [t] +2 到达,真正的 y [t] +1 就可用了。因此,模型用历史数据(X [1] ,…)更新。X [t] ,X [t] +1)。当不同时间的数据来自不同的来源时,概念漂移的机会增加。很多时候,我们无法区分概念漂移和随机噪声,并将噪声误判为概念漂移。我们在处理噪音时应该非常小心。
注意:
请注意,周期性季节性不被认为是一个概念漂移,除非季节性是不确定的。例如,冰淇淋销售高峰与夏季有关,但根据温度和其他因素,高峰可能在每年不同的时间开始,因此不知道高峰将在何时开始。
Please note periodic seasonality is not considered a concept drift except if the seasonality is not known with certainty. As an example, a peak in sales of ice cream is associated with summer but it can start at a different time every year depending on the temperature and other factors, therefore it is not known exactly when the peak will start.
Creme 是一个用于在线机器学习的 python 库,其中模型每次从单个观察中学习,并可用于从流数据中学习。这是在线学习可用的奇妙工具之一,帮助我们保持模型远离概念漂移。
模型再训练
应对概念漂移的另一种方法是定期重新训练模型,从历史数据中学习。如果模型观察到概念漂移,则应该用最近的数据重新训练模型。
例如,财务领域的应用程序可能需要在四月的第一周进行重新培训,以适应财务年末的变化。另一个例子可能是由于流行病引起的用户偏好的突然改变。
困难的部分是检测何时需要模型重新训练,但正如我们之前讨论的,有很多方法可以做到这一点。在任何情况下,一旦检测到漂移,我们就根据新数据重新训练模型,以纳入变化的条件。
这个过程可能是昂贵的,因为在监督设置中,额外的数据点需要被重新标记。因此,与其在整个数据集上重新训练,不如考虑从全部人口中有选择地创建一个子样本,并在其上重新训练。这种方法将在下一节讨论。
使用实例选择进行重新采样
实例选择的概念是通过保持基本分布不变从总体中选择一个子集,以便采样数据能够代表整个数据总体的特征。
简而言之,我们的想法是:
选择一个微小但有代表性的总体样本(使用实例选择之类的方法)
对子样本运行模型
- 找出子样本中模型性能不达标的数据点。
- 在运行实例选择时,我们维护一个代表性样本和该样本所代表的数据点组之间的映射。一旦我们(从微小的子样本中)找出了模型性能不好的观察结果列表,我们就会考虑这些样本所代表的所有数据点,并在这些数据点上重新训练模型。
- 模型加权集成学习
- 集成学习 保持多个模型的集成,进行组合预测。通常,最终预测是单个预测的加权平均值,其中权重反映了单个模型在最近数据上的表现。
集成学习方法背后的动机是,在变化期间,数据可能从多个分布的混合中生成。多个模型的集合,其中每个模型单独地试图表征数据分布以及特征和目标变量之间的关系,应该工作得更好。
基于模型更新的方式,集成学习有不同的变化。一种方法是,对于每一批新的数据,使用动态加权多数表决策略来训练和组合新的分类器。
特征丢弃
特征丢弃是处理概念漂移最简单有效的方法之一,在业界得到了广泛的应用。想法是建立多个模型,每次使用一个特征,保持目标变量不变。对于每个模型,在对测试数据进行预测后,监测 AUC-ROC 响应,如果特定特征的 AUC-ROC 值超过特定阈值(可能为 0.8),则该特定特征可能被认为是漂移的,因此该特征可能被丢弃。
处理概念漂移的最佳实践
近来,在该领域进行了大量研究,但没有一个事实上的标准算法或方法来处理概念漂移。也就是说,在我处理这些问题的过程中,我实现了以下端到端流程,可以检测和防止概念漂移的出现:
第一步:数据收集和预处理:
这个步骤包括处理缺失值、异常值、分类变量的标签编码等等。
第二步:数据标注:
I)将数据流分成一系列窗口。
iii)根据业务环境为各个数据点分配一个类别标签。
步骤 3:概念漂移的检测:
I)分析相邻窗口的数据点以识别概念漂移。可以分析准确性度量,如准确性、精确度、召回率、AUC-ROC 响应曲线和执行时间、分类或聚类误差,以便检测概念漂移。
第四步:避免或消除概念漂移:
如果检测到概念漂移的存在,遵循适当的方法来消除它。
最后的想法
概念漂移是机器学习和数据挖掘中的一个重要问题,应该小心处理。
最大的问题是如何检测概念漂移的存在,因为没有放之四海而皆准的解决方案。它是在很多难以琢磨的隐藏因素存在的情况下发生的。大多数与“概念漂移”相关的方法对于问题的本质来说是非常主观的。然而,使用本文中提到的方法,可以作为构建基线系统来检测和防止概念漂移的很好的参考。
**在这个主题中有大量的研究正在进行,这些研究主要是围绕开发检测关键变化的标准。需要更多的研究来建立一个健壮的系统,该系统可以基于不同种类的概念漂移和不同水平的噪声来触发警报。
参考资料:
希布桑卡尔达斯
一位高级数据科学家@ WalmartLabs,在此之前,他曾在 Envestnet | Yodlee、微软研究院和凯捷工作。他曾被《印度分析》杂志授予“40 名 40 岁以下数据科学家”,因为他在基础机器学习和分析方面展示了专业知识,特别是在深度学习、生成模型和深度强化学习方面。
阅读下一篇
进行 ML 模型监控的最佳工具
7 分钟阅读| Jakub cza kon | 202221 年 1 月 31 日更新
Best Tools to Do ML Model Monitoring
如果您迟早将模型部署到生产中,您将开始寻找 ML 模型监控工具。
当你的 ML 模型影响业务时(它们应该影响),你只需要了解“事情是如何工作的”。
你第一次真正感觉到这一点是当事情停止工作的时候。在没有建立模型监控的情况下,您可能不知道哪里出了问题,也不知道从哪里开始寻找问题和解决方案。人们希望你尽快解决这个问题。
但是在这个上下文中“事物”和“工作”是什么意思呢?
有趣的是,根据团队/问题/管道/设置的不同,人们的意思完全不同。
在一家 MLOps 公司工作的一个好处是你可以和许多 ML 团队交谈并获得第一手信息。因此,事实证明,当人们说“我想监控 ML 模型”时,他们可能想:
监控模型在生产中的表现:查看模型的预测准确度。看看模型性能是否随时间衰减,你应该重新训练它。
监控模型输入/输出分布:查看进入模型的输入数据和特征的分布是否改变?预测的阶级分布是否随时间而改变?这些事情可能与数据和概念漂移有关。
- 监控模型训练和再训练:在训练和再训练期间,查看学习曲线、训练模型预测分布或混淆矩阵。
- 监控模型评估和测试:为您的自动化评估或测试管道记录度量、图表、预测和其他元数据
- 监控硬件指标:查看您的模型在训练和推断过程中使用了多少 CPU/GPU 或内存。
- 监控 CI/CD 管道的 ML :查看您的 CI/CD 管道作业的评估,并进行直观比较。在 ML 中,度量标准通常只能告诉你这么多,需要有人实际看到结果。
- 你指的是哪个 ML 模型监控?
- 无论哪种方式,我们都将研究有助于所有这些用例的工具。
但是首先…
显然,根据您想要监控的内容,您的需求会发生变化,但是在选择 ML 模型监控工具之前,您应该明确考虑一些事情:
易于集成:将其连接到您的模型培训和部署工具有多容易
灵活性和昂贵性:你能记录并看到你想要什么以及你想如何得到它吗
- 开销:日志记录给你的模型训练和部署基础设施带来了多少开销
- 监控功能:能监控数据/特征/概念/模型漂移吗?你能比较同时运行的多个模型吗(A/B 测试)?
- 警报:当性能或输入变得疯狂时,它是否提供自动警报?
- 好了,现在让我们来看看实际的模型监控工具!
- alerting: does it provide automated alerts when the performance or input goes crazy?
Ok now, let’s look into the actual model monitoring tools!
用 PyTorch 中的连体网络实现基于内容的图像检索
图像检索是寻找与给定查询相关的图像的任务。对于基于内容的图像检索,我们指的是找到包含一些属性的图像的任务,这些属性不在图像元数据中,但存在于其视觉内容中。
在本帖中,我们:
- 解释基于内容的图像检索背后的理论概念,
- 逐步展示如何用 PyTorch 构建一个基于内容的图像检索系统,解决一个特定的应用:寻找具有一组给定人脸属性(即男性、金发、微笑)的人脸图像。
排序损失,对比损失,连体网,三联网,三联损失,图像检索
得益于 PyTorch + Neptune 集成,您可以如何跟踪您的模型训练。
基于内容的图像检索:如何在高层构建
为了找到最接近给定查询的图像,图像检索系统需要:
- 计算测试集(通常称为检索集)中的所有图像与查询之间的相似性得分。
- 根据与查询的相似性对所有这些图像进行排序,
- 退回最上面的。
学习这些相似性的常见策略是学习图像和查询在同一向量空间(通常称为嵌入空间)中的表示(通常称为嵌入)。
在我们的例子中,这将是学习人脸图像的嵌入和在同一空间中编码人脸属性的向量。
神经网络用于学习上述嵌入。在我们的例子中,卷积神经网络(CNN)用于学习图像嵌入,多层感知器(MLP)是一组完全连接的层,用于学习属性向量嵌入。
这些网络以连体方式建立,并以排序损失(在我们的例子中是三联损失)进行训练。接下来我们将深入解释这些概念。
架构和损失
排名损失:三重损失
排序损失旨在学习样本之间的相对 T2 距离,这项任务通常被称为 T4 度量学习。
为此,他们计算样本表示之间的距离(即欧几里德距离),并优化模型以最小化相似样本的距离,最大化不同样本的距离。因此,模型最终会学习您定义为相似的样本的相似表示,以及您定义为不相似的样本的距离表示。
三重损失是最常用的排名损失。它处理三个一组的样本,包括:
锚样(三联体的参考样品)。
- 阳性样本(与锚相似)。
- 阴性样本(与锚不同)。
- 三元组损失优化了模型,使得负样本和锚样本表示之间的距离比锚样本和正样本表示之间的距离大一个裕度。
边缘的功能是当模型充分区分三个一组的阳性和阴性样本时,不浪费努力来扩大分离,以便它可以集中于更困难的三个一组。
换句话说:当给定三元组的网络性能已经是最佳时,余量建立。
三重态损耗正式定义为:
L(a,p,n) = max(0,m + d(a,p)-d(a,n))
其中:
d 是使用的距离函数(即欧几里德距离),
- m 是余量,
- a、p 和 n 分别是锚、阳性和阴性样本的表示。
- 在我们面对按属性检索的例子中:
锚样本是一个图像,
- 正样本是编码其属性的向量,
- 负样本是一个属性不匹配的向量。
- 因此,该模型将被优化以在嵌入空间中靠近其属性向量嵌入该图像,而远离其他属性表示。在测试阶段,当您使用属性向量进行查询以检索包含这些属性向量的图像时,您将会发现嵌入在它附近的图像。
简单、坚硬和半坚硬的三胞胎
根据三元组样本之间的距离,在损失计算期间,我们可以有三种不同类型的三元组:
简单三联体:与阳性样本相比,阴性样本与锚定样本的距离足够远。损失为 0,梯度也是。
- d(a,n) > (d(a,p) + m)
硬三元组:负样本表示比正样本表示更接近锚样本表示。网络不能正确地区分这个三联体的阳性和阴性样本。
- d(a,n) < d(a,p)
半硬三连音:负样本表示比正样本表示离锚更远,但距离之间的差异不大于边距。因此,网络必须把它们拉得更远。
- d(a,n) < (d(a,p) + m)
暹罗网
分级损耗通常用于连体网络架构。暹罗网络是共享参数的神经网络,也就是共享权重。实际上,这意味着在训练过程中,我们优化单个神经网络,尽管它处理不同的样本。
在我们通过属性检索人脸图像的例子中,每个三元组包含一个图像(锚点)和两个属性向量(正面和负面)。
处理属性向量的网络将是连体的,这意味着我们将使用同一个网络来转发它们。这是因为我们想要为正负属性向量学习相同的特征提取器。
py torch 中的三重态丢失
PyTorch 提供了三重损失的实现,称为三重边际损失,您可以在这里找到。
该文档使用与本文相同的术语。默认情况下,它使用欧几里德距离来计算输入张量之间的距离。你可以试着把它改成其他的距离,但是从我的经验来看,这并没有太大的区别。
您可以通过导入 Pytorch 神经网络库并设置边距来实例化它:
对于模型的收敛来说,确切的差值并不重要。
import torch.nn as nn
criterion = nn.TripletMarginLoss(margin=0.1)
也就是说,您需要确保由损耗计算的距离差在您设置的值附近。一个好的做法是设置一个界限,使得在训练开始时,一半的三元组是随机正确的,而另一半是不正确的。常用的值是 0.1。
要在模型计算了三联体样本的表示后计算训练循环中的损失,您应该调用:
其中三元组样本表示总是按照该顺序。
loss = criterion(anchor, positive, negative)
loss.backward()
利用 Pytorch 中的三重损失进行人脸图像检索
目标:找到具有某些属性的人脸图像
本示例任务中的目标是找到具有特定属性的人脸图像。为了做到这一点,我们将使用一个带有注释二进制属性的人脸图像数据集。
使用的数据集是大规模名人脸属性(CelebA)数据集,它包含大约 200,000 张名人脸图像和 40 个带注释的二进制属性。属性被编码为 40 维多热点向量,其中包含 1 来指示正面的人脸图像属性,包含 0 来指示其余的属性。
为了让您对带注释的属性有所了解,让我列出几个:
眼袋
- 尖鼻子
- 髭
- 戴耳环
- 戴项链
- 鹅蛋脸
- 最终的图像检索系统旨在找到具有这些属性的给定组合的人脸图像。这里您可以看到数据集中的一些图像示例:
如何创建训练三元组
训练该系统在给定人脸属性的情况下检索人脸图像的三元组将包括:
一个图像(它是锚),
- 它的属性向量(正的),
- 和一个负属性向量(负的)。
- 因此,要创建三元组的锚和正样本,只需加载一个图像及其属性,并将其放入张量中。
接下来,您需要为我们的三元组选择负面属性。你可以只是:
创建一个随机多热点 40 维向量,
- 检查与正向量不同的向量,
- 用它做反面。
- 但是**你最终会得到太多简单的三胞胎,**考虑到许多负面属性向量不太可能出现:例如(“女人”+“金发”+“有胡子”)。因此,模型很容易确定哪一个是正属性向量,并且它不会学习正确区分可能的属性向量。
保存数据集统计数据的通用策略是:
从训练数据中采样随机属性向量,
- 检查它是否不同于我们的正向量,
- 用它做反面。
- 如果
self.attribute_vectors
包含所有训练集属性:
一个创建硬负的策略,可以和上一个结合,就是从正属性向量中改变一些属性。举个例子:
while True:
att_negative = random.choice(self.attribute_vectors)
if not np.array_equal(att_n, att_positive):
break
用这些硬负三元组训练迫使模型区分除了 1、2 或 3 之外所有属性都相似的属性向量。
num_changes = random.randint(1,3)
att_negative = np.copy(att_positive)
for c in range(0,num_changes):
att_idx = random.randint(0,len(att_negative) - 1)
if att_positive[att_idx] == 0:
att_negative[att_idx] = 1
else:
att_negative[att_idx] = 0
如何设计模型并训练它
您需要一个神经网络架构,它可以在同一个向量空间(嵌入空间)中学习图像和属性向量嵌入,这样我们就可以计算它们之间的距离和三元组损失。
你需要做的第一件事是选择嵌入空间的维数。这取决于你想要学习的相似性的复杂程度,但是典型的维度范围是从 100 到 500。我们会选 300。
下图显示了我们将使用的架构:
为了学习图像嵌入,我们使用 CNN(即 ResNet-50),其输出数量与嵌入空间维数相同。该 CNN 将图像张量(img_a,它是我们三元组的锚)[224x224x3]作为输入,并输出 300-D 向量(a)。
为了学习属性向量嵌入,我们使用了一个由两个 300-D 线性层组成的 MLP ,其具有批量标准化和 ReLU 激活。我们的三元组的正样本和负样本都是属性向量,我们将使用相同的层来处理它们,这就是所谓的连体架构(如图中黄色所示)。
一旦计算出图像和属性向量的嵌入,我们就对它们进行 L2 归一化,以确保它们具有相同的欧几里德范数,并将它们输入到三元组损失中,以计算它们之间的距离。在 PyTorch 中,我们可以将训练循环写成:
注意att_positive
和att_negative
是由同一个 MLP 处理的:我们为它们使用了暹罗网络。
anchor = self.CNN(img_anchor)
positive = self.MLP(att_positive)
negative = self.MLP(att_negative)
loss = criterion(anchor, anchor, negative)
optimizer.zero_grad()
loss.backward()
optimizer.step()
如何监控培训
当使用三元组损失来训练图像检索模型时,比在其他情况下更难监控训练,例如当训练用于图像分类的网络时。这是因为测试图像检索需要整个数据集的图像嵌入。
除了直接监控训练和验证损失(这当然会显示模型是否正确学习)之外,在训练和验证期间,监控每批正确三元组的数量也是有用的。
随着损失的减少,在学习期间,每批的正确三联体(易否定)的百分比应该增加。此外,这个百分比给了你一个暗示,三胞胎上网有多难。
如果很高比例的三元组已经是正确的,网络没有从他们那里学到任何东西,所以转发他们是一种计算浪费,也许你应该修改你的三元组创建管道来创建更难的三元组。
使用训练好的模型进行图像检索
一旦模型被训练,使用它进行图像检索是简单的。您应该:
计算所有检索集图像的嵌入,并将它们保存到磁盘。
- 计算查询的嵌入(属性向量)
- 计算查询嵌入和所有检索集图像之间的距离。
- 找最近的。
- 结果?
让我们看一下针对不同属性查询的建议模型的一些结果:
看起来相当不错!
如何评价一个图像检索模型
基于内容的图像检索系统通过检查它们针对一组查询检索的图像是否包含期望的属性来进行评估。
文献中使用了不同的指标,这取决于任务和您想要评估的系统特性。这可能会令人困惑,所以让我解释两个最常用的
Precision@K (P@K):它只考虑前 K 个(通常是 1、5、10 或 100 个)检索到的图像。当您只对正确检索有限数量的图像感兴趣时(推荐系统),或者当检索集太大而无法评估所有排名时,可以使用它。如果检索到的图像包含查询属性,则认为它是正确的。
P @ K = Top K/K 中的正确结果
- 当报告一组查询的平均 P@K 时,这个指标有时被写成 AP@K。
平均精度(mAP):它考虑了所有检索集的排序。它为 k=1,2,…,N 计算 P@K,N 是具有查询属性的检索集图像的数量。然后,它平均所有的精度。这个度量的计算成本更高,也更不直观,但是它可以深入地评估一个检索系统。
- 什么可能出错:要避免的事情和最佳实践
一如既往,有太多的事情可能会出错,所以让我分享一下我的经验教训:
设置余量:如果在训练开始时,损失减少,但正确的三胞胎数量没有增加,可能是您设置了过大的余量。一个好的做法是设置余量,这样当你开始训练时,一些三连音可能已经是正确的了。
监控正确的三元组并使用硬否定:如果你的批处理中的大多数三元组已经是正确的,修改你的三元组挖掘策略以使用更硬的否定,因为你的模型没有从它们那里学到任何东西。但是,请注意保留数据集的统计数据。
也许你只是想在你的批次中使用给定百分比的硬三元组:这高度依赖于你的问题,但如果你的三元组不现实,你可能最终会训练你的网络来区分你在任何现实场景中找不到的样本。
在检索过程中计算距离:确保您使用的距离函数与丢失时使用的距离函数相同。也就是说,如果损失使用欧几里德距离,您也应该在检索时使用它。
检索效率:如果您将检索集图像嵌入加载到您的 GPU 中,并使用 CUDA 中的查询计算距离,对于大型数据集,检索将会快得多。
最后的想法
基于内容的图像检索是通过图像的内容找到图像的任务。
排序损失允许神经网络通过比较样本在向量空间中的表示来学习样本之间的距离。
- 暹罗网络是最常见的分级损失训练架构。在该架构中,不同的样本在每次迭代中通过相同的层转发。
- 所使用的否定选择策略对于高效训练和更好的表现非常重要。
- 监控每批正确三联体的数量有助于确保模型被正确训练。
- 额外资源
- Monitoring the number of correct triplets per batch is helpful to ensure the model is being trained properly.
Additional resources
具有深度强化学习的连续控制
这一次我想探索如何深入利用强化学习,例如让一个人形模型行走。这种任务是连续控制任务。这种任务的解决方案不同于你可能知道并使用深度 Q 网络(DQN)玩 Atari 游戏(如 Pong)的方案。
我将讨论连续控制环境的特征。然后,我将向您介绍演员-评论家架构,并展示最先进的演员-评论家方法,软演员-评论家(SAC)的例子。最后,我们将深入研究代码。我将简要解释它是如何在令人惊叹的 SpinningUp 框架中实现的。我们走吧!
什么是持续控制?
Continuous Control with Deep Reinforcement Learning | Source: Roboschool
遇见人形。它是一个三维的两足机器人环境。它的观测值是描述机器人运动学属性的 376 维向量。它的动作是 17 维向量,指定施加在机器人关节上的扭矩。目标是尽可能快地向前跑…并且不要摔倒。
动作是连续取值的向量。这与您可能已经从 Atari 环境中知道的一组固定的可能操作非常不同。它需要一个策略,不返回所有可能操作的分数或质量,而只返回一个要执行的操作。不同的策略输出需要不同的培训策略,我们将在下一节探讨这一点。
什么是 MuJoCo?
MuJoCo 是一个快速精确的物理模拟引擎,旨在研究和开发机器人、生物力学、图形和动画。OpenAI Gym 及其包含的人形环境利用它来模拟环境动态。我在这里写了关于安装和使用它的整个帖子。对于这个帖子,我们不需要这个。
不符合政策的行动者-批评家方法
Reinforcement Learning | Source: Sutton & Barto, Reinforcement Learning: An Introduction, 2nd edition
让我们回顾一下:强化学习(RL)是学习做什么——如何将情况映射到行动——以最大化某种累积奖励的概念。RL 由一个为了学习而在环境中活动的代理组成。环境对每个代理的动作提供响应,并反馈给代理。奖励被用作强化信号,而状态被用来制约代理人的决策。
真正的目标是找到一个最优的政策。策略告诉代理在它发现自己处于任何状态时应该如何表现。这是代理对环境目标的映射。
如上图所示,演员-评论家架构将代理分为两部分,演员和评论家分别为和。
- 参与者代表策略——它学习从状态到动作的映射。
- 评论家代表 Q 函数——它学习评估每个动作在每个可能的状态下有多好。你可以看到演员利用评论家的评价来改进政策。
为什么要使用这样的构造?如果你已经知道 Q-Learning ( 这里你可以了解它),你知道训练 Q-函数对于解决 RL 任务是有用的。Q 函数会告诉你每个动作在任何状态下有多好。然后,您可以简单地选择最佳行动。当你有一套固定的行动时,很容易做到,你只需简单地评估每一个行动,然后选择最好的!
然而,在一个动作是连续的情况下该怎么办呢?你不能评估每一个值,你可以评估一些值并选择最好的,但它会产生自身的问题,例如分辨率——评估多少个值以及评估哪些值?演员就是这些问题的答案。它近似离散情况下的 argmax 算子。它只是被训练来预测最好的行动,如果我们能和批评家一起评估每一个可能的行动。下面我们描述软演员评论家(SAC)的例子。
伪代码中的 SAC
SAC 的批评者是经过训练的非政策,这意味着它可以重用由旧的、训练较少的政策收集的数据。第 11-13 行中的政策外批评家训练利用了与 DQN 非常相似的技术,例如,它使用目标 Q 网络来稳定训练。不符合策略的方法比符合策略的方法(如 PPO )样本效率更高,因为我们可以构建经验重放缓冲区,其中每个收集的数据样本都可以多次重复用于训练——与符合策略的训练相反,符合策略的训练仅在一次更新后就丢弃数据!
您可以在第 1 行看到 critics 和 replay buffer 被初始化,在第 2 行看到 target critics。我们用两个批评家来对抗论文中描述的高估误差:“双 Q-learning”和“Actor-Critic 中的寻址函数近似误差”,你可以在这里了解更多。然后,在第 4-8 行中收集数据并提供给重放缓冲区。第 14 行更新策略,第 15 行更新目标网络。
您可能会注意到评论家和演员的更新都包括一些额外的日志术语。这是最大熵正则化,防止代理人过多地利用其可能不完美的知识,并奖励有前途的行动的探索。如果你想详细了解它,我推荐你阅读这个资源。
代码中的软演员评论家
我们将在深度 RL-TF2 实施框架中与一起工作。repo 自述文件中有安装说明。注意,你暂时不用安装 MuJoCo。我们将在 OpenAI Gym suite 的 Pendulum-v0 环境中运行一个示例软演员-评论家代理。让我们投入进去吧!
钟摆 v0 环境
摆-v0 是连续控制环境,其中:
行动 | 一维中只有一个关节的扭矩 |
---|---|
三维向量,其中前两维代表摆的位置——它们是摆角的 cos 和 sin 第三维是摆角速度
你可以把它想象成类似人形的更复杂的机器人的简化模型。人形机器人由许多相似的二维或三维关节组成。
培训 SAC 代理
在回购中,SAC 代理代码是这里是。core.py 文件包括演员-评论家模型的工厂方法和其他实用程序。sac.py 包括重放缓冲区定义和上述训练算法的实现。我建议您浏览一下,并尝试将上面的伪代码行映射到该文件中的实际实现。然后,检查我的列表:
- 伪代码的第 1-2 行的初始化在 sac.py 的第 159 行–179 行中实现,
- 伪代码的第 3 行的主循环在 sac.py 中的第 264 行实现,
- 伪代码第 4-8 行的数据收集在 sac.py 中的第270–295行实现。
- 伪代码第 9-11 行的更新处理在 sac.py 的第 298 行–300 行中实现,
- 伪代码第 12-15 行的参数更新在 sac.py 的第 301 行调用,在第192–240 行实现。
- sac.py 中的其余代码主要是日志处理和一些样板代码。
Pendulum-v0 环境中的示例训练是在 repo 根中的 run_example.py 中实现的。简单地像这样运行它:python run_example.py。在训练之后——或者在 200,00 0 个环境步骤之后——训练将自动完成并在。/out/checkpoint 目录。
下面是培训开始和结束时的日志示例。请注意 AverageTestEpReturn 是如何变小的——从一个巨大的负数变到接近零的值,这是最大回报。回报是负的,因为代理人因为钟摆不在目标位置而受到惩罚:垂直,零角速度和零力矩。
在我配有英特尔 i5 处理器的 MacBook 上,培训耗时 482 秒(约 8 分钟)。
训练前
---------------------------------------
| AverageEpRet | -1.48e+03 |
| StdEpRet | 334 |
| MaxEpRet | -973 |
| MinEpRet | -1.89e+03 |
| AverageTestEpRet | -1.8e+03 |
| StdTestEpRet | 175 |
| MaxTestEpRet | -1.48e+03 |
| MinTestEpRet | -1.94e+03 |
| EpLen | 200 |
| TestEpLen | 200 |
| TotalEnvInteracts | 2e+03 |
| AverageQ1Vals | -4.46e+03 |
| StdQ1Vals | 7.1e+04 |
| MaxQ1Vals | 0.744 |
| MinQ1Vals | -63.3 |
| AverageQ2Vals | -4.46e+03 |
| StdQ2Vals | 7.11e+04 |
| MaxQ2Vals | 0.74 |
| MinQ2Vals | -63.5 |
| AverageLogPi | -35.2 |
| StdLogPi | 562 |
| MaxLogPi | 3.03 |
| MinLogPi | -8.33 |
| LossPi | 17.4 |
| LossQ1 | 2.71 |
| LossQ2 | 2.13 |
| StepsPerSecond | 4.98e+03 |
| Time | 3.8 |
---------------------------------------
训练后
---------------------------------------
| AverageEpRet | -176 |
| StdEpRet | 73.8 |
| MaxEpRet | -9.95 |
| MinEpRet | -250 |
| AverageTestEpRet | -203 |
| StdTestEpRet | 55.3 |
| MaxTestEpRet | -129 |
| MinTestEpRet | -260 |
| EpLen | 200 |
| TestEpLen | 200 |
| TotalEnvInteracts | 2e+05 |
| AverageQ1Vals | -1.56e+04 |
| StdQ1Vals | 2.48e+05 |
| MaxQ1Vals | -41.8 |
| MinQ1Vals | -367 |
| AverageQ2Vals | -1.56e+04 |
| StdQ2Vals | 2.48e+05 |
| MaxQ2Vals | -42.9 |
| MinQ2Vals | -380 |
| AverageLogPi | 475 |
| StdLogPi | 7.57e+03 |
| MaxLogPi | 7.26 |
| MinLogPi | -10.6 |
| LossPi | 61.6 |
| LossQ1 | 2.01 |
| LossQ2 | 1.27 |
| StepsPerSecond | 2.11e+03 |
| Time | 482 |
---------------------------------------
可视化经过培训的策略
现在,保存了训练好的模型,我们可以运行它,看看效果如何!运行此脚本:
python run_policy.py --model_path ./out/checkpoint --env_name Pendulum-v0
在回购根中。你会看到你的经纪人接连播放 10 集!是不是很酷?你的代理人受过训练能完美地垂直调整钟摆吗?我的不是。你可以试着玩玩 run_example.py 文件中的超参数(代理的函数参数),让代理找到更好的策略。小提示:我发现早点结束训练可能会有帮助。所有超参数都在 sac.py 文件中的 SAC 的 docstring 中定义。
你可能会奇怪,为什么每一集都不一样?这是因为每次环境重置和新一集开始时,初始条件(钟摆起始角度和速度)都是随机的。
结论
你的下一步是在一些更复杂的环境中训练 SAC,如人形或 MuJoCo 套件中的任何其他环境。 安装 MuJoCo 与 OpenAI 健身房环境一起工作 是我写的关于如何安装 MuJoCo 并访问这些复杂环境的指南。它还描述了要跟踪的有用诊断。你可以在强化学习框架中的 日志中了解更多关于记录这些诊断的信息——你需要知道的 。也有其他实现算法的框架可以解决连续控制任务。在这篇文章中阅读它们: 强化学习的最佳基准:终极清单 。感谢您的参与,下次再见!
为什么您应该在您的机器学习项目中使用持续集成和持续部署
持续集成(CI)、持续交付(CD)和持续测试(CT)是机器学习操作(MLOps)原则的核心。如果你是一名数据科学家或机器学习工程师,知道 DevOps 原则,在这篇文章中,我将向你展示如何将它们应用于 ML 工作流。
如果你是投资于数据科学团队的 It 业务领导者,并且愿意扩展他们的 ML 能力,这也可能是有用的。MLOps 可能是为您的业务带来重大价值的下一步,可以加快任何机器学习项目的开发和实施阶段。
MLOps 为整个项目工作流程带来了透明度。它通过监控机器学习系统的所有步骤来做到这一点。透明性使得检测可能隐藏的瓶颈和缺陷变得容易。知道了问题在哪里,我们就可以提出行动计划,并衡量预防措施的效果。
DevOps 和 MLOps 有什么不同?
DevOps 是软件开发中众所周知且广泛使用的实践。它被证明是可行的,并让团队缩短开发周期,使发布更加顺畅和快速。然而,从一开始就很清楚,我们不能将 DevOps 原则直接应用于机器学习,因为 ML 在本质上是不同的。
机器学习是高度实验性的:我们尝试不同的算法、参数和特征,以从我们的模型中获得最大的收益。ML 工程师必须做大量的实验,并且需要跟踪实验和它们产生的结果,看看什么有效,同时保持代码的可再现性和可重用性。
我们都知道机器学习是关于数据的。ML 工程师可能需要花费大量时间来进行探索性数据分析(EDA),提出特性工程或模型开发的方法——这些是传统软件工程师永远不会做的事情。ML中侧重点不同,这也是 DevOps 实践在这里会失败的另一个原因。
机器学习是一个高节奏的环境,快速发展导致淘汰率增加。作为工程师,我们希望尽可能快地采用这些变化,以保持我们的模型是最新的。所有这些都使得实验驱动的开发变得更加重要,同时也需要跟踪和比较。
测试的方法也不同。与传统的软件测试相比,需要执行其他测试设置:确保数据验证,并进行模型评估。
部署不同。例如,部署 ML 模型不同于部署基于基本模型的预测服务。构建一个部署管道是一件相当不容易的事情,但是它是值得的,让我们构建一个在重新训练之后自动部署模型的系统。目前,许多企业还没有这样的部署系统,因此自动化的潜力是巨大的。
最后但同样重要的是,生产阶段。ML 工程师知道什么是概念漂移,以及它如何随着时间的推移导致模型退化。由于数据配置文件的自然演变,这种情况经常发生。我们不仅需要监控生产模型的性能,还需要在准确性下降时做好改进的准备。
面对 MLOps 的挑战,我们能做些什么
意识到你现在在哪里
Google 通过一组三个层次来定义组织中 ML 过程的成熟度。每个级别“反映了在给定新数据的情况下训练新模型或者在给定新实现的情况下训练新模型的速度。简单地说,根据机器学习管道的自动化程度,自动化水平可以分为三个级别。
谷歌表示,最常见的级别是 MLOps 级别 0——没有自动化,主要是脚本驱动的方法,机器学习工作流程中的大多数步骤都是手动执行的。MLOps 级别为 0 的组织最常见的挑战与部署的模型有关,根据 Google 的说法,“无法适应环境动态的变化,或描述环境的数据的变化”。
这是因为模型很少随着时间的推移而改变和重新训练。生产环境中较差的性能监控使工程师无法跟踪不必要的变化。
MLOps 级别 1 是机器学习管道的自动化方法,该级别的团队"自动化使用新数据在生产中重新训练模型的过程,并执行"连续交付模型预测服务"。
最高的第 2 级是全自动 CI / CD 系统。这是一个我们每个人都应该考虑的基准,并且理想情况下最终会达到。
当在我的团队中提出 MLOps 的问题时,我们处于零步骤。经过几个月和一些变化,我们能够从 0 级推进,并向 MLOps 级迈出第一步。
我将告诉你什么在我们的案例中起了作用,以及我们观察到了什么积极的变化。如果你刚刚开始在机器学习中使用 CI / CD,并希望向自动化的 ML 系统实现迈进,我们的经验一定会帮助你。我们才刚刚开始,离谷歌表现最好的管道还很远,但我们所做的已经给了我们巨大的改进,我很高兴与你分享。让我们开始吧!
定义一系列你最关心的问题
当我们开始的时候,很明显我们的机器学习工作流程并不完美。但是到底是什么问题呢?我们需要慢慢来,正式定义它们。经过几个小时的头脑风暴,我们发现了一系列需要首先解决的问题:
- 我们监控和处理生产模型的方式由于输入数据的发展而衰退(概念和数据漂移,培训服务偏差);
- 缺乏实验跟踪控制,导致我们开发中的可重复性、可重用性和可比性降低;
- 低开发速度阻碍了我们使用尖端技术。我们希望加快测试新算法(架构/配置)的速度,并且足够快,这样就可以快速找到对特定问题最有效的方法。
我们决定将我们的重点限制在上述问题上,并着手解决它们。限制很重要,因为就像古老而真实的习语所说的那样——“一次吃一头大象”。我们决定先从 MLOps 大象身上咬三口,上面的列表是我们该怎么做的指南。
MLOps 级的大部分 ML 团队都存在以上三个问题。所以,你可以完全采用上面的要点来工作,或者改变它们来反映对你和你的队友来说最重要的,应该首先解决的问题。慢慢来,想想在你的环境中什么是重要的。
这是一个重要的结论,来自我们对减轻痛苦的工具的长期寻找:【MLOps 和跟踪解决方案的市场相当不成熟,所以很有可能没有工具可以消除你的所有问题。
即使是最好的可用解决方案也在开发中,无法解决您可能遇到的所有问题。现在,我们只需要接受这一点。所以,不要投入大量的时间去寻找完美的工具,因为你不会找到。
相反,我建议你买一个至少能解决你现有问题 70%的工具。相信我,这是一个很大的问题。
经过一段时间的研究,我们团队决定使用 neptune.ai 。我们想尝试解决我们的问题。数据科学家和机器学习工程师已经知道它是一种很有前途的实验跟踪工具,具有记录的潜力,可以加快我们的合作开发,并提高可重复性和可重用性。
进行试点实验,看看结果
当我们找到合适的工具来测试和采用新的原则时,海王星的试点实验就开始了。
第一个也是最重要的变化是我们如何进行假设检验(即进行实验并跟踪它们)。我们从 TensorBoard(我们使用 TensorFlow / Keras 作为框架)转移到 Neptune,因为它提供了更广泛的选择。这改变了很多——我在另一篇专门比较 TensorBoard 和 Neptune 的文章中描述了最重要的变化。
如何通过 Neptune + TensorFlow / Keras 集成来跟踪您的 TensorFlow/Keras 模型训练。
为了将 Neptune 集成到项目中,我们需要在多大程度上改变项目的代码?如果我们删除所需的注册过程(花了我们大约 3 分钟)并省略安装部分(又花了我们 3 分钟),答案将是–**只添加了几行额外的代码来实现完整的集成。**为了实现集成,我们需要额外的代码:
import neptune
import neptune_tensorboard as neptune_tb
from neptunecontrib.monitoring.keras import NeptuneMonitor
token = *****
neptune.init(project_qualified_name='my_project',
api_token=token)
Neptune 文档很棒,所以你可以在里面找到你需要的任何东西。
让我回到整合上来。下一个变化是使用标准进行培训的模型发布。拟合方法。除了标准之外我们唯一要做的。fit 将传递一个新的回调函数(NeptuneMonitor())来完成所有的集成工作。以下是模型拟合的完整代码:
workers_num = 6
model.fit_generator(generator=train_data_gen,
steps_per_epoch=train_steps_per_epoch,
epochs=100,
validation_data=valid_data_gen,
validation_steps=valid_steps_per_epoch,
callbacks=[tbCallBack,
rLrCallBack,
mcCallBack_loss,
mcCallBack_acc,
esCallBack,
NeptuneMonitor()
],
use_multiprocessing=True,
workers=workers_num
)
NeptuneMonitor()将跟踪模型损失和我们定义的一组指标。它还将监控硬件利用率。
除此之外,我们还可以通过记录我们认为相关的额外工件来丰富每次发布。例如,我们可以将我们使用的一整套模型参数链接到一个实验。这是它在 Neptune UI 中的样子:
Model parameters stored for a particular model training run
除此之外,使用 Neptune,我们能够通过将用于训练和验证的数据集链接到特定的实验运行来实现数据版本控制。这是它在 Neptune UI 中的样子:
Datasets as HTMLs stored at Neptune. Data version control in action.
我们实际上做得更深入,充分利用了 Neptune 的协作选项。我们邀请我们的测试团队到 Neptune,并要求他们上传和附加他们用于模型评估的测试数据集。现在所有数据都存储在一个地方,超级方便。更酷的是,可以通过编程获取数据,并在需要时进行恢复。
我们还选择了一个月的时间作为我们在生产中重新评估模型的时间。这是我们推出生产模型监控的第一小步。
由于我们处理的数据的隐私特定原因,我们没有提出模型评估的自动化解决方案。考虑到数据的敏感性,我们仍然需要半手工的数据收集(半手工,因为我们仍然使用脚本来查询数据库,提取数据并在 Python 中处理它)和评估。我们提取并计划用于评估的新测试数据集以及评估结果现在也上传到 Neptune 并存储在那里。我们可以跟踪我们的模型是否会随着时间的推移而退化。每次评估后,我们都会上传并记录:
- 可以帮助我们直观理解模型性能的情节;
- 绩效指标的值。
Plots (roc-auc and confusion matrix) after evaluation are uploaded to Neptune.
Performance metrics are also displayed.
我之前提到过,在 MLOps 级,大部分工作都是脚本驱动的。我们的团队就是一个例子。但是现在,我们跟踪我们开发的脚本和 jupyter 笔记本。
例如,看看我们如何上传我们在特定模型运行中使用的数据扩充脚本,并将它们附加到 Neptune 中的相关实验:
Data augmentation scripts is attached to an experiment where it was used
为了消除由培训和生产之间的数据处理差异引起的培训服务偏差,我们还开始向 Neptune 上传完整的代码,该代码以推理模式启动模型,并对输入数据进行适当的预处理。由于所有这些代码脚本都在一个地方,这有助于我们的团队更快、更有效地协作。
我们邀请了后端团队的一些人到 Neptune,并解释了他们如何从那里获取模型属性和相关的代码脚本,这样就可以用它们来构建微服务。对了,最后的模型权重现在也上传存储在海王星了。它看起来是这样的:
Weights file for the best model is uploaded and stored at Neptune, so it can be fetched during the deployment phase
最后但同样重要的是,我们现在可以用更方便的方式试验新的模型和参数实现。我提到过,我们在开发过程中努力保持最新。
随着海王星的引入,这变得更好了。这是因为我们现在能够重现实验,并将它们与其他实验进行比较。
例如,最近推出了一种新的主干网,我们想尝试一下?没问题!看看能不能打败我们之前的配置。我们所需要的是获取我们之前用于训练、验证和测试先前模型的所有数据。
如果需要重用一些其他代码片段(比如我们之前讨论的用于增强的脚本),我们也可以直接从 Neptune 获得。尽管去取吧,都是附在上次运行中的。我们甚至可以在同一个笔记本或代码脚本中继续工作。代码中的新变化将被记录在新的检查点中,允许我们随时随地回滚。很漂亮,对吧?
Checkpoints made for a jupyter notebook I worked in through the entire project
同样值得一提的是,所有的实验运行都位于一个地方,一眼就可以轻松区分和比较——这要归功于 Neptune 允许我们放在实验旁边的 标签 和日志。
Experiments page within Neptune’s UI
当你已经做了很多实验,并且上面的实验页面被我们做的实验数量淹没时,这样一个特性变得特别有用。当您可以对实验应用过滤器时,导航会变得容易得多,或者只需查看实验旁边的独特值和描述。
结论
自从我们部署 Neptune 作为 MLOps 元数据存储工具以来,已经过去了大约 3 个月。对我们团队来说,积极的变化是显而易见的。我们离 MLOps 级还很远,但是第一步也是最难的一步已经迈出了。让我们回顾一下我们能够实现的目标:
- 生产模型现在处于我们的密切监视之下:每个月它们都在新获得的生产数据集上被重新评估。数据提取过程仍然是手动的,但是我们引入了这个想法,并将其集成到我们的管理设置中。我们的测试团队已经发展并改变了他们进行生产模型测试的方式。数据集和评估结果现在被上传到 Neptune,并与以前的评估进行比较,因此可以做出关于模型退化的决定。
- 我们的机器学习团队的开发速度明显加快。我们的内部测量显示提高了 2 倍,让我们有更多的时间来交付切实的成果。这是我们开展实验的方式改变的直接影响。现在,有一个简化导航的结构。所有相关的属性和检查点都被附加并存储在一个地方,从而提高了可重用性和可再现性。由于编写良好的文档和方便的集成方法,我们的 Neptune 集成引入的更改很容易被团队采用。
- 我们现在报告的生产、测试和开发阶段的培训服务偏差案例减少了 1/2,消除了不同管道中数据处理方式的差异。
不错吧?尤其是考虑到我们开始工作才 3 个月。我希望我们的经验是一个很好的例子,展示每个人如何开始致力于 ML 项目的 CI / CD 实现。有什么我们可以做得更好的吗?请在下面的评论区与我们分享你的想法和想法。
用于机器学习的持续集成和持续部署(CI/CD)工具
在现代软件开发团队中,持续集成(CI)和持续部署(CD)是标准实践。
CI 是关于项目应该如何在各种运行时自动地和连续地构建和测试。
CD 是必需的,这样通过自动化测试的每一个新代码都可以被发布到产品中,而不需要额外的努力。
在 ML 项目中采用 CI/CD 工具是非常有益的。这些工具可以帮助您快速找到代码中的错误和矛盾,从长远来看,可以降低停机时间的成本。
在现实世界的项目中,专家很难选择与企业采用的项目管理方案不冲突的高质量机器学习模型。这导致错过最后期限和超支。
为了保持预算和满足期限(特别是在早期阶段),ML 团队已经采用了来自传统软件开发的 CI/CD 等最佳实践。
手动做任何事情都很痛苦。您必须分配一台单独的服务器并保持其正常工作,确保必要软件系统的可用性,建立运行时环境,制作数据的备份副本,等等。
将这些职责委托给第三方服务很方便。有许多工具可以促进这种采用,其中许多是专门为机器学习工程师设计的。
在本帖中,我们将讨论机器学习项目中 CI/CD 的七个最佳工具。
机器学习的最佳 CI/CD 服务
机器学习工程师花费大量时间检查他们的模型是否有问题,并优化模型性能。CI/CD 工具消除了时间浪费,并尽可能自动化手动工作。
让我们仔细看看它们。
插件 | 证明文件 | 集气瓶架 | 主办;主持 | 操作系统 | 定价 | |
---|---|---|---|---|---|---|
CML | 2/5 | 合理 | 是 | 在内部/云上 | 任何 | 免费 |
GitHub 动作 | 3/5 | 穷 | 是 | 在内部/云上 | Linux,macOS,Windows | 免费 |
GitLab CI/CD | 2/5 | 好的 | 是 | 在内部/云上 | Linux,macOS,Windows | 免费/付费 |
詹金斯 | 5/5 | 伟大的 | 是 | 在内部/云上 | Windows、Linux、macOS 和其他类似 Unix 的操作系统 | 免费 |
TeamCity | 5/5 | 伟大的 | 是 | 在内部/云上 | Linux,macOS,Windows | $45-$1999 |
圈 CI | 4/5 | 合理 | 是 | 在内部/云上 | Ubuntu,macOS,Linux,Android 和 Windows | 某些配置免费/付费 |
特拉维斯 CI | 5/5 | 好的 | 是 | 在内部/云上 | Ubuntu,macOS | 开源免费/商业使用 69-479 美元 |
1.currentmodelogic 电流型逻辑的
CML,即持续机器学习,是一个开源工具,用于持续集成和部署机器学习项目。这是为数不多的专门为 MLOps 需求定制的项目之一,所以你可以轻松尝试一下。
这个工具是由制作 DVC 的同一个团队开发的,这是一个用于 ML 模型版本控制的开源库。CML 努力使 ML 模型的实现和部署变得容易,并以更少的错误更快地将它们带入交付阶段。
CML 旨在自动化 ML 工程师每天必须执行的一些日常任务,例如训练模型、评估它们的性能、创建和标记数据集等等。CML 具有广泛的特性:从制作和发送自动化报告,到发布数据,到为项目分配云资源。对于基础设施任务,您可以应用已经提到的 DVC 或者使用 Docker 来代替。
该工具支持用于数据科学项目的 GitFlow,允许自动生成报告,并使您不必更深入地研究使用外部服务的复杂细节。这些外部服务的例子是像 AWS、Azure 和 Google Cloud 这样的云平台。
优点:
- CML 将 GitFlow 用于数据科学。无论你习惯使用 GitLab 还是 GitHub,你都可以在你最熟悉的环境中管理 ML 实验。也可以使用 DVC 来代替 Git 回购。
- 它为 ML 项目提供了自动化报告。CML 自动监控不断变化的数据集,并跨项目历史比较 ML 实验,以在每个 Git 拉取请求中生成带有指标和图形的可视化报告。这样,您的工程团队就可以保持警惕,做出数据驱动的决策。
- CML 支持将模型工件从 GitHub 操作工作流发布到带有附加 GitHub 问题和 pull 请求的评论中。这弥补了拉式请求会计的不足,并提高了模型的准确性和有效性。
- 有了 CML,你就不必使用额外的服务。CML 使你能够在 GitLab、Bitbucket 或 GitHub 的帮助下构建自己的 ML 平台。如果您愿意,也可以使用云存储(但这是可选的)。
缺点:
- 这个项目很年轻。CML 的创造者声称有数百名活跃的贡献者,但现实是 CML 仍处于发展阶段。它可能包含错误和低质量的贡献,并且不能保证该项目在将来会得到支持。
概要:
- 操作系统:任何
- 容器支持:是
- 文档:好
- 定价:免费
2.GitHub 操作
GitHub Actions 是 GitHub 上最近推出的工作流自动化功能。GitHub 为 CI/CD 提供了一些功能,比如推送代码、创建发布或者管理问题。
登录 GitHub 后,您可以立即访问 GitHub 操作。它为 CI/CD 提供了巨大的可能性,包括自动化测试、构建容器、部署 web 服务,或者在您的开源项目中自动化新用户的加入。
GitHub 不仅仅是一个 MLOps 工具――用例更加通用。然而,由于许多公司在 GitHub 上为他们的 ML 项目编写和存储代码,对于一些团队来说,它可能比我们列表中的任何其他工具都更方便。一个不可否认的好处是世界上最活跃的社区之一,致力于改善和发展这个项目。
Github Actions 绝对值得一看。如果你不想在定制配置上浪费时间,Github 提供了一个图形界面,在这里你可以快速完成所有工作。
优点:
- 您可以通过开箱即用的身份验证直接访问 GitHub API。不需要复杂的设置。
- GitHub 动作只是连续的 docker 运行。这使得它们很容易推理和调试。
- 您可以隔离工作流中的操作,以便进行无缝测试。您可以在两种不同的计算环境中托管编译和测试。
缺点:
- 没有本机缓存。您可以获得图像和图层缓存,但除此之外别无其他。对于人工制品,你必须滚动自己的缓存,这可能是一个很大的工作量。
- 不支持来自分叉的拉请求。对于包含 fork 的工作流,这使得 GitHub 操作很大程度上不能作为 CI/CD 工具使用。
- 这份文件有许多需要改进的地方。希望将来会变得更好。
概要:
- 操作系统:Linux、macOS、Windows
- 容器支持:是
- 文档:差
- 定价:免费
3.CI/CD 的 GitLab
这是一个免费的开源产品,在 MIT 许可下发布,用 Go 和 Ruby 编写。基于此解决方案的独立服务器可以处理 25,000 多名用户。
GitLab CI/CD 使您能够使用存储库并进行代码审查。它还有一个误差控制系统。为了更好地保护用户隐私,您可以通过在本地安装该工具来将它链接到 Active Directory 和 LDAP 服务器。
一个庞大而复杂的社区使得使用该产品变得相当舒适。GitLab 不仅用于编写代码,还用于彻底审查代码。几乎所有的构建环境和版本控制系统都被支持。
优点:
- 详细的文档和简单的管理。平台和文档都有许多活跃的贡献者,这使得找到您需要的东西更加容易。
- 监控测试结果的便捷用户界面。大型和小型团队都可以使用这个 CI/CD 工具,因为您可以向个人和用户组授予读取和修改权限。
- 简单的资源管理。在 GitLab CI/CD 中,您可以轻松地将人员分配到项目检查点,并按任务分组。
- 方便的并行测试拉请求和分支。这使得它成为开源项目的一个好选择。
缺点:
- 需要为每个任务定义和加载工件。
- 不支持大型任务中的阶段。
概要:
- 操作系统:Linux、macOS、Windows
- 容器支持:是
- 文档:好
- 定价:免费,付费自托管
4.詹金斯
Jenkins 是一个流行的 CI/CDJava 应用程序,可以在 Windows、Mac OS X 和其他类似 Unix 的操作系统上运行,它在 MIT 许可下运行。它有一组丰富的特性来自动执行构建、测试、部署、集成和发布软件的任务。
除了通过传统的安装包安装之外,Jenkins 可以独立安装,也可以作为 Docker 安装在任何安装了 Java Runtime Environment (JRE)的机器上。Jenkins 团队还有一个名为 Jenkins X 的子项目,专门研究 Kubernetes 集群中的 CI/CD。
詹金斯团队已经发布了大约 1500 个插件,因此它可以与其他解决方案一起使用,例如与 Slack 或吉拉一起使用。集成也可用于一系列 DevOps 测试工具。REST API 支持对系统的远程访问。就像 GitLab 一样,该产品拥有一个庞大的充满激情的社区。
优点:
- 易于设置和更新。只需几个步骤,您就可以安装 Jenkins 并开始您的项目工作(然而,这里有一个我们稍后描述的转折)。也可以在 web 界面中进行设置和配置。
- 详细、易懂的文档。Jenkins 有一个专业团队,负责整理文档。
- 易于与其他工具集成。这个工具提供了数百个插件,所以它基本上可以与任何 CI/CD 工具集成。
- 分布式装配的多台机器。当您需要在几个不同的环境中测试产品时,这在任务中很有用。它还允许您在不同的条件下运行程序集。
缺点:
- 专用服务器。如果你想使用 Jenkins,你必须设置一个服务器,这需要服务器本身的额外费用。
- 对于更大的团队。Jenkins 是一个企业级工具。该解决方案对于小型项目来说并不太好,因为设置需要大量的工作。
概要:
- 操作系统:Windows、Linux、macOS
- 容器支持:是的。
- 文档:好
- 定价:免费
5.团队城市
TeamCity 是 JetBrains 团队打造的企业级持续集成服务器。它有强大的功能和一个非常健壮的免费版本,适用于小型项目(最多 100 个构建配置)。
TeamCity 提供了对许多开源插件的广泛支持,包括 JetBrains 的产品和第三方应用程序和工具。此外,团队城市提供了真棒。净支持。
由于所有这些,这个持续集成服务器是高度可靠的,并且独立于程序集的启动。TeamCity 集成了多个版本控制系统。
该软件提供了跟踪提交的能力,然后立即启动构建创建和单元测试。例如,如果提交后测试或编译失败,开发人员将会收到需要修改代码的通知。得益于便捷的网络界面,你可以实时看到发生了什么。
Java 代码由 IntelliJ IDEA inspections 进行分析。因此,负责代码质量的检查可以快速识别并警告程序员错误。它还可以发现当开发人员在同一个项目中重用其他人的代码时发生的重复。
在预测试模式下,您可以在提交之前将补丁上传到 CI 系统,系统本身会将它应用到项目代码和所有程序集,然后检查会自动开始。这个特性在开发人员很难开始自己测试的情况下特别有用,并且这个过程是在不同的操作系统版本的架构下执行的。
优点:
- 支持多平台和多版本控制系统。JetBrains 试图让他们的产品尽可能的精通,以便支持不同的编程语言(Ruby,Java,...。NET)、多版本控制系统(如 Git、SVN、吉拉)和构建运行器(Rake、MSBuild、Nant、ant)
- 出色的报告选项。TeamCity 自动检查正在运行的代码,甚至在构建完成之前就提供关于错误的报告。这样,您可以在更短的时间内发现并修复错误。
- 几个协作选项。TeamCity 对于个人和企业来说都是灵活高效的。该平台根据您需要的功能提供订阅包。
缺点:
- 只能有一个生成配置。
- 当被触发时,构建选项不能被更改。
- 运行 Bash 脚本时,只检查最后一个命令的结果。
- 由于主要的配置工作是在接口中进行的,所以性能与这个接口的速度成正比,相当慢。
概要:
- 操作系统:Linux、macOS、Windows
- 容器支持:是
- 文档:非常好
- 定价:从 45 美元到 1999 美元或更高(针对企业)
6.圆形 CI
CircleCI 是一个基于云的系统,不需要你设置单独的服务器,也不需要管理。CircleCI 是配置最少的交钥匙解决方案。但是,还有一个内部版本,您可以部署在私有云上。即使是商业用途,也有可能免费使用 CircleCI。
使用 REST API,您可以访问项目、程序集和工件。装配结果是一个工件或一组工件。一个工件可以是一个已编译的应用程序或者可执行文件(例如,一个 Android 的 APK)或者元数据(例如,关于一个成功测试的信息)。
CircleCI 缓存第三方依赖项,避免不断安装所需的环境。
CircleCI 可以通过复杂的缓存、dock 级缓存、用于在更快的机器上运行的资源类以及性能评估来高效地运行非常复杂的管道。作为开发人员,您可以使用 SSH 来执行任何调试任务,或者在。circleci/config.yml 文件来加速作业。
作为安装在服务器上的 CircleCI 的操作员或管理员,您会喜欢 CircleCI 监视和分析您的构建,并使用 Nomad 集群进行调度。
优点:
- 自定义构建环境和语言支持。通过使用 Docker 映像或 LINUX / Windows / macOS 虚拟机(VM)设置管道运行时,可以将 CircleCI 配置为模拟目标部署环境。您可以使用 CircleCI 提供的预建 Docker 映像,或者选择自己的 Docker Hub 映像作为运行时。
- CircleCI 预装了 Android SDK、NDK 和其他依赖项,并允许您在 Linux 虚拟机上构建和测试 Android 应用程序。
- 它支持多种语言,包括 PHP、Python、Java、Javascript、ReactNative、RoR、Elixir、Scala 等。
- CircleCI 提供应用级安全性和沙盒运行时安全性。CircleCI 通过 SOC 2 和 FedRAMP 认证。
- 商业使用的免费版本。即使是小团队也能从 CircleCI 的广泛功能中受益。你甚至不需要设置一个专用的 CircleCI 服务器。
- 灵活的配置。CircleCI 可以配置为将代码部署到各种环境,包括 AWS CodeDeploy、AWS EC2 Container Service (ECS)、AWS S3、Google Kubernetes Engine (GKE)、Microsoft Azure 和 Heroku。其他的云服务部署很容易使用 SSH 或者通过在您的工作配置中安装一个服务 API 客户端来编写。
缺点:
- 免费版的 CircleCI 只支持 Ubuntu 12.04 和 14.04。使用 macOS 需要付费。
- 尽管 CircleCI 可以与任何编程语言一起工作,但它只支持 Go (Golang)、Haskell、Java、PHP、Python、Ruby/Rails 和 Scala。
概要:
- 操作系统:Ubuntu、macOS、Linux、Android 和 Windows
- 容器支持:是
- 文件:合理
- 定价:免费/付费选项高达 3150 美元及以上
7.特拉维斯·CI
Travis CI 是一个持续集成平台,对 GitHub 上的所有开源项目都是免费的。只要有一个名为. travis.yml 的文件,其中包含有关项目的一些信息,您就可以在主分支、其他分支甚至是 pull 请求中的代码库发生变化时触发自动构建。不要混淆 travis-ci.org 和 travis-ci.com。第一个是开源项目的免费服务,第二个是付费的 CI 系统。Travis CI 和 CircleCI 很像。
两个系统:
- 使用 YAML 格式的配置文件;
- 部署在云中;
- 支持 Docker 进行测试。
然而,TravisCI 有一些 CircleCI 没有的额外东西:
- 在 Linux 和 Mac OS X 下同时运行测试。
- 支持更多现成的语言:
- Android、C、C #、C ++、Clojure、Crystal、D、Dart、Erlang、Elixir、F #、Go、Groovy、Haskell、Haxe、Java、JavaScript(带 Node.js)、Julia、Objective-C、Perl、Perl6、PHP、Python、R、Ruby、Rust、Scala、Smalltalk、Visual Basic。
- 构建矩阵支持。
优点:
- 轻松快速地开始工作。CircleCI 拥有无缝的 onboarding,可以在内部和云中运行。
- CircleCI 可以用于在 CircleCI 云计算中组织 CI/CD 管道,或者您也可以通过在您的基础设施上运行 CircleCI 来实现 CI/CD。这将使您完全控制功能和维护工作。
- 您可以将 CircleCI 与云生态系统 AWS、Azure、DeployHub、Cloud Foundry、Google Cloud、OpenShift、Serverless 和一系列其他环境/平台集成,以部署您的应用程序。
缺点:
- 价格比 CircleCI 高,没有商业使用的免费版本;
- 它的定制选项有限(有些东西可能需要第三方软件)。
概要:
- 操作系统:Ubuntu,macOS
- 容器支持:是
- 文档:好
- 定价:开源免费/商业使用 69-479 美元
奖金:坞站/坞站集线器
我们在本文中多次提到 Docker,这是有原因的。得益于容器化技术,Docker 是一种工具,即使 Docker 平台本身运行在不同的环境中,也可以轻松地在相同的环境中分发、部署和运行应用程序。
许多开发人员认为 Docker 是最有效的容器技术。弄清楚 Docker 的安装说明可能很棘手,但是一旦你安装了它,你就不会后悔。
Docker Hub 与 Git 资源库的 GitHub 或 JavaScript 包的 NPM 注册表大致相同。它有以下好处:
- 持续开发和零停机部署。假设你写了一个脚本,需要某个版本的库,以及一些预装的软件才能运行,你想和同事分享你的工作成果。您的同事需要为自己重新安装所有必要的库,或者每个人都应该自己配置 Virtualenv。通过将您的脚本作为容器来提供,可以简化整个沉闷的过程。应用程序将提供启动所需的所有环境,同事们只需执行一个简单的命令即可启动。
- 易于迁移。您有一个 web 应用程序,其中部署了 web 服务器和服务器应用程序。在迁移过程中,您可以重新注册权限、配置和设置环境,但是在新实例上启动准备好的容器比重新配置更容易。
- 运行不安全的代码。Docker 允许你运行任何软件,包括图形软件,通过安全地将它隔离在一个容器中。因此,它非常适合运行各种不可信或不安全的代码。
结论
在 ML 项目的任何阶段,开箱即用的 CI/CD 工具对于监控代码报告的变更和生成单元&集成测试是必要的。由于数据是一种重要的业务资源,就像开发人员的时间一样,自动化和优化工具应该成为您最好的朋友。
机器学习模型每天都要经历很多次转换。数据的频繁变化,它们从一种状态到另一种状态的转换——所有这些都迫使经理们尝试 CI/CD 这样的软件管理方法,这种方法让你可以使用复杂的机器学习模型,而不会损失数据管理的质量。
英伟达支持的对话式人工智能架构:工具指南
原文:https://web.archive.org/web/https://neptune.ai/blog/conversational-ai-nvidia-tools-guide
随着自然语音合成和语音识别等深度学习领域的最新进展,AI 和深度学习模型越来越多地进入我们的日常生活。事实上,许多无害的应用程序,与我们的日常生活无缝集成,正慢慢变得不可或缺。
大型数据驱动的服务公司严重依赖复杂的网络架构,其管道使用对话式深度学习模型,并遵守各种各样的语音任务,以尽可能最好的方式为客户服务。
更广泛地说,“对话式人工智能”一词意味着所有能够自然模仿人类声音、理解对话、开发个人口语意图识别配置文件(如 Alexa 或谷歌助手)的智能系统。简而言之,对话式 AI 是为了类似人类的对话。
深度学习在改进现有的语音合成方法方面发挥了巨大的作用,它用纯数据训练的神经网络取代了整个管道过程。根据这个观点,我想探索两个在他们的领域中非常有名的新模型:
- 用于文本到语音转换的 Tacotron 2,
- 用于自动语音识别的 Quartznet。
我们将讨论的模型版本基于 Nvidia 最近推出的神经模块 NeMo 技术。
我们将探索它们的架构,并深入研究 Github 上的 Pytorch。此外,我们将实现一个 Django REST API,通过公共端点为模型提供服务,最后,我们将创建一个小型 IOS 应用程序,通过客户端的 HTTP 请求来使用后端。
深入研究 ASR 和 TTS 架构
石英网
正如他们的论文所述,Jasper 是一个用于自动语音识别的端到端神经声学模型。所有 Nvidia 的语音识别模型,像石英网,都来自 Jasper。
由于它是端到端的,所以整体架构支持从输入音频处理到文本转录的所有必要阶段。基础设施背后的管道涉及三个主要部分:
- 编码器和解码器,用于将音频输入转换为 Mel 频谱图;
- 统计语言模型,即强化的 n-gram 语言模型 ,从声学输入中寻找最可能产生的词序列,并生成与声谱图采样率紧密匹配的特定嵌入;
- 产生对应于音频输入的文本输出。
符合 Jasper 架构的主要层是卷积神经网络。它们旨在通过允许整个子块融合到单个 GPU 内核中来促进快速 GPU 推理。这对于部署阶段的严格实时场景极其重要。
使用密集残差连接,每个块输入都与所有后续块的最后一个子块紧密连接(要了解更多关于残差网络的信息,请查看本文)。每个块的内核大小和过滤器数量都不相同,越深的层其大小越大。
塔克特龙二号
就编码器-解码器管道而言,Tacotron 的整体架构遵循与 Quartznet 相似的模式。Tacotron 也可以被视为一个序列到序列模型,它将字符嵌入映射到可扩展的 Mel 频谱图,然后是一个修改的声码器(WaveNet),以帮助合成时域波形并生成人类听觉输出。
注 : 梅尔频谱图 是基于梅尔曲线的时频分布图,反映了人耳蜗的特征。
该体系结构的关键阶段是:
- 处理字符嵌入的第一递归的基于序列间注意力的特征提取器。它产生 Mel 谱图帧作为第二级的前向输入;
- 一个改进的 WaveNet 声码器,它产生先前根据 Mel 频谱图调节的时域波形样本。
解码器基于自回归递归神经网络。它试图从编码的输入序列中一次一帧地预测 Mel 光谱图。来自前面步骤的预测通过一个小的预网络,具有 256 个隐藏 ReLU 单元的 2 个完全连接的层。主要思想是使用完全连接的层作为信息瓶颈,因此它可以有效地学习注意力。关于注意力机制的更多见解,你可以查看以下文章:
注:这两个模型在流行的 Librispeech 和 WSJ 数据集上都取得了平均意见得分4.53的 MOS,几乎可以与专业录制的演讲相媲美。
神经模块工具包, NeMo
NeMo 是一个编程库,它利用可重用神经组件的能力来帮助您轻松安全地构建复杂的架构。神经模块是为速度而设计的,可以在并行 GPU 节点上横向扩展训练。
通过神经模块,他们想要创建通用 Pytorch 类,每个模型架构都是从这些类中派生出来的。该库非常强大,并提供了对话式人工智能所需的不同深度学习模型的整体旅行。语音识别、语音合成、文本到语音到自然语言处理,等等。
通常,神经模块是对应于神经网络的概念部分的软件抽象,例如编码器、解码器、专用损耗、语言和声学模型、或者音频和频谱图数据处理器。
该库构建在 CUDA 和 cuDNN 低级软件之上,利用 Nvidia GPUs 进行并行训练和速度推理。
看看他们的 Github repo ,很有见地。
通过 Pytorch 处理程序服务模型
为了构建和公开访问模型推理的 API 端点,我们需要创建一个管理中间所需步骤的类;从预处理原始输入数据,用配置和检查点文件初始化模型实例,到运行推理并产生合适的结果——这需要很好地管理。
此外,如果我们想要组合多个模型来构建一个更复杂的管道,组织我们的工作是分离每个部分的关注点的关键,并使我们的代码易于维护。
例如,ASR 输出通常不会被打断。如果我们在一个敏感的场景中使用模型,我们必须用标点符号将 ASR 模型的文本原始输出链接起来,以帮助澄清上下文并增强可读性。
在这方面,以下代码说明了不同的模型处理程序:
Tacotron 处理器
class TacotronHandler(nn.Module):
def __init__(self):
super().__init__()
self.tacotron_model = None
self.waveglow = None
self.device = None
self.initialized = None
def _load_tacotron2(self, checkpoint_file, hparams_config: Hparams):
tacotron2_checkpoint = torch.load(os.path.join(_WORK_DIR, _MODEL_DIR, checkpoint_file))
self.tacotron_model = Tacotron2(hparams= hparams_config)
self.tacotron_model.load_state_dict(tacotron2_checkpoint['state_dict'])
self.tacotron_model.to(self.device)
self.tacotron_model.eval()
def _load_waveglow(self, checkpoint_file, is_fp16: bool):
waveglow_checkpoint = torch.load(os.path.join(_WORK_DIR, _MODEL_DIR, checkpoint_file))
waveglow_model = WaveGlow(
n_mel_channels=waveglow_params.n_mel_channels,
n_flows=waveglow_params.n_flows,
n_group=waveglow_params.n_group,
n_early_every=waveglow_params.n_early_every,
n_early_size=waveglow_params.n_early_size,
WN_config=WN_config
)
self.waveglow = waveglow_model
self.waveglow.load_state_dict(waveglow_checkpoint)
self.waveglow = waveglow_model.remove_weightnorm(waveglow_model)
self.waveglow.to(self.device)
self.waveglow.eval()
if is_fp16:
from apex import amp
self.waveglow, _ = amp.initialize(waveglow_model, [], opt_level="3")
def initialize(self):
if not torch.cuda.is_available():
raise RuntimeError("This model is not supported on CPU machines.")
self.device = torch.device('cuda')
self._load_tacotron2(
checkpoint_file='tacotron2.pt',
hparams_config=tacotron_hparams)
self._load_waveglow(
is_fp16=False,
checkpoint_file='waveglow_weights.pt')
self.initialized = True
logger.debug('Tacotron and Waveglow models successfully loaded!')
def preprocess(self, text_seq):
text = text_seq
if text_seq[-1].isalpha() or text_seq[-1].isspace():
text = text_seq + '.'
sequence = np.array(text_to_sequence(text, ['english_cleaners']))[None, :]
sequence = torch.from_numpy(sequence).to(device=self.device, dtype=torch.int64)
return sequence
def inference(self, data):
start_inference_time = time.time()
_, mel_output_postnet, _, _ = self.tacotron_model.inference(data)
with torch.no_grad():
audio = self.waveglow.infer(mel_output_postnet, sigma=0.666)
return audio, time.time() - start_inference_time
def postprocess(self, inference_output):
audio_numpy = inference_output[0].data.cpu().numpy()
output_name = 'tts_output_{}.wav'.format(uuid.uuid1())
path = os.path.join(_AUDIO_DIR, output_name)
print(path)
write(path, tacotron_hparams.sampling_rate, audio_numpy)
return 'API/audio/'+ output_name
initialize():用各自的检查点加载 Tacontron 和 Wave Glow 。
预处理(text_seq):将原始文本转换成适合模型的输入。转换它
一组特定的字符序列。
推断(数据):对之前处理的输入进行推断,并返回与输入文本匹配的相应合成音频。
postprocess(inference_output):将 wav 音频文件保存到容器文件系统下的一个目录中。
石英网装载机
class Quartznet_loader():
def __init__(self, torch_device=None):
if torch_device is None:
if torch.cuda.is_available():
torch_device = torch.device('cuda')
else:
torch_device = torch.device('cpu')
self.file_config = path.join(WORK_DIR, _MODEL_CONFIG)
self.file_checkpoints = path.join(WORK_DIR, _MODEL_WEIGHTS)
model_config = OmegaConf.load(self.file_config)
OmegaConf.set_struct(model_config, True)
if isinstance(model_config, DictConfig):
self.config = OmegaConf.to_container(model_config, resolve=True)
self.config = OmegaConf.create(self.config)
OmegaConf.set_struct(self.config, True)
instance = EncDecCTCModel(cfg=self.config)
self.model_instance = instance
self.model_instance.to(torch_device)
self.model_instance.load_state_dict(torch.load(self.file_checkpoints, torch_device), False)
def covert_to_text(self, audio_files):
return self.model_instance.transcribe(paths2audio_files=audio_files)
def create_output_manifest(self, file_path):
manifest = dict()
manifest['audio_filepath'] = file_path
manifest['duration'] = 18000
manifest['text'] = 'todo'
with open(file_path + ".json", 'w') as fout:
fout.write(json.dumps(manifest))
return file_path + ".json"
- init(torch_device):初始化将要运行模型检查点的硬件设备,无论它是在 CPU 上还是在支持 Cuda 的 GPU 上。
- model _ config = omegaconf . load(self . file _ config):用编码器、解码器、优化器、预处理器和声谱图增强器的相应结构加载模型的配置文件。
- instance = EncDecCTCModel(CFG = self . config):调用神经模块 EncDecCTCModel 从各自的 Quartz-Net 配置文件中实例化。该模块将创建一个特定的 NeMo 实例,通过它可以访问一些非常方便的驱动模型行为的函数。convert_to_text(audio_files):调用 EncDecCTCModel.instance 将音频 wav 格式文件转录为文本输出。
- create _ output _ manifest(file _ path):将最终结果保存到一个 json 文件中,文件中包含输入音频文件路径、音频时长、音频采样率以及相应的转录文本。
Bert Loader
class Bert_loader():
def __init__(self, torch_device=None):
if torch_device is None:
if torch.cuda.is_available():
torch_device = torch.device('cuda')
else:
torch_device = torch.device('cpu')
self.file_config = path.join(WORK_DIR, _MODEL_CONFIG)
self.file_checkpoints = path.join(WORK_DIR, _MODEL_WEIGHTS)
model_config = OmegaConf.load(self.file_config)
OmegaConf.set_struct(model_config, True)
if isinstance(model_config, DictConfig):
self.config = OmegaConf.to_container(model_config, resolve=True)
self.config = OmegaConf.create(self.config)
OmegaConf.set_struct(self.config, True)
instance = PunctuationCapitalizationModel(cfg=self.config)
self.model_instance = instance
self.model_instance.to(torch_device)
self.model_instance.load_state_dict(torch.load(self.file_checkpoints, torch_device), False)
def punctuate(self, query):
return self.model_instance.add_punctuation_capitalization(query)[0]
- init(torch_device):在 CPU 或支持 Cuda 的 GPU 上初始化将运行模型检查点的硬件设备。
- model _ config = omegaconf . load(self . file _ config):用编码器、解码器、优化器、预处理器和声谱图增强器的相应结构加载模型的配置文件。
- instance = PunctuationCapitalizationModel(CFG = self . config):调用神经模块,该模块实现了轻量级 Bert 语言模型行为的内部代码。实际的实例将能够标点出原始输入文本。
- 标点(查询):以查询的形式获取原始输入文本,并输出一个整洁的文本版本,该文本带有完整的标点符号,可读性很好。
注:关于代码的更多细节,请参考我的 github repo,我在那里获得了整个项目的资源——对话式 API
构建 Django API
我们将使用 Django REST 框架构建一个简单的 API 来服务我们的模型。我们的想法是配置所有需要的文件,包括模型、路由管道和视图,这样我们就可以通过 forward POST 和 GET 请求轻松地测试推理。
如果你需要做一个 Django Rest 项目的完整旅程,可以看看我以前关于这个主题的文章:使用 Django API 进行语义分割
对于项目需求,我们将依靠第三方服务来通过我们的端点存储和检索语音生成的数据。所以,Django ORM 助手和序列化器将会派上用场。正如他们的文档所述,Django ORM 是“一种创建 SQL 来查询和操作数据库并以 Pythonic 方式获得结果的 Pythonic 方式”
现在:
- 为 TTS、ASR 输出创建 ORM 模型;
- 创建相应的序列化程序;
- 构建您的视图(发布、删除)和路由。
class ASRText(models.Model):
uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=255,null=True, blank=True)
Output = models.TextField(null=True, blank=True)
inference_time = models.CharField(max_length=255,null=True, blank=True)
audio_join_Transformed = models.FileField(upload_to=get_asr_media, null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name = "ASRText"
verbose_name_plural = "ASRTexts"
def __str__(self):
return "%s" % self.name
class TTSSound(models.Model):
uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=255,null=True, blank=True)
text_content = models.TextField(null=True, blank=True)
audio_join = models.FileField(upload_to=get_tts_media, null=True, blank=True)
inference_time = models.CharField(max_length=255,null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
连续地创建你的视图。出于示例的目的,我将展示两个简单的 POST 请求,它们在 ASR 和 TTS 这两种场景中都完成了工作:
- ASR 文本实例的 ASRText
- TTS 音频实例的 TTSound
但是在实际实现 API 视图之前,我们需要在项目的全局范围内实例化模型处理程序,以便可以将繁重的配置文件和检查点加载到内存中并准备使用。
bert_punctuator = Bert_loader()
quartznet_asr =Quartznet_loader()
tacotron2_tts = TTS_loader()
ASR_SAMPLING_RATE = 22050
ASR 发布请求
@api_view(['POST'])
def asr_conversion(request):
data = request.FILES['audio']
audio = ASRInputSound.objects.create(audio_file=data)
file = [audio.audio_file.path]
start_time = time.time()
transcription = quartznet_asr.covert_to_text(file)
well_formatted = bert_punctuator.punctuate(transcription)
text = ASRText.objects.create(
name='ASR_Text_%02d' % uuid.uuid1(),
Output=well_formatted,
inference_time=str((time.time() - start_time)),
audio_join_Transformed=audio.audio_file.path
)
serializer = ASROutputSeralizer(text)
return Response(serializer.data, status=status.HTTP_200_OK)
- 它获取从 POST api 调用 file = [audio.audio_file.path]发送的音频文件的存储路径。在获得文件后,quartznet 实例立即对后者进行推理,提取一个原始转录,调用 bert _ punctuator.punctuate(转录)对其进行标点。
- 接下来,调用 ASRText 序列化程序将实例对象保存到数据库中,如果运行顺利,它会输出一个 HTTP 成功状态 200,并带有包含实际转录输出的格式化 JSON 响应。
TTS 发布请求
@api_view(['POST'])
def tts_transcription(request):
text = request.data.get('text')
tts_id = uuid.uuid1()
path = "Audio/tts_output_%02d.wav" % tts_id
start_time = time.time()
output_audio = tacotron2_tts.tts_inference(text)
write(path, int(ASR_SAMPLING_RATE), output_audio)
audio = TTSSound.objects.create(
audio_join=path,
name='Sound_%02d' % tts_id,
text_content=text,
inference_time=str((time.time() - start_time))
)
audio.save()
serializer = TTSOutputSerializer(audio)
return Response(serializer.data, status=status.HTTP_200_OK)
tts_transcription post 方法也是如此,我们对输入文本进行推理,生成采样率为 22050 的输出音频文件,并使用 write(path)方法将其保存在文件系统的本地。
类似地,如果请求成功,带有包含音频路径的格式化 JSON 响应,我们返回 HTTP 200 状态。
创建 iOS 应用程序来使用服务
在本节中,我们将创建一个简单的 IOS 应用程序,它带有两个 ViewControllers,以一种有趣的方式使用 API。
我们将以编程方式构建应用程序,不使用故事板,这意味着没有要切换的框或按钮——只有纯代码。
要从项目设置中完全删除故事板,您需要遵循以下步骤:
- 删除项目结构中的 main.storyboard 文件。
- 对于 Xcode 11 或更高版本,转到 i nfo.plist 文件,删除故事板名称属性。
- 如下修改 SceneDelegate.swift 文件中的代码,使 AudioViewController 成为主 UINavigationController
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScence = (scene as? UIWindowScene) else { return }
window = UIWindow(frame: windowScence.coordinateSpace.bounds)
window?.windowScene = windowScence
let recordingController = AudioRecordingViewController() as AudioRecordingViewController
let navigationController = UINavigationController(rootViewController: recordingController)
navigationController.navigationBar.isTranslucent = false
window?.rootViewController = navigationController
window?.makeKeyAndVisible()
}
现在,您已经准备好开始编写主视图控制器了。
对于这个简单的应用程序,我们将呈现两个屏幕,每个屏幕关注一个特定的部分:
- AudioViewController 将负责录制您的语音,并使用录音按钮设置通用 UI。
- ASRViewController 将发送一个包含您录制的音频文件的 HTTP Post 请求,并接收转录的文本。将解析 JSON 响应,并显示文本内容。
为您的 AudioViewContoller 构造布局和 UI 配置
AudioViewController 有两个按钮:一个用于录音,一个用于停止录音。在录音按钮下面有一个最后的标签,显示一条消息通知用户他的声音正在被录音。
要构建没有 AutoLayout 的视图,我们需要在每个 UI 元素上设置自定义约束。
下面的代码可以做到这一点:
func constrainstInit(){
NSLayoutConstraint.activate([
// Constraints for the Recording Button:
recordingButton.widthAnchor.constraint(equalToConstant: view.frame.width - 60),
recordingButton.heightAnchor.constraint(equalToConstant: 60),
recordingButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
recordingButton.topAnchor.constraint(equalTo: logo.bottomAnchor, constant: view.frame.height/6),
// Constraints for the Label:
recordingLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor),
recordingLabel.topAnchor.constraint(equalTo: recordingButton.bottomAnchor, constant: 10),
// Constraints for the Stop Recording Button:
stopRecordingButton.widthAnchor.constraint(equalToConstant: view.frame.width - 60),
stopRecordingButton.heightAnchor.constraint(equalToConstant: 60),
stopRecordingButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
stopRecordingButton.topAnchor.constraint(equalTo: recordingButton.bottomAnchor, constant: 40)
])
}
将布局添加到主视图:
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
view.addSubview(recordingButton)
view.addSubview(recordingLabel)
view.addSubview(stopRecordingButton)
view.addSubview(logo)
constrainstInit()
}
音频记录逻辑
对于记录部分,我们将使用来自 UIKit 的广为人知的 AVFoundation 库,它完全符合我们的目的。
三个主要功能将实现核心逻辑:
1.录音音频()
使用 AVAudioRecorder 共享实例处理与语音录制相关的所有逻辑,并设置内部目录路径以保存生成的音频文件。
@objc
func recordAudio(){
recordingButton.isEnabled = false
recordingLabel.isHidden = false
stopRecordingButton.isEnabled = true
// Code for audio record:
let dirPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
let recordedFileName = "recording.wav"
let pathArray = [dirPath, recordedFileName]
let filePath = URL(string: pathArray.joined(separator: "/"))
let recordingSession = AVAudioSession.sharedInstance()
try! recordingSession.setCategory(AVAudioSession.Category.playAndRecord, options: .defaultToSpeaker)
try! audioRecorder = AVAudioRecorder(url: filePath!, settings: [:])
audioRecorder.delegate = self
audioRecorder.isMeteringEnabled = true
audioRecorder.prepareToRecord()
audioRecorder.record()
}
2.停止录制()
完成录音会话并使默认 iphone 扬声器静音,以避免原始录音上出现任何不必要的噪音。
@objc
func stopRecording() {
stopRecordingButton.isEnabled = false
recordingButton.isEnabled = true
// Stop the recording and AVAudioRecord session previously active:
audioRecorder.stop()
let audioSession = AVAudioSession.sharedInstance()
try! audioSession.setActive(false)
}
3.audioRecorderDidFinishRecording()委托
当 AVAudioRecorder 会话成功结束且未引发任何硬件相关错误时触发。它将记录器文件的路径发送给 ASRViewController。
func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) {
if flag {
asrController.recorderAudioURL = audioRecorder.url
self.navigationController?.pushViewController(asrController, animated: true)
}
else {
print("Your audio was not saved")
}
}
ASRViewController,处理 API 回调
API 期望一个[String:String]类型的字典——键是“audio”,值是音频文件路径,实际上是一个字符串。
我们将使用 Alamofire ,这是一个广泛使用的 Swift 软件包,用于处理与 Swift 的优雅的 HTTP 联网。用你喜欢的方法安装软件包,我用的是 CocoaPod。
创建将用于发送要编码到 URLRequest 中的 POST 请求值的参数;
使用 Alamofire 请求方法执行请求。传递 API 入口点、方法类型(在我们的例子中是 POST)和参数;
处理 API 响应结果。如果成功,我们将把 API 响应解析为 JSON 对象,并提取输出文本来显示它。
func transcribeAudio() {
let audioFilePath = audioRecorder.url! as String
AF.request(URL.init(string: self.apiEntryPoint)!, method: .post, parameters: parameters, encoding: JSONEncoding.default, headers: .none).responseJSON { (response) in
switch response.result {
case .success(let value):
if let JSON = value as? [String: Any] {
let trasncribedText = JSON["Output"] as! String
}
break
case .failure(let error):
print(error)
break
}
}
}
结果
对于下面的音频文件: Sample ASR ,我们从 API 调用:
获得结果 JSON 响应
结论
好的,这是整个项目的概述。从构建后端 API 来服务于我们的深度学习模型,到以有趣而简单的方式消费服务的小应用程序。我强烈建议您查看 Github repos 以获得更深入的见解:
正如你所看到的,语音合成和语音识别是非常有前途的,它们将不断改进,直到我们达到令人惊叹的结果。
对话式人工智能越来越接近无缝地讨论智能系统,甚至没有注意到与人类语音的任何实质性差异。
如果您想深入了解,我将为您提供更多资源:
感谢阅读!
使用 Swift、Core ML 和 TuriCreate 创建一个人脸识别应用程序
原文:https://web.archive.org/web/https://neptune.ai/blog/create-a-face-recognition-application
面部识别技术已经出现了一段时间,涉及到越来越多的应用,肯定会彻底改变我们的生活。依赖这些技术的应用程序向最终客户保证了数据隐私和安全性的高度可靠性。尽管最近的一些伦理争议,如 Clearview AI 在很大程度上呼应了公共面部识别的可能威胁,但人们一直渴望学习和理解这项技术的工作原理。
如今,谷歌、脸书或苹果等领先的科技行业提供第三方软件来帮助开发者快速构建和迭代使用这些技术扰乱市场并帮助塑造未来时代的产品。后者的一个明显例子是苹果。最近几个月发布了其视觉 API 的主要更新,这是他们所有与计算机视觉相关的事情的主要框架。
Vision API 包括以下功能:
- 本地人脸检测 API
- 使用 ARkit 进行人脸跟踪
- 文本和条形码识别
- 光栅重合
- Vision 允许为各种图像任务使用定制的核心 ML 模型
在本文中,我们将通过查看以下内容,尝试对这些技术有更多的了解:
注 :您可以在我的 Github repo 中找到整个项目的代码
苹果核心 ML 框架之旅
Core ML 是苹果的机器学习框架,通过充分利用所有模型的统一表示,开发人员可以在设备上部署强大的 ML 模型。
更具体地说, Core ML 旨在为设备体验提供优化的性能,允许开发人员从各种 ML 模型中进行选择,他们可以在已经配备了专用神经引擎和 ML 加速器的 Apple 硬件上部署这些模型。
如何在设备上进行 ML 部署
在展示 Core ML 3.0 中的新功能之前,我想解释一下将一个训练好的模型从 Pytorch 或 Tensorflow 导出到 Core ML 并最终部署到 IOS 应用程序中的不同步骤。
核心 ML 文档推荐使用一个 python 包来简化从第三方培训库(如 TensorFlow 和 PyTorch )到核心 ML 格式的迁移。
使用 coremltools 软件包,您可以:
- 轻松转换来自第三方库的训练模型的权重和结构
- 优化和超调核心 ML 模型
- 利用 Catalyst 和核心 ML 验证 macOS 转换
很明显,并不是所有的模型都被支持,但是在每一次更新中,他们试图增加对更多神经结构、线性模型、集成算法等的支持。你可以在他们的官方文档网站找到当前支持的库和框架如下:
模型类别
支持的软件包
Supported packages:
Tensorflow 1
Tensorflow 2
Pytorch (1.4.0+)
Keras (2.0.4+)
ONNX (1.6.0)
Caffe
Supported packages:
XGBoost
Sci-kit 学习
广义线性模型
Supported packages:
Sci-kit 学习
Supported packages:
LIBSVM
数据管道(后处理和预处理)
Supported packages:
Sci-kit 学习
使用 Pytorch 的转换示例
为了说明如何轻松利用 coremltools 并将一个经过训练的 Pytorch 模型转换为 Core ML 格式,我将给出一个简单的实际操作示例,说明如何使用 TorchScript 和 torch 转换来自 torchvision 库的 MobileNetV2 模型。 jit.trace 对模型权重进行量化和压缩。
注意 :这个例子的代码可以在 coremltools 官方文档 页面中找到
模型转换的步骤:
加载 MobileNetV2 的预训练版本,并将其设置为评估模式
- 使用 torch.jit.trace 模块生成 Torchscript 对象
- 使用 coremltools 将 TorchScript 对象转换为 Core ML
- 首先,您需要安装 coremltools python 包:
按照官方文档的建议使用 Anaconda
创建 conda 虚拟环境:
- 激活您的康达虚拟环境:
conda create --name coreml-env python=3.6
- 安装 conda-forge 的 coremltools
conda activate coreml-env
- 或者使用 pip 和 virtualenv 软件包:
conda install -c conda-forge coremltools
安装 virtualenv 软件包:
- sudo pip 安装虚拟
激活虚拟环境并安装 coremltools:
virtualenv coreml-env
- 加载预训练版本的 MobileNetV2
source coreml-env/bin/activate
pip install -u coremltools
使用 torchvision 库导入在 ImageNet 上训练的 MobileNetV2 版本。
将模型设置为评估模式:
import torch
Import torchvision
mobile_net = torchvision.models.mobilenet_v2(pretrained=True)
使用 torch.jit.trace 生成 Torchscript 对象
mobile_net.eval()
Torch jit 跟踪模块采用与模型通常采用的输入张量维数完全相同的输入示例。跟踪只正确记录那些不依赖于数据的函数和模块(例如,张量中的数据没有条件),并且没有未跟踪的外部依赖项(例如,执行 I/O 或访问全局变量)。
给出随机数据的轨迹:
从单独的文件下载分类标签:
import torch
input = torch.randn(1, 3, 224, 224)
mobile_net_traced = torch.jit.trace(mobile_net, input)
使用 coremltools 将 TorchScript 对象转换为 Core ML 格式
import urllib
label_url = 'https://storage.googleapis.com/download.tensorflow.org/data/ImageNetLabels.txt'
class_labels = urllib.request.urlopen(label_url).read().decode("utf-8").splitlines()
class_labels = class_labels[1:]
assert len(class_labels) == 1000
多亏了统一转换 API ,转换成核心 ML 格式才成为可能。
MLModel 扩展封装了核心 ML 模型的预测方法、配置和模型描述。正如您所看到的,coremltools 包帮助您将来自各种训练工具的训练模型转换成核心 ML 模型。
import coremltools as ct
model = ct.convert(
mobile_net_traced,
inputs=[ct.ImageType(name="traced_input", shape=input.shape)]
classifier_config = ct.ClassifierConfig(class_labels)
)
model.save("MobileNetV2.mlmodel")
核心 ML 内部 ML 工具
从我们到目前为止所讨论的内容中,我们了解了 Core ML 是如何工作的,以及将模型从第三方库转换成 Core ML 格式是多么容易。现在,让我们来看看如何使用苹果内部的人工智能生态系统来构建、训练和部署一个 ML 模型。
苹果在他们的整个 ML 框架中集成的两个主要工具是:
Turi Create
如果您希望快速迭代模型实现,以完成系统推荐、对象检测、图像分割、图像相似性或活动分类等任务,这应该是您的目标。
Turi Create 非常有用的一点是,它已经为每个任务定义了预训练模型,您可以使用自定义数据集对其进行微调。Turi-Create 使您能够使用 python 构建和训练您的模型,然后将其导出到 Core ML,以便在 IOS、macOS、watchOS 和 tvOS 应用程序中使用。
What is incredibly useful with Turi Create is that it already defines pretrained models for each task that you can fine-tune with your custom datasets. Turi-Create enables you to build and train your model using python and then just export it to Core ML for use in IOS, macOS, watchOS, and tvOS apps.
机器学习任务
描述
个性化和定制用户选择
Description:
对图像进行标记和分类
Description:
识别图画和手势
Description:
识别和分类声音
Description:
分类和检测场景中的对象
Description:
风格化的图像和视频
Description:
使用传感器对活动进行检测和分类
Description:
寻找图像之间的相似之处
Description:
预测标签
Description:
预测数值
Description:
以无人监督的方式对相似的数据点进行分组
Description:
分析情感分析
Description:
创建 ML
与 Turi create 不同,Create ML 使用户能够构建和训练他们的 ML 模型,而无需编写太多代码。macOS 上可用的 Create ML 提供了一个图形界面,您可以在其中拖放您的训练数据,并选择您想要训练的模型类型(语音识别、图像分类、对象检测等)。)
核心 ML 3.0 中的新特性
在 2019 年 WWDC 发布会上,苹果发布了几个关于 Core ML 和板上新功能的有趣公告。我会给你一个关于新增强的快速总结,以防你错过。
到目前为止,Core ML 3.0 中引入的最令人兴奋的特性是可以直接在设备上训练部署的模型。在此之前,我们只有设备上的推理,这基本上意味着我们在其他机器上训练模型,然后利用训练好的模型在设备上进行预测。
通过设备上的培训,您可以执行转移学习或在线学习,在那里您可以调整现有的模型,以随着时间的推移提高性能和可持续性。
他们包括新型的神经网络层
他们主要关注中间操作层,如屏蔽、张量操作、控制流和布尔逻辑。
- 如果你对所有更新都感兴趣,请随时观看 WWDC 2019 视频。
人脸识别和 Apple Vision API
苹果的视觉框架旨在提供一个高级 API,包含随时可用的复杂计算机视觉模型。他们在 2019 年发布的最新版本包括令人兴奋的功能和改进,再次展示了设备上的机器学习模型是他们移动武器库中的一个巨大部分,他们肯定非常重视它。
用苹果自己的话说:
视觉 是一个新的功能强大且易于使用的框架,通过一致的接口为计算机视觉挑战提供解决方案。了解如何使用视觉来检测面部、计算面部标志、跟踪物体等。
vision API 可分为三个主要部分:
1。请求:当你请求框架分析实际场景,它返回给你任何被发现的物体。它被称为请求对进行分析。 不同种类的请求由多个 API 类处理:
vndetectfacerectangles 请求:人脸检测
VNDetectBarcodesRequest: 条形码检测
- VNDetectTextRectanglesRequest:图像内的可见文本区域
- VNCoreMLRequest :请求使用核心 ML 功能进行图像分析
- VNClassifyImageRequest :图像分类请求
- **VNDetectFaceLandmarksRequest:**请求分析人脸并检测特定的拓扑区域,如鼻子、嘴、嘴唇等。基于用包含计算的面部标志的数据训练的模型
- VNTrackObjectRequest: 视频场景内的实时对象跟踪。
- 2。请求处理器:分析并执行您触发的请求。它处理从发送请求到执行请求之间发生的所有相关的中间事务。
- VNImageRequestHandler :处理图像分析的请求
VNSequenceRequestHandler :处理实时对象跟踪的请求,例如,他们专注于跟踪制作视频时生成的各种图像序列或帧。
- **3。观察:**请求返回的结果被包装到观察类中,每个观察类引用相应的请求类型。
- **VNClassificationObservation:**图像分析产生的分类信息
VNFaceObservation :专门针对人脸检测。
- VNDetectedObjectObservation:用于物体检测。
- VNCoreMLFeatureValueObservation:用核心 ML 模型预测图像分析得到的键值信息的集合。
- vnhorizonto observation:确定场景中物体的角度和地平线。
- VNImageAlignmentObservation:检测对齐两幅图像内容所需的变换。
- VNPixelBufferObservation :嵌入式核心 ML 模型处理后的输出图像。
- 用 Turicreate 训练人脸识别模型
- 我们将训练一个图像分类器,利用 resnet-50 的 Turi-reate 预训练版本来检测和识别我们的正确面部。这个想法是用精选的人类面部数据集执行一些迁移学习,然后将模型导出到 Core ML,用于设备上部署。
设置
要继续学习,您需要在系统中安装 Python 3.6 和 anaconda。
然后会创建一个康达虚拟环境,安装 turicreate 5.0。
创建 conda 虚拟环境:
激活您的 conda 环境:
- 收集和分离培训数据
conda create --name face_recog python=3.6
- 为了训练我们的分类器,我们需要一些人脸样本和其他与人脸不对应的事物样本,如动物图像、实物等。最终,我们将需要创建两个数据文件夹,包含我们的脸和其余图像的图像。
conda activate face_recog
pip install turicreate==5.03
为了收集我们面部的图像,我们可以使用手机的前置摄像头给自己拍照。我们可以从 ImageNet 或任何其他类似的提供商那里获得其他图像。
数据扩充
数据扩充很有帮助,因为扫描过程中从前置摄像头拍摄的照片可能有不同的光照、曝光、方向、裁剪等,我们希望考虑所有的情况。
*Source: Author *
为了扩充我们的数据,我们将依赖一个非常有用的 python 包 Augmentor,它完全可以在 Github 上获得。
使用增强器,我们可以应用广泛的随机数据增强,如旋转、缩放、剪切或裁剪。我们将创建一个数据处理函数,负责所有的转换。
Augmentor 将生成 1500 个额外的面部数据样本。
模特培训
import Augmentor as augment
def data_processing(root_dir: str):
data = augment.Pipeline(root_dir)
data.rotate(probability=0.7, max_left_rotation=10, max_right_rotation=10)
data.zoom(probability=0.5, min_factor=1.1, max_factor=1.5)
data.skew(probability=0.5, magnitude=0.5)
data.shear(probability=0.5, max_shear_left=10, max_shear_right=10)
data.crop_random(probability=0.5, percentage_area=0.9, randomise_percentage_area=True)
data.sample(1500)
我们将在我们的虚拟环境中创建一个简单的 python 脚本,其中我们调用 turicreate resnet-50 预训练模型,并用我们收集的相应数据对其进行训练。
从培训文件夹加载图像
从文件夹名称创建目标标签:艾曼-面/非艾曼-面
- 用新数据微调模型
- 将训练好的模型导出到核心 ML 格式。
- 模型将开始训练,并在整个过程中显示历元结果。
- 构建 IOS 应用程序
import turicreate as tc
import os
data = tc.image_analysis.load_images('Training Data', with_path=True)
data['label'] = data['path'].apply(lambda path: os.path.basename(os.path.dirname(path)))
model = tc.image_classifier.create(data, target='label', model='resnet-50', max_iterations=100)
model.export_coreml('face_recognition.mlmodel')
我们将建立一个小的 IOS 应用程序,检测和识别我的脸在前置摄像头流。该应用程序将触发我的 iphone 的前置摄像头,并使用我们之前训练的 turicreate 模型进行实时人脸识别。
Displaying training stats on the terminal
打开 XCode 并创建一个单视图应用程序。应用程序的一般 UX 相当简单,有两个 ViewControllers:
入口点 ViewController 定义了一个极简布局,带有一个自定义按钮来激活前置摄像头
一个 CameraViewController,管理相机流并执行实时推理来识别我的脸。
- 设置布局
- 让我们去掉主要的故事板文件,因为我总是喜欢以编程方式编写所有的应用程序,而完全不依赖于任何 XML。
删除主故事板文件,更改 info.plist 文件以删除故事板名称,并编辑 SceneDelegate 文件:
设计入口点 LayoutViewController 的布局,将应用程序的徽标图像放在最上面部分的中心,并将导航到 CameraViewController 的按钮设置在其稍下方。
- ViewController 布局:
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(frame: windowScene.coordinateSpace.bounds)
window?.windowScene = windowScene
window?.rootViewController = LayoutViewController()
window?.makeKeyAndVisible()
}
处理人脸识别方法:
Application Mockup, Source: Author
let logo: UIImageView = {
let image = UIImageView(image:
image.translatesAutoresizingMaskIntoConstraints = false
return image
}()
let faceRecognitionButton: CustomButton = {
let button = CustomButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.addTarget(self, action:
button.setTitle("Object detection", for: .normal)
let icon = UIImage(systemName: "crop")?.resized(newSize: CGSize(width: 50, height: 50))
button.addRightImage(image: icon!, offset: 30)
button.backgroundColor = .systemPurple
button.layer.borderColor = UIColor.systemPurple.cgColor
button.layer.shadowOpacity = 0.3
button.layer.shadowColor = UIColor.systemPurple.cgColor
return button
}()
- 人脸识别视图控制器
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemBackground
addButtonsToSubview()
}
fileprivate func addButtonsToSubview() {
view.addSubview(logo)
view.addSubview(faceRecognitionButton)
}
fileprivate func setupView() {
logo.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
logo.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor, constant: 20).isActive = true
faceRecognitionButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
faceRecognitionButton.widthAnchor.constraint(equalToConstant: view.frame.width - 40).isActive = true
faceRecognitionButton.heightAnchor.constraint(equalToConstant: 60).isActive = true
faceRecognitionButton.bottomAnchor.constraint(equalTo: openToUploadBtn.topAnchor, constant: -40).isActive = true
}
- 该 ViewController 采用实时摄像机预览,并触发模型对摄像机流产生的每一帧进行实时推理。在操作每个视频帧时,我们应该格外小心,因为我们可能会由于实时推断而使可用资源迅速超载,并使应用程序崩溃,从而导致内存泄漏。
@objc func handleFaceRecognition() {
let controller = FaceRecognitionViewController()
let navController = UINavigationController(rootViewController: controller)
self.present(navController, animated: true, completion: nil)
}
为了在相机设置过程中保持稳定的每秒帧数,建议将分辨率和视频质量降低到:30 FPS 和 640×480。
实例化模型
var videoCapture: VideoCapture!
let semaphore = DispatchSemaphore(value: 1)
let videoPreview: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.videoCapture.start()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
self.videoCapture.stop()
}
// MARK: - SetUp Camera preview
func setUpCamera() {
videoCapture = VideoCapture()
videoCapture.delegate = self
videoCapture.fps = 30
videoCapture.setUp(sessionPreset: .vga640x480) { success in
if success {
if let previewLayer = self.videoCapture.previewLayer {
self.videoPreview.layer.addSublayer(previewLayer)
self.resizePreviewLayer()
}
self.videoCapture.start()
}
}
}
我们需要实例化之前获得的核心 ML 模型( face_recognition.mlmodel )并开始进行预测。这个想法是通过输入帧来触发模型。该模型应返回封装边界框的多数组对象。最后的步骤将是预测,解析对象,并在脸部周围画一个方框。
实现VideoCaptureDelegate启动模型推理。
定义对每一帧执行推理的预测函数。
func initModel() {
if let faceRecognitionModel = try? VNCoreMLModel(for: face_recognition().model) {
self.visionModel = visionModel
request = VNCoreMLRequest(model: visionModel, completionHandler: visionRequestDidComplete)
request?.imageCropAndScaleOption = .scaleFill
} else {
fatalError("fail to create the model")
}
}
- 最后,在后处理阶段,在每个预测上画一个方框。
extension FaceRecognitionViewController: VideoCaptureDelegate {
func videoCapture(_ capture: VideoCapture, didCaptureVideoFrame pixelBuffer: CVPixelBuffer?, timestamp: CMTime) {
// the captured image from camera is contained on pixelBuffer
if !self.isInferencing, let pixelBuffer = pixelBuffer {
self.isInferencing = true
// make predictions
self.predictFaces(pixelBuffer: pixelBuffer)
}
}
}
- 扩展 facecognitionviewcontroller { func visionrequestdiddomplete(请求:VNRequest,错误:error?){ if let predictions = request . results as?[VNRecognizedObjectObservation]{ dispatch queue . main . async { self。bounding box view . predicted objects = predictions self . is referencing = false } } else self . semaphore . signal()} }
extension FaceRecognitionViewController {
func predictFaces(pixelBuffer: CVPixelBuffer) {
guard let request = request else { fatalError() }
self.semaphore.wait()
let handler = VNImageRequestHandler(cvPixelBuffer: pixelBuffer)
try? handler.perform([request])
}
- 最终输出
结论
苹果的 vision API 为希望将 ML 模型集成到他们的应用程序中的移动开发者开辟了新的可能性。整个图书馆的设计非常直观,易于理解。没有必要携带机器学习的重要背景来享受核心 ML 的乐趣,开箱即用的各种工具和功能非常令人鼓舞。
苹果通过增加对新架构的支持来不断改进他们的 ML 库,并确保与他们的硬件无缝集成。
您可以随时通过改进数据集或创建自己的网络并使用 coremltools 进行转换来改进这些模型。
参考
艾曼·哈克姆
Spotbills 的数据科学家|机器学习爱好者。
阅读下一篇
ML 实验跟踪:它是什么,为什么重要,以及如何实施
10 分钟阅读|作者 Jakub Czakon |年 7 月 14 日更新
ML Experiment Tracking: What It Is, Why It Matters, and How to Implement It
我来分享一个听了太多次的故事。
“…我们和我的团队正在开发一个 ML 模型,我们进行了大量的实验,并获得了有希望的结果…
…不幸的是,我们无法确切地说出哪种性能最好,因为我们忘记了保存一些模型参数和数据集版本…
…几周后,我们甚至不确定我们实际尝试了什么,我们需要重新运行几乎所有的东西"
不幸的 ML 研究员。
事实是,当你开发 ML 模型时,你会进行大量的实验。
这些实验可能:
使用不同的模型和模型超参数
使用不同的培训或评估数据,
- 运行不同的代码(包括您想要快速测试的这个小变化)
- 在不同的环境中运行相同的代码(不知道安装的是 PyTorch 还是 Tensorflow 版本)
- 因此,它们可以产生完全不同的评估指标。
- 跟踪所有这些信息会很快变得非常困难。特别是如果你想组织和比较这些实验,并且确信你知道哪个设置产生了最好的结果。
这就是 ML 实验跟踪的用武之地。
Keeping track of all that information can very quickly become really hard. Especially if you want to organize and compare those experiments and feel confident that you know which setup produced the best result.
This is where ML experiment tracking comes in.
交叉熵损失及其在深度学习中的应用
在 21 世纪,大多数企业都在使用机器学习和深度学习来自动化他们的流程、决策、提高疾病检测的效率等。公司如何优化这些模型?他们如何确定模型的效率?评估模型效率的一种方法是**准确性。**精度越高,模型效率越高。因此,有必要通过优化模型来提高精度;通过应用 损失函数 **。**在这篇文章中,我们学习下面的内容,更侧重于 交叉熵函数 。
- 什么是损失函数?
- 离散损失函数和连续损失函数的区别。
- 交叉熵损失函数。(在二分类和多类分类中,理解交叉熵公式)
- 在深度学习框架中应用交叉熵;PyTorch 和 TensorFlow。
损失函数
在大多数情况下,误差函数和损失函数的意思是相同的,但有微小的区别。
一个误差函数测量/计算我们的模型偏离正确预测的程度。
一个损失函数对误差进行运算,以量化特定大小/方向的误差有多糟糕,该误差受到导致不正确预测的负面后果的影响。
损失函数可以是离散的,也可以是连续的。
连续和离散误差/损失函数
我们将用两个例子来理解连续和离散损失函数。
插图 1
想象一下,你想在一个阴天从一座大山的山顶上下来。你是如何选择正确的方向一直走到底部的?
你将不得不考虑所有可能的方向,并选择一个使你下降最多的方向。你朝着选定的方向前进,从而降低高度,重复同样的过程,总是降低高度,直到你到达你的目标=山脚。
注意,我们用高度来衡量我们离底部有多远。降低高度意味着我们离目标更近了。我们可以将高度称为误差函数(测量/计算我们离底部有多远)。
插图 2
让我们看另一个例子。哪个误差函数适合解决下面的问题?蓝点代表通过考试的学生,而红点代表失败的学生。
我们开发了一个模型来预测学生是不及格还是及格。下图中的线条代表模型预测。
一个红点在蓝色区域,一个蓝点在红色区域,这意味着预测线导致 2 个错误。
你如何解决这个错误?
为了解决这个错误,我们移动这条线以确保所有的正面和负面预测都在正确的区域。
在大多数现实生活中的机器学习应用程序中,我们很少像上面那样对预测线进行如此剧烈的移动。我们应用小步骤来最小化误差。如果我们在上面的例子中移动小步长,我们可能会以相同的误差结束,这就是离散误差函数的情况。
然而,在图 1 中,由于山的坡度不同,我们可以检测到我们高度的微小变化(误差)并采取必要的措施,这是连续误差函数的情况。
Sigmoid 函数
为了将误差函数从离散型转换为连续型误差函数,我们需要对每个学生的线性得分值应用一个激活函数,这将在后面讨论。
比如图 2 中的 ,模型预测输出决定一个学生会及格还是不及格;这个模型回答了这个问题,学生 A 会通过 SAT 考试吗?
一个连续的问题是,学生 A 通过 SAT 考试的可能性有多大?答案是 30%或 70%等等。,有可能。
我们如何确保我们的模型预测输出在(0,1)范围内或连续?我们对每个学生的线性分数应用一个激活函数。我们的例子是我们所说的二进制分类,其中有两类,要么通过,要么失败。在这种情况下,应用的激活函数被称为s 形激活函数。
通过以上做法,错误不再是两个学生没有通过 SAT 考试,而是学生每个错误的总和。
在图 2 中使用概率可以更容易地对每个学生的误差(他们离及格有多远)求和,从而更容易地逐步移动预测线,直到我们获得最小的求和误差。
下面的公式表示 sigmoid 函数( x 是每个点的值):
Softmax 函数
在最后几段中,我们发现 sigmoid 激活对二进制分类问题有效。有两个以上的类要分类的情况会怎样?如下图所示:
我们试图回答的问题是:颜色是蓝色、绿色还是红色?
在这种情况下,回答不是是/否,而是两者之一(绿色、蓝色或红色)
如何将响应从(蓝色、绿色和红色)转换成可能的颜色(绿色/红色/蓝色)?
在深度学习中,该模型将线性回归应用于每个输入,即输入特征的线性组合,并且表示为:
您可以查看线性回归的基础知识以获得更多理解。
假设线性回归函数根据类别/输入参数/特征给出以下分数:
蓝色= 2,绿色= 1,红色= -1
获得概率的最简单方法是:
上述转换将适用于正分数。如果有负分怎么办,记住,概率一定在 0-1 之间?比如红色班,分数为负;我们如何将分数转化为正值?
我们在所有分数上使用指数:
蓝色=
=0.705
绿色=
=0.259
红色=
=0.035
指数将概率转换为 0-1 的范围
我们有 n 个类,我们要找出个类的概率 x 会,用线性得分 **A1,A2… An,**来计算每个类的概率。
上面的函数是 **softmax 激活函数,**其中 i 是类名。
为了理解交叉熵,有必要讨论损失函数和激活函数,即将离散预测转化为连续预测。我们现在将深入交叉熵函数。
交叉熵
克劳德·香农在他 1948 年的论文《交流的数学理论》中引入了信息熵的概念。根据香农的说法,随机变量的熵是变量可能结果中固有的“信息”、“惊喜”或“不确定性”的平均水平。
听起来熟悉吗?
我们可以看到,随机变量的熵与我们引入的概念的误差函数有关。不确定度的平均水平指的是误差。
交叉熵 建立在信息论熵的思想上,测量给定随机变量/事件集的两个概率分布之间的差异。
交叉熵可以应用于二分类和多分类问题。我们将讨论在每种情况下使用交叉熵的区别。
二元交叉熵
让我们考虑一下前面的例子,我们回答一个学生是否会通过 SAT 考试。在这种情况下,我们和四个学生一起工作。我们有两个模型,A 和 B,预测这四个学生通过考试的可能性,如下图所示。
注。 前面我们讨论过 “在深度学习中,模型对每个输入应用线性回归,即输入特征的线性组合。
每个模型将线性回归函数(f(x) = wx + b) 应用于每个学生,以生成线性分数。然后使用 sigmoid 函数将线性得分转换为概率。让我们假设这两个模型给出了图表的概率,其中蓝色区域表示通过,而红色区域表示失败。
模型 A
模型 B
上图显示,模型 B 比模型 A 执行得更好,因为它正确地对各自区域的所有学生进行了分类。所有概率的乘积决定了模型的最大似然。
乘积概率 : 同时发生的两个(或多个)独立事件的概率是通过乘以事件各自的概率来计算的。
我们想通过乘以每个独立学生的概率来计算模型的总概率。
产品概率模型 A:
0.1 * 0.7 * 0.6 * 0.2 = 0.0084
产品概率模型 B:
0.8 * 0.6 * 0.7 * 0.9 = 0.3024
模型 B 的产品概率优于模型 a。
产品概率在我们有几个项目要预测时效果更好,但现实生活中的模型预测却不是这样。
例如,如果我们有一个满是 1000 名学生的班级,不管你的模型有多好,乘积概率总是接近于 0。如果我们也改变一个概率,产品会发生剧烈变化,给人一种模型表现良好的错误印象。因此,我们需要使用对数函数将乘积转换为总和。
测井模型 A:
对数(0.1) +对数(0.7) +对数(0.6) +对数(0.2)
-1 + -0.154 + -0.221 + -0.698 = -2.073
测井模型 B:
对数(0.8) +对数(0.6) +对数(0.7) +对数(0.9)
-0.09 + -0.22 + -0.15 + -0.045 = -0.505
介于 0 和 1 之间的数的对数总是负数。以上是评价我们模型性能的更好方法吗?不完全是。相反,我们将采用预测概率的负对数。
负对数模型 A:
-对数(0.1)+-对数(0.7)+-对数(0.6)+-对数(0.2)
1 + 0.154 + 0.221 + 0.698 = 2.073
负对数模型 B:
-对数(0.8) +-对数(0.6)+-对数(0.7)+-对数(0.9)
0.09 + 0.22 + 0.15 + 0.045 = 0.505
交叉熵损失是每个学生预测概率的负对数之和。 模型 A 的交叉熵损失为 2.073;B 型的是 0.505。交叉熵很好地衡量了每个模型的有效性。
二元交叉熵公式
在我们的四个学生预测中——模型 B:
A | B | C | D | 可能性 |
---|---|---|---|---|
P1=0.8(失败) | P2=0.6(失败) | P3=0.7(通过) | P4=0.9(通过) | 通过概率 |
1–P1 | 1–P2 | P3 | P4 | 如果学生通过 else 0,则 yi = 1,因此: |
y1= 0 | ||||
y2 = 0 | y3 = 1 | y4 = 1 | 学生 C 的交叉熵: | 蓝色代表学生证。红色代表学生失败。 |
学生 A 的交叉熵
请注意,我们使用每个学生的预测概率来计算交叉熵。我们将纳入公式,包括概率是如何产生的。之前,我们讨论了二分类中使用的 sigmoid 激活函数,用于将线性函数得分转换为概率。这是使用激活的交叉熵函数:
其中:
S**[I]**–输入/权重
f–这种情况下的激活功能,
t–目标预测
- **I—**要预测的类。
- BCE =
- 多类交叉熵/分类交叉熵
- 对于多类分类问题,我们使用多类交叉熵。假设我们需要创建一个模型来预测水果的类型/种类。我们有三种不同容器的水果(橘子、苹果、柠檬)。
水果
容器一
概率
容器 B
概率
| 容器 C
概率 | 橙色 | 0.7 | 0.3 |
| --- | --- | --- | --- |
| 0.1 | 苹果 | 0.2 | 0.4 |
| 0.5 | 柠檬 | 0.1 | 0.3 |
| 0.4 | 每个容器的概率总和需要为 1。 | 容器 A | 容器 B |
集装箱 C
正确的水果放在
各自的容器里
| 橙子 | 柠檬 | 柠檬 | 预测的概率
证明水果是正确的 |
| --- | --- | --- | --- |
| 0.7 | 0.3 | 0.4 | 产品概率= 0.7 * 0.3 * 0.4 = 0.084 |
| 交叉熵=-log(0.7)+–log(0.3)+-log(0.4)= 1.073 | 多类交叉熵公式 | 让我们将概率值指定为变量: | 水果 |
容器一
概率
容器 B
概率
容器 C
概率
橙色
P1T2 一
P1T2 B | P1T2【C3】 | 苹果 | p2T2 |
---|---|---|---|
p2T2 B | P2T2【C3】 | 柠檬 | P3T2 |
P3T2 B | P3T2【C3】 | 容器 A 中的橙子、苹果或柠檬的概率是多少?我们分别有 0.7、0.2 和 0.1 。 | 如果容器 A 包含特定的水果,则其 y1 值等于 1;否则为 0。 |
y1 [A,–]如果是橙子 | y2[A–]如果是苹果 | y3[A—]如果是柠檬。 | 容器 A 的交叉熵: |
容器 B 的交叉熵:
容器 C 的交叉熵:
设我们的类(1,2,3)等于 I,容器(A,B,C)等于 j。
- 交叉熵容器 A:
- 交叉熵容器 B:
- 交叉熵容器 C:
在总交叉熵损失中,我们的类由 I 定义;因此,我们可以将(y1,y2,y3)等同于 I:
总交叉熵 :
我们使用总交叉熵公式计算多类分类中的交叉熵。
整合激活功能:
多类交叉熵
CE=
如何应用交叉熵?
我们已经讨论了交叉熵损失用于二分类和多分类。让我们看看如何应用交叉熵的例子:
PyTorch
1。使用 Pytorch 简单说明二元交叉熵
请确保您安装了 PyTorch 遵循此处的指南。
使用 PyTorch random 生成输入特征(X)和标签(y)值。
让我们来看看 X 的值:
Y 的值:
在我们的讨论中,我们使用 sigmoid 函数作为输入的激活函数。我们将把 PyTorch sigmoid 模块传递给我们的输入(X)特性。
Pytorch 二元交叉熵损失:
2。使用 Pytorch 的分类交叉熵
PyTorch 分类交叉熵模块,softmax 激活函数已经应用于公式。因此,我们不会像在前面的例子中那样使用激活函数。
import torch
import torch.nn as nn
我们仍然使用 PyTorch 随机数来生成输入要素(X)和标注(y)值。
X = torch.randn(10)
y = torch.randint(2, (10,), dtype=torch.float)
由于这是一个多类问题,输入要素有五个类(class_0,class_1,class_2,class_3,class_4)
print(X)
tensor([ 0.0421, -0.6606, 0.6276, 1.2491, -1.1535, -1.4137, 0.8967, -1.1786,
-1.3214, 0.2828])
多类交叉熵计算如下:
print(y)
tensor([1., 0., 0., 1., 0., 0., 1., 0., 0., 0.])
跨不同深度学习框架计算交叉熵是一样的;让我们看看如何在 TensorFlow 中实现同样的功能。
X_continous_values = torch.sigmoid(X)
print(X_continous_values)
tensor([0.5105, 0.3406, 0.6519, 0.7772, 0.2398, 0.1957, 0.7103, 0.2353, 0.2106,
0.5702])
海王星与 PyTorch 的融合
loss = nn.BCELoss()(X_continous_values, y)
print(loss)
tensor(1.0966)
TensorFlow
1。二元交叉熵:
假设我们的实际值和预测值如下:
使用 tensor flowBinaryCrossentropy()模块:
X = torch.randn(10, 5)
print(X)
tensor([[-0.5698, -0.0558, -0.2550, 1.6812, 0.0238],
[-2.1786, 1.3923, -0.2363, -0.4601, -1.4949],
[ 1.3679, 1.2853, 0.4087, -0.5743, -0.2752],
[ 2.1995, 0.1469, -0.1661, 0.4617, -0.4395],
[-0.5686, -0.7453, -0.1455, -0.5304, 0.3020],
[-0.1489, -0.9143, -1.5282, -0.5023, 1.2751],
[-1.3830, -0.6535, 0.5392, -2.2050, -1.4138],
[-0.5592, 1.5028, 0.0442, -1.5487, -0.1522],
[ 0.7436, -1.8956, 1.0145, -0.2974, -2.0576],
[ 0.1003, 0.6604, -1.3535, -0.3053, -0.4034]])
y = torch.randint(5, (10,))
print(y)
tensor([3, 0, 1, 1, 2, 4, 0, 2, 1, 3])
2。分类交叉熵
loss = nn.CrossEntropyLoss()(X, y)
print(loss)
tensor(1.9732)
假设我们有三个类(猫、狗、熊)要预测。我们实际的形象/阶级是一只狗;因此,我们理论上有(0,1,0)。其中 1 表示实际图像,0 表示图像不是狗。我们的价值观将是:
假设模型预测图像有 5%可能是猫,85%是狗,10%是熊。那么我们的预测值将是:
使用 TensorFlow 分类交叉熵()模块,我们计算损失如下:
海王星与张量流的融合
import tensorflow as tf
结论
actual_values = [0, 1, 0, 0, 0, 0]
predicted_values = [.5, .7, .2, .3, .5, .6]
本文涵盖了损失函数的核心概念,主要是交叉熵。我希望它能让你更好地理解交叉熵,以及它是如何用于二元和多类分类问题的,并且你能够在你的案例场景中应用它。
binary_cross_entropy = tf.keras.losses.BinaryCrossentropy()
loss = binary_cross_entropy(actual_values, predicted_values)
print(loss.numpy)
0.53984624
资源:
Let’s say we have three classes(cat, dog, bear) to predict. Our actual image/class is a dog; therefore, we have theoretically (0, 1, 0). Where 1 represents the actual image and 0, where the image is not a dog. Our values will be:
actual_values = [0, 1, 0]
Hypothetically the model predicts that the image is 5% likely to be a cat, 85% a dog, and 10% a bear. Then our predicted values will be:
predicted_values = [0.05, 0.85, 0.10]
Using the TensorFlow Categorical Cross Entropy() module, we calculate loss as follows:
loss = tf.keras.losses.CategoricalCrossentropy()
loss = loss(actual_values, predicted_values)
print(loss.numpy)
0.1625189
Neptune’s integration with TensorFlow
Conclusion
This article covers the core concepts of Loss functions, mainly the Cross-Entropy. I hope it gives you a better understanding of cross-entropy and how it’s used for both binary and multi-class classification problems and that you are in a position to apply it in your case scenario.
Resources:
机器学习中的交叉验证:如何正确进行
在机器学习(ML)中,泛化通常指的是算法在各种输入中有效的能力。这意味着 ML 模型不会遇到来自相同训练数据分布的新输入的性能下降。
对人类来说,概括是最自然不过的事情了。我们可以即时分类。例如,我们肯定会认出一只狗,即使我们以前没有见过这个品种。然而,对于 ML 模型来说,这可能是一个相当大的挑战。这就是为什么在构建模型时,检查算法的泛化能力是一项需要大量注意力的重要任务。
为此,我们使用 交叉验证 ( CV )。
在本文中,我们将涵盖:
- 什么是交叉验证:定义、使用目的和技术
- 不同的 CV 技术:保持、k 折叠、留一、留 p、分层 k 折叠、重复 k 折叠、嵌套 k 折叠、时间序列 CV
- 如何使用这些技术:sklearn
- 机器学习中的交叉验证:sklearn,CatBoost
- 深度学习中的交叉验证:Keras,PyTorch,MxNet
- 最佳实践和提示:时间序列、医疗和财务数据、图像
什么是交叉验证?
交叉验证是一种评估机器学习模型并测试其性能的技术。CV 常用于应用型 ML 任务。它有助于为特定的预测建模问题比较和选择合适的模型。
CV 易于理解,易于实施,并且与用于计算模型效率得分的其他方法相比,它倾向于具有较低的偏差。所有这些使得交叉验证成为为特定任务选择最佳模型的有力工具。
有很多不同的技术可以用来交叉验证模型。尽管如此,它们都有一个相似的算法:
- 将数据集分成两部分:一部分用于训练,另一部分用于测试
- 在训练集上训练模型
- 在测试集上验证模型
- 重复 1-3 步几次。该数字取决于您正在使用的CV 方法
你可能知道,有很多简历技巧。有些是常用的,有些只是理论上的。让我们来看看本文将涉及的交叉验证方法。
- 坚持
- k 倍
- 留一个出来
- 漏接
- 分层 K 折叠
- 重复 K 倍
- 嵌套 K 折叠
- 时间序列 CV
保留交叉验证
保留交叉验证是最简单和最常见的技术。你可能不知道这是一种坚持的方法,但你肯定每天都在用。
保持技术的算法;
- 将数据集分为两部分:训练集和测试集。通常,数据集的 80%用于训练集,20%用于测试集,但是您可以选择更适合您的任何拆分
- 在训练集上训练模型
- 在测试集上验证
- 保存验证的结果
就是这样。
我们通常在大型数据集上使用 hold-out 方法,因为它只需要训练模型一次。
实施 hold-out 真的很容易。例如,您可以使用 sk learn . model _ selection . train _ test _ split 来完成。
import numpy as np
from sklearn.model_selection import train_test_split
X, y = np.arange(10).reshape((5, 2)), range(5)
X_train, X_test, y_train, y_test = train_test_split(X, y,
test_size=0.2,
random_state=111)
尽管如此,拒绝合作还是有一个很大的缺点。
例如,分布不完全均匀的数据集。如果是这样的话,我们可能会在分拆后陷入困境。例如,训练集不会代表测试集。训练集和测试集可能差别很大,其中一个可能更容易或更难。
此外,我们只测试我们的模型一次的事实可能是这种方法的瓶颈。由于前面提到的原因,通过保持技术获得的结果可能被认为是不准确的。
k 倍交叉验证
k 倍交叉验证是一种最大限度减少拒绝法缺点的技术。k-Fold 引入了一种分割数据集的新方法,有助于克服“只测试一次的瓶颈”。
k 倍技术的算法:
- 选择折叠数–k。通常,k 为 5 或 10,但您可以选择小于数据集长度的任何数字。
- 将数据集分成 k 个相等(如果可能)的部分(它们被称为折叠)
- 选择 k–1 折叠作为训练集。剩余的折叠将是测试集
- 在训练集上训练模型。在交叉验证的每次迭代中,您必须独立于前一次迭代中训练的模型来训练新的模型
- 在测试集上验证
- 保存验证的结果
- 重复步骤 3-6k 次。每次使用剩余的折叠作为测试集。最后,你应该在你的每一次折叠中验证这个模型。
- 要获得最终分数,请对第 6 步中得到的结果进行平均。
要执行 k-Fold 交叉验证,可以使用 sklearn.model_selection.KFold。
import numpy as np
from sklearn.model_selection import KFold
X = np.array([[1, 2], [3, 4], [1, 2], [3, 4]])
y = np.array([1, 2, 3, 4])
kf = KFold(n_splits=2)
for train_index, test_index in kf.split(X):
print("TRAIN:", train_index, "TEST:", test_index)
X_train, X_test = X[train_index], X[test_index]
y_train, y_test = y[train_index], y[test_index]
总的来说,使用 k 折技术总比持有要好。在面对面的情况下,比较 k 倍给出了更稳定和可信的结果,因为训练和测试是在数据集的几个不同部分上执行的。如果我们增加折叠次数,在许多不同的子数据集上测试模型,我们可以使总得分更加稳健。
尽管如此,k-Fold 方法有一个缺点。增加 k 导致训练更多的模型,并且训练过程可能非常昂贵和耗时。
留一交叉验证
留一法сRoss-validation(LOOCV)是 k 倍 CV 的极端案例。想象一下如果 k 等于 n 其中 n 是数据集中样本的数量。这种 k 折情况相当于留一法技术。
LOOCV 技术的算法:
- 从数据集中选择一个样本作为测试集
- 剩余的 n-1 个样本将成为训练集
- 在训练集上训练模型。在每次迭代中,必须训练一个新的模型
- 在测试集上验证
- 保存验证的结果
- 重复步骤 1-5n 次,因为对于 n 个样本,我们有 n 个不同的训练和测试集
- 要获得最终分数,请对第 5 步中得到的结果进行平均。
对于 LOOCV,sklearn 也有一个内置的方法。可以在 model_selection 库–sk learn . model _ selection . leave one out 中找到。
import numpy as np
from sklearn.model_selection import LeaveOneOut
X = np.array([[1, 2], [3, 4]])
y = np.array([1, 2])
loo = LeaveOneOut()
for train_index, test_index in loo.split(X):
print("TRAIN:", train_index, "TEST:", test_index)
X_train, X_test = X[train_index], X[test_index]
y_train, y_test = y[train_index], y[test_index]
留一交叉验证的最大优点是不会浪费太多数据。我们只使用整个数据集中的一个样本作为测试集,而其余的是训练集。但与 k-Fold CV 相比,LOOCV 需要建立 n 个模型而不是 k 个模型,因为我们知道代表数据集中样本数量的 n 比 k 大得多。这意味着 LOOCV 比 k-Fold 的计算成本更高,使用 LOOCV 交叉验证模型可能需要大量时间。
因此,数据科学界有一个基于经验证据和不同研究的一般规则,这表明 5 倍或 10 倍交叉验证应优于 LOOCV。
遗漏交叉验证
留一法交叉验证 ( LpOC )类似于留一法 CV ,它通过使用 p 样本作为测试集来创建所有可能的训练和测试集。所有提到的关于 LOOCV 的都是真的,对于 LpOC 。
不过,值得一提的是,与 LOOCV 不同,如果 p 大于 1,LpOC 的 k 倍测试集将重叠。
LpOC 技术的算法;
- 从将成为测试集的数据集中选择 p 个样本
- 剩余的 n–p 个样本将成为训练集
- 在训练集上训练模型。在每次迭代中,必须训练一个新的模型
- 在测试集上验证
- 保存验证的结果
- 重复步骤 2–5c[p]n 次
- 要获得最终分数,请对第 5 步中得到的结果进行平均
您可以使用 sk learn–sk learn . model _ selection . Leave pout 执行 Leave-p-out CV。
import numpy as np
from sklearn.model_selection import LeavePOut
X = np.array([[1, 2], [3, 4], [5, 6], [7, 8]])
y = np.array([1, 2, 3, 4])
lpo = LeavePOut(2)
for train_index, test_index in lpo.split(X):
print("TRAIN:", train_index, "TEST:", test_index)
X_train, X_test = X[train_index], X[test_index]
y_train, y_test = y[train_index], y[test_index]
LpOC 具有 LOOCV 的所有缺点,但无论如何,它和 LOOCV 一样强大。
分层 k 倍交叉验证
有时,我们可能会面临数据集中目标值的巨大不平衡。例如,在关于手表价格的数据集中,可能有大量价格高的手表。在分类的情况下,在猫和狗的数据集中,可能有很大的向狗类的转移。
分层 k-Fold 是标准 k-Fold CV 技术的一种变体,该技术被设计成在目标不平衡的情况下有效。
它的工作原理如下。分层 k 折叠将数据集分成 k 个折叠,使得每个折叠包含与完整集大致相同百分比的每个目标类的样本。在回归的情况下,分层 k-Fold 确保平均目标值在所有 Fold 中大致相等。
分层 k 折叠技术的算法;
- 选择一些折叠–k
- 将数据集分割成 k 个折叠。每个文件夹必须包含与完整集大致相同百分比的每个目标类别的样本
- 选择 k–1 个折叠作为训练集。剩余的折叠将是测试集
- 在训练集上训练模型。在每次迭代中,必须训练一个新的模型
- 在测试集上验证
- 保存验证的结果
- 重复步骤 3-6k 次。每次使用剩余的折叠作为测试集。最后,你应该在你的每一次折叠中验证这个模型。
- 要获得最终分数,请对第 6 步中得到的结果进行平均。
您可能已经注意到,分层 k 折叠技术的算法类似于标准 k 折叠。您不需要额外编写代码,因为该方法会为您做所有必要的事情。
分层 k-Fold 在 sklearn 中也有一个内置的方法——sk learn . model _ selection . stratifiedkfold。
import numpy as np
from sklearn.model_selection import StratifiedKFold
X = np.array([[1, 2], [3, 4], [1, 2], [3, 4]])
y = np.array([0, 0, 1, 1])
skf = StratifiedKFold(n_splits=2)
for train_index, test_index in skf.split(X, y):
print("TRAIN:", train_index, "TEST:", test_index)
X_train, X_test = X[train_index], X[test_index]
y_train, y_test = y[train_index], y[test_index]
上面提到的所有关于 k-Fold CV 对于分层 k-Fold 技术都是正确的。在选择不同的 CV 方法时,请确保您使用的是正确的方法。例如,您可能会认为您的模型性能很差,仅仅是因为您使用 k-Fold CV 来验证在具有类不平衡的数据集上训练的模型。为了避免这种情况,您应该始终对您的数据进行适当的探索性数据分析。
重复 k 倍交叉验证
重复 k 倍交叉验证或重复随机子抽样 CV 可能是本文所有 CV 技术中最稳健的。它是 k-Fold 的变体,但是在重复 k-Fold****的情况下,k 不是折叠的次数。这是我们训练模型的次数。
总的想法是,在每次迭代中,我们将在整个数据集中随机选择样本作为我们的测试集。例如,如果我们决定数据集的 20%将成为我们的测试集,那么将随机选择 20%的样本,剩下的 80%将成为训练集。
重复 k 倍技术的算法;
- 选择 k–模型将被训练的次数
- 挑选一些样本作为测试集
- 分割数据集
- 在训练器械上进行训练。在交叉验证的每次迭代中,必须训练一个新的模型
- 在测试集上验证
- 保存验证的结果
- 重复步骤 3-6 k 次
- 要获得最终分数,请对第 6 步中得到的结果进行平均。
重复 k 倍比标准 k 倍 CV 有明显的优势。首先,训练/测试分割的比例不依赖于迭代的次数。其次,我们甚至可以为每次迭代设置唯一的比例。第三,从数据集中随机选择样本使得重复 k-Fold 对选择偏差更加鲁棒。
尽管如此,还是有一些缺点。k-Fold CV 保证模型将在所有样本上进行测试,而重复 k-Fold 基于随机化,这意味着一些样本可能永远不会被选入测试集。同时,一些样本可能被选择多次。因此对于不平衡的数据集来说,这是一个糟糕的选择。
Sklearn 会帮你实现一个重复的 k 倍 CV。只需使用 sklearn . model _ selection . repeated kfold。在 sk learn 实现该技术时,您必须设置想要的折叠次数(n_splits)和将要执行的分割次数(n_repeats)。它保证您在每次迭代中都有不同的折叠。
import numpy as np
from sklearn.model_selection import RepeatedKFold
X = np.array([[1, 2], [3, 4], [1, 2], [3, 4]])
y = np.array([0, 0, 1, 1])
rkf = RepeatedKFold(n_splits=2, n_repeats=2, random_state=42)
for train_index, test_index in rkf.split(X):
print("TRAIN:", train_index, "TEST:", test_index)
X_train, X_test = X[train_index], X[test_index]
y_train, y_test = y[train_index], y[test_index]
嵌套 k 折叠
与旨在评估算法质量的其他 CV 技术不同,嵌套 k 重 CV 用于训练模型,其中超参数也需要优化。它估计基础模型及其(超)参数搜索的泛化误差。
Nested k-Fold cross-validation resampling | Source
嵌套 k 折叠技术的算法;
- 为当前模型定义一组超参数组合 C。如果模型没有超参数,C 就是空集。
- 将数据分成 K 份,病例和对照的分布大致相等。
- (外循环)对于折叠 K,在 K 折叠中:
- 将折叠 k 设置为测试集。
- 对剩余的 K-1 个折叠执行自动特征选择。
- 对于 C 中的参数组合 C:
- (内部循环)对于折叠 K,在剩余的 K-1 个折叠中:
- 将折叠 k 设置为验证集。
- 剩余 K-2 褶皱上的火车模型。
- 在折叠 k 上评估模型性能
- 计算参数组合 c 的 K-2 倍平均性能。
- (内部循环)对于折叠 K,在剩余的 K-1 个折叠中:
- 使用超参数组合在 K-1 个折叠上训练模型,该超参数组合在内部循环的所有步骤上产生最佳平均性能。
- 在折叠 k 上评估模型性能
- 计算 K 倍的平均性能。
内部循环执行交叉验证,以使用外部循环的每次迭代中可用的 k-1 个数据折叠来识别最佳特征和模型超参数。该模型为每个外部循环步骤训练一次,并在保留的数据折叠上进行评估。这个过程产生模型性能的 k 个评估,每个数据折叠一个,并允许在每个样本上测试模型。
要注意的是,这种技术在计算上是昂贵的,因为大量的模型被训练和评估。不幸的是,sklearn 中没有内置的方法可以为您执行嵌套的 k-Fold CV。
可以自己实现,也可以参考这里的实现。
时间序列交叉验证
传统的交叉验证技术不适用于时序数据,因为我们不能选择随机数据点并将它们分配给测试集或训练集,因为使用未来的值来预测过去的值是没有意义的。这主要有两种方法:
- 滚动交叉验证
交叉验证是在滚动的基础上进行的,即从用于训练目的的一小部分数据开始,预测未来值,然后检查预测数据点的准确性。下图可以帮助你获得这种方法背后的直觉。
Rolling cross-validation | Source
- 交叉验证受阻
第一种技术可能会将未来数据泄漏到模型中。该模型将观察未来的模式进行预测,并试图记住它们。这就是引入阻塞交叉验证的原因。
Blocked cross-validation | Source
它的工作原理是在两个位置增加边距。第一个是在训练和验证折叠之间,以防止模型观察到两次使用的滞后值,一次作为回归变量,另一次作为响应。第二个是在每次迭代中使用的折叠之间,以防止模型从一次迭代到下一次迭代记住模式。
机器学习中的交叉验证
什么时候交叉验证是正确的选择?
尽管对你训练过的模型进行交叉验证从来都不是一个坏的选择,在某些情况下,交叉验证是绝对必要的:
- 有限数据集
假设我们有 100 个数据点,我们正在处理一个有 10 个类的多类分类问题,平均每个类有 10 个例子。在 80-20 的训练测试划分中,这个数字甚至会进一步下降到每类 8 个样本用于训练。这里明智的做法是使用交叉验证,并利用我们的整个数据集进行训练和测试。
- 相关数据点
当我们对数据进行随机训练测试分割时,我们假设我们的例子是独立的。这意味着知道一些实例不会帮助我们理解其他实例。然而,情况并不总是这样,在这种情况下,我们的模型熟悉整个数据集是很重要的,这可以进行交叉验证。
- 单一指标的缺点
在没有交叉验证的情况下,我们只能得到一个单一的准确度或精确度值,或者回忆,这可能是一个偶然的结果。当我们训练多个模型时,我们消除了这种可能性,并获得了每个模型的指标,从而产生了强大的洞察力。
- 超参数调谐
虽然有很多方法可以调优你的模型的超参数比如网格搜索,贝叶斯优化等等。这个练习不能在训练集或测试集上完成,因此需要一个验证集。因此,我们退回到上面讨论过的同样的分裂问题,交叉验证可以帮助我们解决这个问题。
深度学习中的交叉验证
深度学习(DL)中的交叉验证可能有点棘手,因为大多数 CV 技术需要至少训练模型几次。
在深度学习中,你通常会试图避免 CV,因为与训练 k 个不同模型相关联的成本。你可以使用训练数据的随机子集作为验证的依据,而不是使用 k-Fold 或其他 CV 技术。
例如, Keras 深度学习库允许你为执行训练的 fit 函数传递两个参数中的一个。
- validation_split :应该等待验证的数据的百分比
- validation_data :应该用于验证的(X,y)元组。该参数覆盖 validation_split 参数,这意味着您一次只能使用其中一个参数。
在 PyTorch 和 MxNet 等其他 DL 框架的官方教程中也使用了同样的方法。他们还建议将数据集分成三部分:训练、验证和测试。
- 训练–数据集的一部分,用于训练
- 验证–训练时要验证的数据集的一部分
- 测试–模型最终验证数据集的一部分
不过,如果数据集很小(包含数百个样本),您可以在 DL 任务中使用交叉验证。在这种情况下,学习一个复杂的模型可能是一个不相关的任务,所以请确保不要使任务进一步复杂化。
最佳实践和技巧
值得一提的是,有时执行交叉验证可能有点棘手。
例如,分割数据集时很容易犯逻辑错误,这可能导致不可信的 CV 结果。
在交叉验证以下模型时,您可能会发现一些需要牢记的提示:
- 拆分数据时要合乎逻辑(拆分方法有意义吗)
- 使用适当的 CV 方法(这种方法对我的用例可行吗)
- 当处理时间序列时,不要验证过去(见第一个提示)
- 当处理医疗或财务数据时,记得按人进行分类。避免一个人的数据同时出现在训练集和测试集中,因为这可能会被认为是数据泄漏
- 当从较大的图像中裁剪补丁时,记得按较大的图像 Id 进行分割
当然,提示因任务而异,几乎不可能涵盖所有的提示。这就是为什么在开始交叉验证模型之前执行可靠的探索性数据分析总是最佳实践。
最后的想法
交叉验证是一个强大的工具。每个数据科学家都应该熟悉它。在现实生活中,如果不交叉验证一个模型,你就无法完成这个项目。
在我看来,最好的 CV 技术是嵌套 k 折和标准 k 折。就我个人而言,我在欺诈检测任务中使用了它们。嵌套的 k-Fold,as 以及 GridSeachCV ,帮助我调整我的模型的参数。另一方面,k 倍用于评估我的模型的性能。
在本文中,我们已经弄清楚了什么是交叉验证,在野外有哪些 CV 技术,以及如何实现它们。在未来,最大似然算法的表现肯定会比现在更好。尽管如此,交叉验证总是需要的,以支持你的结果。
希望有了这些信息,你在为下一个机器学习项目设置简历时不会有任何问题!
资源
- https://www . geeks forgeeks . org/cross-validation-machine-learning/
- https://machinelearningmastery.com/k-fold-cross-validation/
- https://towards data science . com/cross-validation-in-machine-learning-72924 a 69872 f
- https://towards data science . com/why-and-how-do-cross-validation-for-machine-learning-D5 BD 7 e 60 c 189
- https://sci kit-learn . org/stable/modules/cross _ validation . html
7 个交叉验证错误会让你损失惨重[ML 中的最佳实践]
原文:https://web.archive.org/web/https://neptune.ai/blog/cross-validation-mistakes
我们都希望我们的模型能够很好地泛化,以便它们在任何类型的数据集上都保持最佳性能。为了确保这样的需求,我们经常在机器学习项目中依赖交叉验证,这是一种用于评估有限数据样本上的机器学习模型的重采样程序。当你花了这么多时间来调整你的模型,却发现你的交叉验证策略有问题,这可能是一场噩梦。
在本文中,我们将讨论人们在使用交叉验证时最常犯的七个错误,以及如何避免它们。让我们从交叉验证的简单介绍开始。
什么是交叉验证?
它是一种统计方法,用于在机器学习模型投入使用之前评估其性能。它包括以下步骤:
- 首先,我们将数据集分成 k 个折叠。
- k 个折叠中的一个用于测试,而 k-1 个折叠用于模型训练。
- 这个过程重复 k 次,以估计模型的平均性能。
K-fold cross-validation | Source
这种方法产生的性能评估偏差较小。
了解更多信息
要了解更多关于交叉验证的信息,你可以参考这篇文章👉机器学习中的交叉验证:如何正确操作
进行交叉验证时的常见错误
1.随机选择分裂的数量
k-fold 交叉验证的关键配置参数是 k,它定义了数据集将被分割的折叠数。这是使用 k 折叠交叉验证时的第一个困境。我们通常坚持最常用的 k 值,即 5,这在计算上不太昂贵。
没有硬性的规则来决定 k 的值。如果 k 的值太小(如 2 或 3),性能估计器的悲观偏差会很高。如果您增加 k 的值,则所得估计值的偏差和方差将会减少,从而在 k=10 附近给出一个合适的折衷。
但是,在确定 k 的值时,必须确保所选的值对数据集有意义。解决这一问题的一种经过试验和测试的方法是对不同的 k 值进行敏感性分析,即评估具有不同 k 值的模型的性能,并观察它们的表现。
2.总是选择目标分层交叉验证进行分类
在处理分类问题时,我们的自然倾向是总是选择在目标标签上分层的流行的分层 k 折叠。这里假设底层数据包含**独立样本,并且是同分布的。**然而,这并不一定适用于所有情况。让我们借助一个例子来理解这一点:
考虑从多个患者收集的医疗数据,该数据可能包含来自每个患者的多个样本。并且这种数据可能依赖于个体患者组。在这种情况下,我们想知道我们在特定群体上训练的模型是否能在看不见的患者群体上很好地推广。为了实现这一点,我们希望保持训练组和验证组相互排斥,即不在验证数据集中保留任何训练患者组。
组 k 倍是帮助我们处理上述情况的 k 倍的变异。它确保同一组不会出现在训练集、验证集和测试集中。你可以在这里找到 scikit-learn 实现。
GroupKfold cross validation | Source
大部分分类问题都有类别不平衡数据。在这种情况下,您可能希望将 k 组折叠与分层相结合,这里有一个 scikit-learn dev 实现分层 k 组折叠,您可以在这里找到。
Stratified GroupKfold cross validation | Source
在上图中,您可以看到 GroupKfold 和 StatifiedGroupKfold 之间的区别。分层组 k-fold 在尝试返回分层样本时试图保持对组 k-fold 的约束。
3.回归问题中交叉验证技术的选择
为回归问题选择交叉验证方案时,大多数人会选择正态 K 倍,因为目标值是连续的。这将导致训练和验证集随机分裂,且不能确保训练和验证中目标值的相同分布。
为了解决这个常见的错误,我们可以将目标值分成 n 个箱,然后使用这些箱值进行分层 k 折叠。让我们来看看这是如何做到的:
From sklearn.model_selection import StratifiedKFold
def create_folds(df, n_grp, n_s=5):
df['Fold'] = -1
skf = StratifiedKFold(n_splits=n_s)
df['grp'] = pd.cut(df.target, n_grp, labels=False)
target = df.grp
for fold_no, (t, v) in enumerate(skf.split(target, target)):
df.loc[v, 'Fold'] = fold_no
return df
现在,这将确保在您训练和验证中有一个相同的目标分布。这种方法也称为连续目标分层。
4.交叉验证前的过采样
这是我在处理分类问题时进行交叉验证时观察到的一个非常常见的错误。分类任务中的大多数数据集都存在类不平衡问题。解决类不平衡的一种方法是进行过采样,即通过随机将少数类的样本添加到数据集中,以使每个标签的样本数量平衡。
假设您正在处理一个欺诈检测数据集。你发现在这个问题上存在极端的阶级不平衡,你决定首先解决这个问题。为了解决这个问题,你决定进行过采样。在这之后,你选择做交叉验证。现在,通过 k-fold 交叉验证形成的训练和验证数据集将具有许多公共样本,这将导致高估模型性能。因此,避免在交叉验证之前进行过采样。
如果过采样对您的任务至关重要,您应该首先将数据拆分到相应的折叠中,然后在训练和验证循环中继续进行上采样。下面是实现这一点的伪代码:
kfold = KFold(n_splits=n_splits)
scores = []
for train,valid in kfold.split(data):
train_oversampled = oversample_function(train)
score = train_and_validate(train_oversampled,valid)
scores.append(score)
5.知识泄露
这是机器学习中的一个主要问题,在进行交叉验证时也很常见。知识泄漏或数据泄漏是指使用训练集之外的信息来创建模型。这些额外的信息允许模型知道一些它原本不知道的关于数据的额外信息。这导致过于乐观的预测和高估车型性能**。让我们通过一个流行的错误来理解这一点,**
假设您正在处理包含数百个特征的药物分类表格数据。你决定通过主成分分析进行一些特征工程。完成 PCA 后,将前 5 个主成分作为特征添加到数据中。之后,您决定进行交叉验证,并将数据输入 CV 循环。现在你会发现你的简历成绩比预期提高了很多。您对您的模型感到满意,并继续在维持测试集上测试性能。但是出乎你的意料,你的模型表现很差!
这里,您犯了数据泄漏的错误,因为您对整个数据进行了 PCA,而不是分别对训练和验证进行 PCA。一般来说,任何应用于数据的特征工程都应该在 CV 循环内单独进行训练和验证,以避免数据泄漏。
6.时间序列数据的交叉验证
我们知道时间序列数据是不同的。在进行时间序列预测时,我们的目标是建立一个能够根据过去的一些观察结果预测未来的模型。在验证时间序列模型时,应该始终只保留验证/测试集中过期的样本。这是为了确保模型能够很好地概括历史数据。
在对时间序列数据建模时,使用 scikit-learn 中可用的普通 k-fold 方法进行交叉验证是一个常见的错误。这将导致训练和验证数据集的随机分割,无法确保超时条件。因此,在进行时间序列预测时,应该始终使用 scikit-learn 中可用的 时间序列分割 方法来进行交叉验证。
Time series split cross validation | Source
滞后特征被广泛用于时间序列预测时的响应建模,这也可能导致数据泄漏。使用滞后功能时,您可以使用阻塞时间序列分割。下图描述了时间序列分割和分块时间序列分割方法之间的区别。
Blocking time series split cross validation | Source
它的工作原理是在两个位置增加边距。第一个是在训练和验证折叠之间,以防止模型观察到两次使用的滞后值,一次作为回归变量,另一次作为响应。第二个是在每次迭代中使用的折叠之间,以防止模型从一次迭代到下一次迭代记住模式。
7.交叉验证估计中的随机性
几乎所有用于机器学习的算法都受到随机种子值的影响。然而,在像变压器这样的复杂深度神经网络的情况下,随机种子的效果特别高。当用小数据集训练像 BERT 这样的大模型时,这种效果会非常明显。对于这样的模型,您不太可能使用正常的交叉验证来获得模型性能的准确估计。
为了避免在用你坚持的测试数据集测试你的模型时出现任何意外,你应该在多个种子上做交叉验证,并平均模型性能。这将使您能够更好地理解您的模型性能。这是它的伪代码,
SEEDS = [1, 2, 3, 4, 5]
ScoreMetric = []
for seed in SEEDS:
seed_all(seed)
kfold = KFold(n_splits=5, random_state=seed)
scores = []
for train,valid in kfold.split(data):
score = train_and_validate(train,valid)
scores.append(score)
ScoreMetric.append(scores)
Print(f"Average Model Performance {np.mean(ScoreMetric)}")
结论
在本文中,我们讨论了人们在进行交叉验证时会犯的一些常见错误。我们还研究了这些错误的不同解决方案。我希望通过这篇文章,你能够更好地了解交叉验证。
同时,我会敦促你参考更多关于使用不同模型选择和验证技术的实验的研究论文。我附上了一些很好的参考资料,以帮助您开始学习。
参考
沙胡尔 ES
数据科学家,非常熟悉机器学习、NLP 和音频处理领域。他是 Kaggle 大师,也喜欢做开源。
阅读下一篇
如何比较机器学习模型和算法
9 分钟阅读|作者 Samadrita Ghosh |年 9 月 16 日更新
机器学习在过去几年里迅速发展。今天,数据科学家和开发人员不再使用简单的、单向的或线性的 ML 管道,而是运行多个并行实验,即使对于大型团队来说,这些实验也可能变得不堪重负。每个实验都应该以一种不变的、可重复的格式记录下来,这就产生了无穷无尽的日志,其中包含了无价的细节。
我们需要通过将机器学习模型与平行实验进行彻底比较来缩小技术范围。使用计划周密的方法对于理解如何选择算法和手头数据的正确组合是必要的。
因此,在本文中,我们将探讨如何比较 ML 模型和算法。
模型选择的挑战
每个模型或任何机器学习算法都有几个以不同方式处理数据的特征。通常,根据之前的实验阶段,输入这些算法的数据也是不同的。但是,由于机器学习团队和开发人员通常会记录他们的实验,因此有足够的数据可供比较。
挑战在于理解哪些参数、数据和元数据必须被考虑以达到最终的选择。这是一个经典的悖论,有大量的细节却不清晰。
更具挑战性的是,我们需要了解一个具有高值的参数,比如说一个较高的度量分数,是否实际上意味着该模型比一个具有较低分数的模型更好,或者它是否只是由统计偏差或错误的度量设计引起的。
使用机器学习实现客户细分[初学者指南]
原文:https://web.archive.org/web/https://neptune.ai/blog/customer-segmentation-using-machine-learning
如今,你可以个性化一切。没有一刀切的方法。但是,对于企业来说,这其实是一件很棒的事情。它为良性竞争创造了大量空间,也为企业创造了获得和留住客户的创造性机会。
实现更好的个性化的一个基本步骤是客户细分。这是个性化开始的地方,适当的细分将帮助你做出关于新功能、新产品、定价、营销策略,甚至是应用内推荐的决定。
但是,手动进行分段可能会很累人。为什么不使用机器学习来为我们做这件事呢?在本文中,我将告诉你如何做到这一点。
什么是客户细分
客户细分简单来说就是根据各种特征对您的客户进行分组(例如根据年龄对客户进行分组)。
这是组织了解客户的一种方式。了解客户群体之间的差异,就更容易做出关于产品增长和营销的战略决策。
细分市场的机会是无限的,这主要取决于你有多少客户数据可供使用。从基本标准开始,如性别、爱好或年龄,一直到“在网站 X 上花费的时间”或“自用户打开我们的应用程序以来的时间”。
客户细分有不同的方法,它们取决于四种类型的参数:
- 地理,
- 人口统计学,
- 行为上的,
- 心理上。
地理客户细分非常简单,都是关于用户的位置。这可以通过多种方式实现。您可以按国家、州、城市或邮政编码分组。
人口统计细分与客户的结构、规模和在空间和时间上的移动有关。许多公司利用性别差异来创造和营销产品。父母身份是另一个重要特征。你可以从客户调查中获得这样的数据。
行为客户细分基于过去观察到的客户行为,可用于预测未来行动。比如顾客购买的品牌,或者购买最多的瞬间。客户细分的行为方面不仅试图了解购买的原因,还试图了解这些原因在一年中是如何变化的。
顾客的心理细分通常涉及性格特征、态度或信仰。这些数据是通过客户调查获得的,可以用来衡量客户情绪。
客户细分的优势
实施客户细分会带来大量新的商机。您可以在以下方面进行大量优化:
- 预算,
- 产品设计,
- 推广,
- 营销,
- 客户满意度。
让我们更深入地讨论这些好处。
没有人喜欢投资那些不能产生新客户的活动。大多数公司都没有庞大的营销预算,所以钱必须花在正确的地方。细分使您能够首先锁定具有最高潜在价值的客户,因此您可以从营销预算中获得最大收益。
客户细分有助于你了解你的用户需要什么。您可以识别最活跃的用户/客户,并根据他们的需求优化您的应用/产品。
正确实施的客户细分有助于您规划特别优惠和交易。在过去的几年里,频繁的交易已经成为电子商务和商业软件的主要内容。如果你在正确的时间给客户提供了正确的报价,他们就有很大的机会购买。客户细分将帮助您完美定制您的特别优惠。
通过细分可以直接改善营销策略,因为您可以利用客户最常用的渠道为不同的客户群规划个性化的营销活动。
通过研究不同的客户群体,你可以了解他们最看重你公司的什么。这些信息将帮助您创建完全符合客户偏好的个性化产品和服务。
在下一部分,我们将讨论机器学习为什么用于客户细分。
面向客户细分的机器学习
机器学习方法是分析客户数据和发现洞察力和模式的伟大工具。人工智能模型是决策者的有力工具。他们可以精确地识别客户群,这是手工或传统分析方法难以做到的。
机器学习算法有很多种,每一种都适合特定类型的问题。适用于客户细分问题的一种非常常见的机器学习算法是 k 均值聚类算法。还有其他聚类算法,如 DBSCAN、凝聚聚类和 BIRCH 等。
为什么要为客户细分实现机器学习?
更多的时间
手动客户细分非常耗时。手动分析成堆的数据并找到模式需要几个月甚至几年的时间。此外,如果启发式地完成,它可能没有预期的有用的准确性。
客户细分过去是手动完成的,并且不太精确。您需要手动创建和填充不同的数据表,并像侦探戴着镜子一样分析数据。现在,仅仅使用机器学习要好得多(并且由于 ML 的快速发展而相对容易),这可以腾出你的时间来专注于需要创造力来解决的更高要求的问题。
易于再培训
客户细分不是一个“开发一次,永远使用”的项目。数据是不断变化的,趋势是振荡的,在您的模型部署后,一切都在不断变化。通常,更多的标记数据在开发后变得可用,这对于提高模型的整体性能是一个很好的资源。
有许多方法可以更新客户细分模型,但这里有两种主要方法:
- 以旧模式为起点,重新训练。
- 保留现有模型,并将其输出与新模型相结合。
更好的缩放
由于云基础设施,在生产中部署的机器学习模型支持可扩展性。这些模型对于未来的变化和反馈非常灵活。例如,假设一家公司今天有 10000 名客户,他们实施了一个客户细分模型。一年后,如果公司有 100 万客户,那么理想情况下,我们不需要创建一个单独的项目来处理这些增加的数据。机器学习模型具有处理更多数据和生产规模的内在能力。
更高的精度
对于给定的客户数据,使用机器学习方法(如 elbow 方法)很容易找到最佳聚类数的值。当我们使用机器学习时,不仅最优的聚类数,而且模型的性能也要好得多。
探索客户数据集及其特征
让我们分析一个客户数据集。我们的数据集有 24,000 个数据点和四个特征。其特点是:
- 客户 ID–这是特定企业的客户 ID。
- 购买的产品–该功能表示客户一年中购买的产品数量。
- 投诉–该列值表示客户去年提出的投诉数量
- 支出金额–该列值表示客户去年支付的金额。
在接下来的部分,我们将预处理这个数据集。
预处理数据集
在将数据输入 k-means 聚类算法之前,我们需要预处理数据集。让我们为客户数据集实现必要的预处理。
接下来,我们将用 Python 实现 k-means 聚类算法。
在 Python 中实现 K-means 聚类
K-Means 聚类是解决数据聚类问题的一种有效的机器学习算法。这是一种非监督算法,非常适合解决客户细分问题。在我们继续之前,让我们快速探索两个关键概念
无监督学习
无监督机器学习与有监督机器学习截然不同。这是一种特殊的机器学习算法,可以从未标记的数据中发现数据集中的模式。
无监督的机器学习算法可以根据数据集中的相似属性对数据点进行分组。无监督模型的主要类型之一是聚类模型。
注意,监督学习帮助我们从先前的经验中产生一个输出。
聚类算法
聚类机器学习算法是一种无监督的机器学习算法。它用于发现数据集中的自然分组或模式。值得注意的是,聚类算法只是解释输入数据,并在其中找到自然的聚类。
一些最流行的聚类算法有:
- k 均值聚类
- 凝聚层次聚类
- 期望最大化聚类
- 基于密度的空间聚类
- 均值漂移聚类
在下一节中,我们将使用 k-means 聚类算法和机器学习来分析客户细分问题。但是,在此之前,让我们快速讨论一下为什么使用 k-means 聚类算法。
为什么使用 K-means 聚类进行客户细分?
与监督学习算法不同,K-means 聚类是一种非监督机器学习算法。当我们有未标记的数据时,使用这种算法。未标记数据是指没有提供类别或组的输入数据。我们的客户细分数据对于这个问题是这样的。
该算法发现数据中的组(聚类),其中聚类的数量由 K 值表示。根据所提供的特征,该算法迭代地将每个输入数据分配给 K 个聚类之一。所有这些使得 k-means 非常适合客户细分问题。
给定一组数据点,根据特征相似性进行分组。K 均值聚类算法的输出是:
- K 个簇的质心值,
- 每个输入数据点的标签。
在实施结束时,我们将获得输出,例如一组群集以及哪个客户属于哪个群集。
首先,我们需要实现所需的 Python 库,如下表所示。
import pandas as pd
import numpy as np
from sklearn.cluster import KMeans
import plotly.express as px
import plotly.graph_objects as go
import matplotlib.pyplot as plt
我们已经导入了 pandas、NumPy sklearn、plotly 和 matplotlib 库。Pandas 和 NumPy 用于数据争论和操作,sklearn 用于建模,plotly 和 matplotlib 将用于绘制图形和图像。
导入库之后,我们的下一步是加载 pandas 数据框中的数据。为此,我们将使用熊猫的 read_csv 方法。
customersdata = pd.read_csv("customers-data.csv")
加载数据后,我们需要定义 K 均值模型。这是在我们从 sklearn 导入的 KMeans 类的帮助下完成的,如下面的代码所示。
kmeans_model = KMeans(init='k-means++', max_iter=400, random_state=42)
定义模型后,我们要使用训练数据集进行训练。这是通过使用 fit 方法实现的,如下面的代码所示。
kmeans_model.fit(customersdata[['products_purchased','complains',
'money_spent']])
注意,我们将三个特性传递给 fit 方法,即 products_purchased、complains 和 money _ spent。
尽管我们已经训练了一个 K-means 模型达到这些点,但我们还没有找到在这种客户细分情况下所需的最佳聚类数。对于给定的数据集,找到最佳的聚类数目对于产生高性能的 k-means 聚类模型是重要的。
在接下来的部分中,我们将找到给定数据集的最佳聚类数,然后使用这些最佳 k 值重新训练 k-means 聚类模型。这将生成我们的最终模型。
寻找最佳的聚类数
实现 k-means 聚类算法的关键任务之一是找到最佳的聚类数。值得注意的是,K 均值聚类模型可能会收敛于任何 K 值,但同时,并不是所有的 K 值都会产生最佳模型。
对于某些数据集,数据可视化有助于了解最佳聚类数,但这并不适用于所有数据集。我们有一些方法,如肘方法、间隙统计法和平均轮廓法,来评估给定数据集的最佳聚类数。我们将逐一讨论它们。
- 肘方法使用总的组内平方和值来寻找最佳组数的值。这代表了所生成的集群彼此之间的分散程度。在这种情况下,K-means 算法针对 K 的几个值进行评估,并针对 K 的每个值计算类内平方和。之后,我们绘制 K 与平方和的关系图。在分析该图之后,选择聚类的数量,以便添加新的聚类不会显著改变平方和的值。
- 平均轮廓法是一种衡量每个数据点与其对应聚类拟合程度的方法。该方法评估聚类的质量。作为一般规则,高平均轮廓宽度表示更好的聚类输出。
- 缺口统计方法是对缺口统计值的衡量。间隙统计是不同 k 值的总簇内变化与其预期值之间的差异。该计算使用数据点的零参考分布来完成。最佳聚类数是使间隙统计值最大化的值。
我们将使用肘法。K-means 聚类算法通过将给定的数据点分成 K 组等方差来对数据进行聚类。这有效地最小化了一个叫做惯性的参数。在这种情况下,惯性只不过是群内距离的平方和。
当我们使用肘方法时,我们从 2 开始逐渐增加簇的数量,直到达到添加更多簇不会导致惯性值显著下降的簇的数量。
达到这个分类数的阶段称为分类模型的肘部。我们会看到在我们的例子中 K =5。
为了实现肘方法,首先创建名为“try_different_clusters”的函数。它接受两个值作为输入:
- k(簇的数量),
- 数据(输入数据)。
def try_different_clusters(K, data):
cluster_values = list(range(1, K+1))
inertias=[]
for c in cluster_values:
model = KMeans(n_clusters = c,init='k-means++',max_iter=400,random_state=42)
model.fit(data)
inertias.append(model.inertia_)
return inertias
下面的代码调用了 try_different_clusters 方法,其中我们将 K 的值从 1 传递到 12,并计算 K 的每个值的惯性。
outputs = try_different_clusters(12, customersdata[['products_purchased','complains','money_spent']])
distances = pd.DataFrame({"clusters": list(range(1, 13)),"sum of squared distances": outputs})
使用下面的代码,我们绘制了 K 值(在 x 轴上)相对于 Y 轴上相应的惯性值。
figure = go.Figure()
figure.add_trace(go.Scatter(x=distances["clusters"], y=distances["sum of squared distances"]))
figure.update_layout(xaxis = dict(tick0 = 1,dtick = 1,tickmode = 'linear'),
xaxis_title="Number of clusters",
yaxis_title="Sum of squared distances",
title_text="Finding optimal number of clusters using elbow method")
figure.show()
我们可以使用上面的代码生成下图。代码的拐点在 K=5 处。我们已经选择了 5,如果我们将集群的数量增加到 5 个以上,那么惯性或平方距离的和会有非常小的变化。
K = 5 的最佳值
聚类数达到最佳值的阶段称为聚类模型的拐点。例如,在下图中,肘部位于五个簇处(K =5)。添加 5 个以上的集群将导致创建效率低下或性能较差的集群模型。
如前所述,我们需要使用找到的最佳聚类数再次训练 k-means 聚类模型。
kmeans_model_new = KMeans(n_clusters = 5,init='k-means++',max_iter=400,random_state=42)
kmeans_model_new.fit_predict(customersdata[['products_purchased','complains','money_spent']])
请注意,我们使用 fit_predict 方法来训练模型。
在下一节中,我们将讨论如何在三维空间中可视化客户细分群。
可视化客户群
在本节中,我们将使用 plotly express 实现一些代码。通过这种方式,我们可以用 k-means 算法在三维空间中可视化聚类。Plotly express 是一个基于 Plotly 的库,可处理多种类型的数据集并生成高度风格化的绘图。
首先,让我们向现有的客户数据集中添加一个名为“clusters”的新列。该列将能够表明哪个客户属于哪个集群。
cluster_centers = kmeans_model_new.cluster_centers_
data = np.expm1(cluster_centers)
points = np.append(data, cluster_centers, axis=1)
points
注意,我们在这里使用 NumPy expm1 方法。NumPy expm1 函数为 NumPy 数组中的每个元素返回负一的指数值作为输出。因此,np.expm1 方法接受 arr_name 和 out 参数,然后将数组作为输出返回。
points = np.append(points, [[0], [1], [2], [3], [4]], axis=1)
customersdata["clusters"] = kmeans_model_new.labels_
添加名为 clusters 的新列后,客户数据数据集将如下所示。
最后,我们将使用下面的代码来可视化所创建的五个集群。这是使用 plotly 和 express 库完成的。
Plotly 是一个 Python 库,用于绘图、统计、绘图和分析。这可以与 Python、R、Julia 和其他编程语言一起使用。Plotly 是一个免费的开源库。
想要组织你的实验过程吗?检查如何将交互式 Plotly 图表存储在与模型元数据(指标、参数、权重等)相同的位置。
Plotly Express 是 Plotly 上的一个高级接口,可用于多种类型的数据集并生成高度风格化的图。
plotly.express 类具有可以一次性生成完整数字的函数。一般来说,它被称为 px。值得注意的是 plotly express 是 plotly 库的内置模块。这是创建推荐的最常见地块的起点。注意,每个 plotly express 函数在内部创建图形对象,并返回 plotly.graph_objects。
使用 plotly express 通过单一方法调用创建的图形也可以仅使用图形对象创建。然而,在这种情况下,它需要大约 5 到 100 倍的代码。
与 2D 散点图一样,px.scatter 在二维空间中绘制单个数据,而 3D 方法 px.scatter_3d 在三维空间中绘制单个数据。
figure = px.scatter_3d(customersdata,
color='clusters',
x="products_purchased",
y="complains",
z="money_spent",
category_orders = {"clusters": ["0", "1", "2", "3", "4"]}
)
figure.update_layout()
figure.show()
数据点聚类的可视化非常重要。图表的不同边缘提供了复杂输入数据集的快速视图。
结论
用相同的产品型号、电子邮件、短信活动或广告来服务所有客户是不明智的。客户有不同的需求。一刀切的商业模式通常会导致更少的参与,更低的点击率,最终更少的销售。客户细分是解决这个问题的方法。
找到最佳数量的独特客户群将有助于您了解您的客户有何不同,并帮助您准确满足他们的需求。客户细分改善了客户体验,增加了公司收入。这就是为什么如果你想超越你的竞争对手,获得更多的客户,细分是必须的。用机器学习来做肯定是正确的方向。
如果你做到了这一步,感谢你的阅读!
Python 中的数据扩充:您需要知道的一切
原文:https://web.archive.org/web/https://neptune.ai/blog/data-augmentation-in-python
在机器学习( ML )中,模型没有很好地从训练数据泛化到看不见的数据的情况被称为过拟合。你可能知道,这是应用机器学习中最棘手的障碍之一。
解决这个问题的第一步是真正知道你的模型过度拟合*。* 这就是正确的交叉验证的用武之地。
识别问题后,您可以通过应用正则化或使用更多数据进行训练来防止问题发生。尽管如此,有时您可能没有额外的数据添加到您的初始数据集。获取和标记额外的数据点也可能是错误的途径。当然,在很多情况下,会有更好的效果,但在工作方面,往往费时费钱。
这就是 数据增强 ( DA )的用武之地。
在本文中,我们将涵盖:
什么是数据增强?
数据扩充是一种技术,可用于通过从现有数据创建修改后的数据来人为扩大训练集的规模。如果您想要防止过度拟合,或者初始数据集太小而无法训练,或者甚至您想要从您的模型中获得更好的性能,那么使用 DA 是一个很好的实践。
让我们明确一点,数据扩充不仅仅是用来防止过拟合。一般来说,拥有大型数据集对于 ML 和深度学习 ( DL )模型的性能都至关重要。然而,我们可以通过增加现有的数据来提高模型的性能。这意味着数据扩充也有利于增强模型的性能。
一般情况下,在建立 DL 模型时,经常使用 DA 。这就是为什么在整篇文章中,我们将主要讨论用各种 DL 框架来执行数据扩充。不过,你应该记住,你也可以为 ML 问题扩充数据。
您可以增加:
- 声音的
- 文本
- 形象
- 任何其他类型的数据
我们将重点放在图像增强,因为这些是最受欢迎的。尽管如此,增加其他类型的数据也同样有效和容易。这就是为什么最好记住一些可以用来扩充数据的常用技术。
数据扩充技术
我们可以对原始数据进行各种修改。例如,对于图像,我们可以使用:
- 几何变换–你可以随意翻转、裁剪、旋转或平移图像,而这只是冰山一角
- 颜色空间转换–改变 RGB 颜色通道,增强任何颜色
- 内核过滤器–锐化或模糊图像
- 随机擦除–删除初始图像的一部分
- 混合图像–基本上,将图像彼此混合。可能违反直觉,但它确实有效
对于文本,有:
- 单词/句子混排
- 单词替换–用同义词替换单词
- 语法树操作–使用相同的单词解释句子,使其语法正确
- 关于 NLP 中的数据增强的其他描述
对于音频增强,您可以使用:
- 噪声注入
- 换挡
- 改变磁带的速度
- 还有更多
此外,增强技术的最大优势是你可以一次使用所有这些技术。因此,您可能会从最初的样本中获得大量独特的数据样本。
深度学习中的数据增强
上面提到的 深度学习, 数据增强 是常见的做法。因此,每个 DL 框架都有自己的增强方法,甚至是一个完整的库。例如,让我们看看如何使用 TensorFlow (TF)和 Keras、PyTorch 和 MxNet 中的内置方法来应用图像增强。
TensorFlow 和 Keras 中的数据扩充
当使用 TensorFlow 或 Keras 作为我们的 DL 框架时,我们可以:
- 使用 tf.image 编写我们自己的增强管道或层。
- 使用 Keras 预处理层
- 使用图像数据生成器
Tf .图像
让我们更仔细地看看第一种技术,定义一个可视化图像的函数,然后使用 tf.image 将翻转应用于该图像。您可以在下面看到代码和结果。
def visualize(original, augmented):
fig = plt.figure()
plt.subplot(1,2,1)
plt.title('Original image')
plt.imshow(original)
plt.subplot(1,2,2)
plt.title('Augmented image')
plt.imshow(augmented)
flipped = tf.image.flip_left_right(image)
visualize(image, flipped)
为了更好的控制,你可以写你自己的增强管道。在大多数情况下,对整个数据集而不是单个图像应用增强是有用的。您可以如下实现它。
import tensorflow_datasets as tfds
def augment(image, label):
image = tf.cast(image, tf.float32)
image = tf.image.resize(image, [IMG_SIZE, IMG_SIZE])
image = (image / 255.0)
image = tf.image.random_crop(image, size=[IMG_SIZE, IMG_SIZE, 3])
image = tf.image.random_brightness(image, max_delta=0.5)
return image, label
(train_ds, val_ds, test_ds), metadata = tfds.load(
'tf_flowers',
split=['train[:80%]', 'train[80%:90%]', 'train[90%:]'],
with_info=True,
as_supervised=True,)
train_ds = train_ds
.shuffle(1000)
.map(augment, num_parallel_calls=tf.data.experimental.AUTOTUNE)
.batch(batch_size)
.prefetch(AUTOTUNE)
当然,这只是冰山一角。 TensorFlow API 有大量的增强技术。如果你想了解更多关于这个话题的内容,请查看官方文件或其他文章。
Keras 预处理
如上所述, Keras 有多种预处理层,可用于数据扩充。您可以按如下方式应用它们。
data_augmentation = tf.keras.Sequential([
layers.experimental.preprocessing.RandomFlip("horizontal_and_vertical"),
layers.experimental.preprocessing.RandomRotation(0.2)])
image = tf.expand_dims(image, 0)
plt.figure(figsize=(10, 10))
for i in range(9):
augmented_image = data_augmentation(image)
ax = plt.subplot(3, 3, i + 1)
plt.imshow(augmented_image[0])
plt.axis("off")
Keras ImageDataGenerator
此外,您可以使用imagedata generator(TF . keras . preprocessing . image . image data generator),它可以使用实时 DA 生成批量张量图像。
datagen = ImageDataGenerator(rotation_range=90)
datagen.fit(x_train)
for X_batch, y_batch in datagen.flow(x_train, y_train, batch_size=9):
for i in range(0, 9):
pyplot.subplot(330 + 1 + i)
pyplot.imshow(X_batch[i].reshape(img_rows, img_cols, 3))
pyplot.show()
break
PyTorch 和 MxNet 中的数据扩充
Pytorch 中的变换
Transforms library 是 torchvision 包的增强部分,该包由流行的数据集、模型架构和用于计算机视觉任务的常见图像转换组成。
要安装转换你只需要安装火炬视觉:
pip3 install torch torchvision
转换库包含不同的图像转换,可以使用合成方法将它们链接在一起。在功能上, Transforms 实现了多种增强技术。你可以通过使用 Compose 方法来组合它们。只需查看官方文档就能找到任务的增强功能。
此外,还有torch vision . transforms . functional模块。它有各种功能转换,可以对转换进行细粒度的控制。如果您正在构建一个更复杂的增强管道,例如,在分段任务的情况下,这可能会非常有用。
除此之外,变换并没有什么独特的特性。它主要与 PyTorch 一起使用,因为它被认为是一个内置的增强库。
更多关于 PYTORCH 闪电
py torch 变换的示例用法
让我们看看如何使用变换来应用增强。你应该记住,变换只适用于 PIL 的图像。这就是为什么你要么阅读 PIL 格式的图像,要么对你的增强管道进行必要的转换。
from torchvision import transforms as tr
from torchvision.transfroms import Compose
pipeline = Compose(
[tr.RandomRotation(degrees = 90),
tr.RandomRotation(degrees = 270)])
augmented_image = pipeline(img = img)
有时你可能想为训练编写一个定制的数据加载器。让我们看看如何通过变换来应用增强,如果你这样做的话。
from torchvision import transforms
from torchvision.transforms import Compose as C
def aug(p=0.5):
return C([transforms.RandomHorizontalFlip()], p=p)
class Dataloader(object):
def __init__(self, train, csv, transform=None):
...
def __getitem__(self, index):
...
img = aug()(**{'image': img})['image']
return img, target
def __len__(self):
return len(self.image_list)
trainset = Dataloader(train=True, csv='/path/to/file/', transform=aug)
MxNet 中的转换
Mxnet 还有一个内置的增强库叫做Transforms(Mxnet . gluon . data . vision . Transforms)。它非常类似于 PyTorch 转换库。几乎没有什么可补充的。如果您想找到关于这个主题的更多信息,请查看上面的转换部分。一般用法如下。
MxNet 转换的示例用法
color_aug = transforms.RandomColorJitter(
brightness=0.5,
contrast=0.5,
saturation=0.5,
hue=0.5)
apply(example_image, color_aug)
这些都是很好的例子,但是从我的经验来看,当您使用定制库时,数据扩充的真正威力就会显现出来:
- 他们有更广泛的转换方法
- 它们允许您创建自定义增强
- 您可以将一个转换与另一个堆叠在一起。
这就是为什么使用定制的 DA 库可能比使用内置库更有效。
图像数据增强库
在本节中,我们将讨论以下库:
- 奥吉
- 白蛋白
- 伊姆高格
- 自动增强(DeepAugment)
我们将查看安装、增强功能、增强过程并行化、自定义增强,并提供一个简单的示例。请记住,我们将侧重于图像增强,因为它是最常用的。
在我们开始之前,我有一些关于在不同的 DL 框架中使用定制增强库的一般说明。
一般来说,如果您在训练模型之前执行扩充,所有的库都可以用于所有的框架。
重点是有些库和特定框架有预存的协同,比如albuminations和 Pytorch 。用这样的对子更方便。不过,如果您需要特定的函数或者您喜欢一个库胜过另一个库,您应该在开始训练模型之前执行 DA ,或者编写一个定制的数据加载器和训练过程。
第二个主题是在不同的增强库中使用定制的增强。例如,您想使用自己的 CV2 图像转换,并从albuminations库中进行特定的增强。
让我们弄清楚这一点,你可以对任何库这样做,但它可能比你想象的更复杂。一些图书馆在他们的官方文档中有如何做的指南,但是其他的没有。
如果没有向导,你基本上有两种方法:
- 分别应用增强,例如,使用转换操作,然后使用管道。
- 检查一下 Github 仓库,以防有人已经想出如何正确地将定制增强集成到管道中。
好了,现在我们开始吧。
奥吉先生
继续谈库, Augmentor 是一个 Python 包,它的目标是既是一个数据扩充工具,又是一个基本图像预处理函数库。
通过 pip 安装增强器非常容易:
pip install Augmentor
如果你想从源代码编译这个包,请查阅官方文档。
一般来说,增强器由许多标准图像变换函数的类组成,比如裁剪、旋转、翻转等等。
增强器允许用户为每个变换操作选择一个概率参数。此参数控制操作的应用频率。因此,增强器允许形成一个增强管道,将大量随机应用的操作链接在一起。
这意味着每次图像通过管道时,都会返回完全不同的图像。根据流水线中的操作数量和概率参数,可以创建非常大量的新图像数据。基本上,这是最好的数据扩充。
使用增强器我们可以对图像做什么?增强器更侧重于几何变换虽然它也有其他增强。增强器组件的主要特点是:
- 透视倾斜–从不同的角度观看图像
- 弹性变形–给图像添加变形
- 旋转–简单地说,旋转图像
- 剪切–沿着图像的一边倾斜图像
- 裁剪–裁剪图像
- 镜像–应用不同类型的翻转
Augmentor 是一个组织严密的库。您可以将它与各种 DL 框架( TF、Keras、PyTorch、MxNet )一起使用,因为增强甚至可以在您建立模型之前应用。
此外,增强器允许您添加自定义增强。这可能有点棘手,因为它需要编写一个新的操作类,但是你可以做到。
不幸的是,Augmentor在功能上既不非常快也不灵活。有一些库提供了更多的转换函数,可以更快更有效地执行 DA 。这就是为什么增强器可能是最不受欢迎的 DA 库。
增强器使用示例
让我们检查一下增强器的简单用法:
- 我们需要导入它。
- 我们创建一个空的扩充管道。
- 在那里添加一些操作
- 使用采样方法获得增强图像。
请注意,当使用样本时,您需要指定您想要获得的增强图像的数量。
import Augmentor
p = Augmentor.Pipeline("/path/to/images")
p.rotate(probability=0.7, max_left_rotation=10, max_right_rotation=10)
p.zoom(probability=0.3, min_factor=1.1, max_factor=1.6)
p.sample(10000)
白蛋白
albuminations是一款计算机视觉工具,旨在执行快速灵活的图像放大。它似乎拥有所有图像增强库中最大的转换函数集。
让我们通过 pip 安装相册。如果你想以其他方式做这件事,检查官方文件。
pip install albumentations
albuminations提供了一个简单的界面来处理不同的计算机视觉任务,如分类、分割、对象检测、姿态估计等。该库为最大速度和性能进行了优化,拥有大量不同的图像转换操作。
如果我们谈论的是数据扩充,那么没有什么是白蛋白不能做的。说实话,albuminations是堆栈最多的库,因为它没有专注于图像转换的某个特定领域。你可以简单地检查官方文档,你会找到一个你需要的操作。
而且,albuminations与深度学习框架如 PyTorch 和 Keras 无缝集成。这个库是 PyTorch 生态系统的一部分,但是你也可以和 TensorFlow 一起使用。因此,albuminations是最常用的图像增强库。
另一方面,albuminations没有与 MxNet 集成,这意味着如果你使用 MxNet 作为 DL 框架,你应该编写一个定制的数据加载器或者使用另一个增强库。
值得一提的是albuminations是一个开源库。如果你愿意,你可以很容易地检查原始的代码。
白蛋白使用示例
让我们看看如何使用相册来放大图像。您需要使用 Compose 方法定义管道(或者您可以使用单个增强),向其传递一个图像,并获得增强的图像。
import albumentations as A
import cv2
def visualize(image):
plt.figure(figsize=(10, 10))
plt.axis('off')
plt.imshow(image)
image = cv2.imread('/path/to/image')
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
transform = A.Compose(
[A.CLAHE(),
A.RandomRotate90(),
A.Transpose(),
A.ShiftScaleRotate(shift_limit=0.0625, scale_limit=0.50,
rotate_limit=45, p=.75),
A.Blur(blur_limit=3),
A.OpticalDistortion(),
A.GridDistortion(),
A.HueSaturationValue()])
augmented_image = transform(image=image)['image']
visualize(augmented_image)
伊姆高格
现在,在阅读了增强器和相册之后,你可能会认为所有的图像增强库彼此都非常相似。
没错。在许多情况下,每个库的功能是可以互换的。然而,每一个都有自己的主要特点。
ImgAug 也是一个图像增强库。它在功能上与增强器和缓冲区非常相似,但是官方文档中提到的主要特性是 T4 在多个 CPU 内核上执行增强的能力。如果你想这样做,你可能想检查下面的指南。
正如你所看到的,这与增强师专注于几何变换或 融合 试图覆盖所有可能的增强截然不同。
然而, ImgAug 的关键特性似乎有点奇怪,因为增强器和缓冲也可以在多个 CPU 内核上执行。总之 ImgAug 支持广泛的增强技术,就像白蛋白一样,并通过细粒度控制实现复杂的增强。
ImgAug 可通过 pip 或 conda 轻松安装。
pip install imgaug
img aug 的使用示例
与其他图像增强库 , ImgAug 一样,使用起来也很方便。要定义一个扩充管道,使用顺序方法,然后像在其他库中一样简单地堆叠不同的转换操作。
from imgaug import augmenters as iaa
seq = iaa.Sequential([
iaa.Crop(px=(0, 16)),
iaa.Fliplr(0.5),
iaa.GaussianBlur(sigma=(0, 3.0))])
for batch_idx in range(1000):
images = load_batch(batch_idx)
images_aug = seq(images=images)
自动增强
另一方面,自动增强更有趣。你可能知道,用机器学习 ( ML )来提高 ML 的设计选择,已经到了 DA 的空间。
2018 年,谷歌推出了自动增强算法,该算法是设计的,用于搜索最佳增强策略。自动增强帮助提高了最先进的模型在数据集上的性能,如 CIFAR-10、CIFAR-100、ImageNet 等。
然而, AutoAugment 使用起来很棘手,因为它没有提供控制器模块,这阻止了用户为自己的数据集运行它。这就是为什么只有当我们计划训练的数据集和我们要完成的任务已经有了增强策略时,使用自动增强才是有意义的。
因此,让我们更仔细地看看 DeepAugment ,它比自动增强更快、更灵活。 DeepAugment 与 AutoAugment 除了一般的想法之外没有什么强有力的联系,是由一群爱好者开发的。您可以通过 pip 安装它:
pip install deepaugment
知道如何使用 DeepAugment 为我们的图像获得最佳的增强策略对我们来说很重要。你可以按照下面的方法来做,或者查看官方的 Github 库。
请记住,当您使用优化方法时,您应该指定用于找到最佳增强策略的样本数量。
from deepaugment.deepaugment import DeepAugment
deepaug = DeepAugment(my_images, my_labels)
best_policies = deepaug.optimize(300)
总的来说,自动增强和深度增强都不常用。不过,如果您不知道哪种增强技术最适合您的数据,运行它们可能会非常有用。你只需要记住,这需要大量的时间,因为要训练多个模型。
值得一提的是,我们没有涵盖所有的自定义图像增强库,但我们已经涵盖了主要的。现在你知道什么库最受欢迎,它们有什么优点和缺点,以及如何使用它们。如果您需要,这些知识将帮助您找到任何其他信息。
图像数据增强库的速度比较
您可能已经发现,增强过程在时间和计算上都非常昂贵。
执行 DA 所需的时间取决于我们需要转换的数据点的数量、整个扩充流水线的难度,甚至取决于您用来扩充数据的硬件。
让我们进行一些实验,找出最快的增强库。我们将对增强器、白蛋白、 ImgAug 和转化进行这些实验。我们将使用来自 Kaggle 的一个图像数据集,它是为花朵识别而设计的,包含超过 4000 张图像。
在我们的第一个实验中,我们将创建一个只包含两个操作的扩充管道。这将是概率为 0.4 的水平翻转和概率为 0.8 的垂直翻转。让我们将管道应用于数据集中的每个图像,并测量时间。
正如我们所预料的, Augmentor 的执行速度比其他库慢。尽管如此,albumation 和 Transforms 都显示出良好的结果,因为它们被优化来执行快速增强。
对于我们的第二个实验,我们将创建一个更复杂的管道,使用各种转换到**,看看转换和缓冲是否停留在顶部**。我们将更多的几何变换堆叠成一个流水线。因此,我们将能够使用所有库作为增强器,例如,没有太多的内核过滤操作。
你可以在我为你准备的笔记本中找到完整的流程。请随意试验和使用它。
再一次变换和贴图位于顶部。
此外,如果我们检查通过 Neptune 获得的 CPU 使用图表,我们会发现缓冲和转换使用的 CPU 资源都不到 60%。
另一方面,增强器和 ImgAug 使用超过 80%。
你可能已经注意到了,转存和转换都非常快。这就是它们在现实生活中被广泛使用的原因。
最佳实践、提示和技巧
值得一提的是,尽管 DA 是一个强大的工具,但你应该小心使用它。在应用增强时,您可能需要遵循一些通用规则:
为你的任务选择适当的扩充。让我们想象一下,你正试图检测一张图像上的一张脸。你选择随机删除作为增强技术,突然你的模型甚至在训练中表现也不好。这是因为图像上没有人脸,因为它是通过增强技术随机擦除的。同样的事情也适用于声音检测和应用噪声注入到磁带作为一个增强。记住这些案例,在选择 DA 技术时要合乎逻辑。
不要在一个序列中使用太多的增强。你可能会简单地创建一个全新的观察,与你最初的训练(或测试数据)毫无共同之处
在笔记本中显示增强数据(图像和文本),并在开始训练之前聆听转换后的音频样本。当形成一个扩充管道时,很容易出错。这就是为什么复查结果总是更好的原因。
此外,在创建自己的扩充管道之前,检查一下笔记本也是一个很好的做法。你可以在那里找到很多想法。试着为类似的任务找一个笔记本,检查作者是否应用了和你计划的一样的扩充。
最后的想法
在本文中,我们已经弄清楚了什么是数据扩充,有哪些 DA 技术,以及您可以使用哪些库来应用它们。
据我所知,最好的公共图书馆是图书室。这就是为什么如果你正在处理图像并且不使用 MxNet 或 TensorFlow 作为你的 DL 框架,你可能应该使用albuminations作为 DA 。
希望有了这些信息,你在为下一个机器学习项目设置 DA 时不会有任何问题。
资源
弗拉基米尔·利亚申科
年轻的人工智能爱好者,对医学中的教育技术和计算机视觉充满热情。我想通过帮助其他人学习,探索新的机会,并通过先进的技术跟踪他们的健康状况,让世界变得更美好。
阅读下一篇
机器学习中模型评估和选择的最终指南
10 分钟阅读|作者 Samadrita Ghosh |年 7 月 16 日更新
在高层次上,机器学习是统计和计算的结合。机器学习的关键围绕着算法或模型的概念,这些概念实际上是类固醇的统计估计。
然而,根据数据分布的不同,任何给定的模型都有一些限制。它们中没有一个是完全准确的,因为它们只是 (即使使用类固醇) 。这些限制俗称 偏差 和 方差 。
具有高偏差的模型会由于不太注意训练点而过于简化(例如:在线性回归中,不管数据分布如何,模型将总是假设线性关系)。
具有高方差的模型将通过不对其之前未见过的测试点进行概括来将其自身限制于训练数据(例如:max_depth = None 的随机森林)。
当限制很微妙时,问题就出现了,比如当我们必须在随机森林算法和梯度推进算法之间进行选择,或者在同一决策树算法的两个变体之间进行选择。两者都趋向于具有高方差和低偏差。
这就是模型选择和模型评估发挥作用的地方!
在本文中,我们将讨论:
- 什么是模型选择和模型评估?
- 有效的模型选择方法(重采样和概率方法)
- 流行的模型评估方法
- 重要的机器学习模型权衡
NLP 中的数据扩充:来自 Kaggle Master 的最佳实践
原文:https://web.archive.org/web/https://neptune.ai/blog/data-augmentation-nlp
NLP 中有许多任务,从文本分类到问题回答,但是无论您做什么,您必须训练模型的数据量都会严重影响模型的性能。
你能做些什么来扩大你的数据集?
简单的选项->获取更多数据:)。
但是获取和标记额外的观察值可能是一个昂贵且耗时的过程。
你能做些什么呢?
对文本数据应用数据扩充。
数据扩充技术用于**使用您已有的数据生成额外的合成数据。**增强方法在计算机视觉应用中非常流行,但它们对自然语言处理同样有效。
在本文中,我们将介绍 NLP 的所有主要数据扩充方法,您可以使用这些方法来增加文本数据集的大小并提高模型性能。
视觉与自然语言处理的数据增强
在计算机视觉应用中,数据扩充几乎无处不在,以获得更大的训练数据,并使模型更好地泛化。
使用的主要方法包括:
- 裁剪,
- 翻转,
- 缩放,
- 旋转,
- 噪声注入,
- 和许多其他人。
在计算机视觉中,这些转换是使用数据生成器在移动中完成的**。当一批数据被输入你的神经网络时,它会被随机转换(增强)。训练前不需要准备任何东西。**
这与 NLP 的情况不同,由于文本的语法结构,数据扩充应该小心进行。这里讨论的方法都是训练前使用的**。**预先生成一个新的扩充数据集,然后输入数据加载器来训练模型。
数据扩充方法
在本文中,我将主要关注以下项目中提供的 NLP 数据扩充方法:
所以,让我们深入了解每一个问题。
反向翻译
在这个方法中,我们将文本数据翻译成某种语言,然后再翻译回原来的语言。这可以帮助生成具有不同单词的文本数据,同时保留文本数据的上下文。
像 google translate、Bing、Yandex 这样的语言翻译 API 用于执行翻译。例如,给出这样一句话:
你可以看到,这些句子是不一样的,但回译后它们的内容保持不变。如果您想对数据集尝试这种方法,您可以使用这个笔记本作为参考。
简单的数据扩充
简易数据扩充使用传统且非常简单的数据扩充方法。EDA 包括四个简单的操作,在防止过度拟合和帮助训练更健壮的模型方面做得出奇的好。
从句子中随机选择 n 个不是停用词的单词。用随机选择的同义词替换这些单词。
例如,给出这样一句话:
这篇文章将重点总结自然语言处理中的数据增强技术。
方法随机选取 n 个单词(说两个),单词文章和技法,分别用写法和方法代替。
这篇文章将重点总结 NLP 中的数据扩充方法。
找出句子中不是停用词的随机词的随机同义词。将同义词插入句子中任意位置。这样做 n 次。
例如,给出这样一句话:
这篇文章将重点总结自然语言处理中的数据增强技术。
方法随机选取 n 个单词(比如两个),将单词文章和技巧分别找到同义词为写作和方法。然后将这些同义词插入句子中的任意位置。
本文将关注综述NLP方法中的数据扩充技术。
随机选择句子中的两个单词,交换位置。这样做 n 次。
例如,给定一个句子
这篇文章将重点总结自然语言处理中的数据增强技术。
该方法随机选择 n 个单词(比如两个),单词文章和技巧并交换它们来创建一个新句子。
本技巧将重点总结 NLP 中的数据增强文章。
以概率 p 随机去掉句子中的每个单词。
例如,给定一个句子
这篇文章将重点总结自然语言处理中的数据增强技术。
该方法选择 n 个单词(比如说两个),单词将和技术,并将它们从句子中移除。
这篇 文章重点总结 NLP 中的数据增强。
如果您想将这些技术应用到您的项目中,您可以访问这个库。
NLP 蛋白沉淀
之前,我们讨论了计算机视觉数据增强和 NLP 数据增强之间的差异。但是在本节中,我们将看到如何在 NLP 中应用 CV 数据扩充中使用的一些思想。
为此,我们将使用白蛋白包。
让我们来看看这里的一些技术。
- 混排句子变换
在这种转换中,如果给定的文本样本包含多个句子,这些句子将被打乱以创建一个新的样本。
例如:
文本= ' <句子 1 >。<句子 2 >。第四句>。第四句>。第五句>。‘句子 5>’
被转换为:
文本= ' <句子 2 >。<句子 3 >。第一句>。句子 5 >。第五句>。<句子 4 >
- 排除重复转换
在这种转换中,如果给定的文本样本包含具有重复句子的多个句子,则这些重复句子被移除以创建新的样本。
例如给定样本,
文本= ' <句子 1 >。<句子 2 >。第四句>。第四句>。第五句>。‘句子 5>’
我们将其转化为:
’<句子 1 >。<句子 2 >。第四句>。‘句子 5>’
您可以使用这个库尝试许多其他转换。你可以查看这个精彩的笔记本来看看完整的实现。
NLPAug 库
到目前为止,我们已经讨论了在 NLP 中使用数据扩充的许多方法。
但是从头开始有效地实现这些方法需要做大量的工作。
在这一节中,我将向您介绍一个 python 包,它可以让您轻松地完成所有这些数据扩充,并且您可以使用各种参数来调整您需要的扩充级别。
NLPAug 帮助你为你的机器学习项目增加 NLP。让我们看看如何使用这个库来执行数据扩充。
NLPAug 提供三种类型的增强:
- 字符级增强
- 单词级增强
- 句子层次扩充
在每个级别中,NLPAug 都提供了前面章节中讨论的所有方法,例如:
- 随机删除,
- 随机插入,
- 洗牌,
- 同义词替换,
- 等等。
根据我的经验,最常用和有效的技术是通过单词嵌入替换同义词。
我们将 n 个单词替换为它的同义词(接近这些单词的单词嵌入),以获得具有相同含义但不同单词的句子。
在执行同义词替换时,我们可以选择应该使用哪种预训练嵌入来查找给定单词的同义词。
使用 NLPaug,我们可以选择非上下文嵌入,例如:
或者上下文嵌入,比如:
例如:
aug = naw.ContextualWordEmbsAug(
model_path='bert-base-uncased', action="insert")
augmented_text = aug.augment(text)
原件:
敏捷的棕色狐狸跳过懒惰的狗
扩充文本:
即使是敏捷的棕色狐狸通常也会跳过懒狗
进行 NLP 数据扩充时要记住的事情
正如我在介绍中所说的,在 NLP 中进行增强时,我们需要注意一些事情。
在对扩充数据进行训练时面临的主要问题是算法,如果做得不正确,就会严重过度拟合扩充的训练数据。
一些需要记住的事情:
- 不要使用扩充数据进行验证。
- 如果你正在进行 K-fold 交叉验证,请始终将原始样本和扩充样本放在同一个 fold 中,以避免过度拟合。
- 总是尝试不同的增强方法,并检查哪个效果更好。
- 混合使用不同的增强方法也是值得的,但是不要过度。
- 通过实验来确定要增加的最佳样本数,以获得最佳结果。
- 请记住,NLP 中的数据扩充并不总是有助于提高模型性能。
数据扩充工作流程
在本节中,我们将在上尝试数据增强,真实与否?在 Kaggle 上举办的 NLP 与灾难推文竞赛。
在我之前的一篇文章中,我使用了这次比赛的数据来尝试不同的非上下文嵌入方法。在这里,我将使用我在那里使用的完全相同的分类管道,但是我将添加数据扩充,以查看它是否提高了模型性能。
首先,让我们加载训练数据集并检查目标类分布。
…
x=tweet.target.value_counts()
sns.barplot(x.index,x)
plt.gca().set_ylabel('samples')
我们可以看到这里有一个小的阶级不平衡。
让我们用同义词替换法生成一些正样本。
在数据扩充之前,我们将数据分为训练集和验证集,以便验证集中没有样本用于数据扩充。
train,valid=train_test_split(tweet,test_size=0.15)
现在,我们可以对训练数据集进行数据扩充。我已经选择从正类中生成 300 个样本。
def augment_text(df,samples=300,pr=0.2):
aug_w2v.aug_p=pr
new_text=[]
df_n=df[df.target==1].reset_index(drop=True)
for i in tqdm(np.random.randint(0,len(df_n),samples)):
text = df_n.iloc[i]['text']
augmented_text = aug_w2v.augment(text)
new_text.append(augmented_text)
new=pd.DataFrame({'text':new_text,'target':1})
df=shuffle(df.append(new).reset_index(drop=True))
return df
train = augment_text(train)
我们现在可以使用这些扩充的文本数据来训练模型。
如果你对学习如何从 NLP 的数据准备、训练分类器和运行推理中构建整个管道感兴趣,你可以查看我的另一篇文章。
那么,用同义词替换进行数据扩充有效吗?
| 没有数据扩充 | 用数据
增强 | ROC AUC 得分 |
| --- | --- | --- |
| 0.775 | 0.785 | 通过数据扩充,我们在模型性能(AUC)方面得到了很好的提升。 |
使用不同的技术和调整数据扩充方法的超参数可以进一步改善结果,但我现在将把它放在一边。
如果你想这么做,我准备了一个笔记本,你可以在上面玩东西。
最后的想法
在本文中,我们讨论并实现了文本数据的不同数据扩充方法。
据我所知,这些是完成这项任务的最好的公开技术和软件包。
希望你会发现它们对你的项目有用。
To my knowledge, these are the best publically available techniques and packages to do the task.
Hopefully, you will find them useful in your projects.
机器学习中的数据中心方法与模型中心方法
原文:https://web.archive.org/web/https://neptune.ai/blog/data-centric-vs-model-centric-machine-learning
代码和数据是 AI 系统的基础。这两个组件在健壮模型的开发中都起着重要的作用,但是您应该更关注哪一个呢?在本文中,我们将介绍以数据为中心的与以模型为中心的 方法,看看哪种方法更好,我们还将讨论如何采用以数据为中心的基础设施。
以模型为中心的方法
以模型为中心的方法意味着开发实验研究以提高 ml 模型的性能。这包括从广泛的可能性中选择最佳的模型架构和训练过程。****
- 在这种方法中,您保持数据不变,并改进代码或模型架构。
- 处理代码是这种方法的中心目标。
人工智能世界中以模型为中心的趋势
目前,大多数人工智能应用都是以模型为中心的,这背后的一个可能原因是人工智能领域非常关注对模型的学术研究。据吴恩达称,该领域超过 90%的研究论文都是以模型为中心的。这是因为很难创建能够成为公认标准的大型数据集。因此,人工智能社区认为,以模型为中心的机器学习更有前途。在关注代码的同时,数据经常被忽略,数据收集被视为一次性事件。
以数据为中心的方法
在这个时代,数据是每个决策过程的核心,以数据为中心的公司可以通过使用运营中产生的信息,更好地使其战略与其利益相关者的利益保持一致。这样,结果可以更准确、更有条理、更透明,有助于组织更顺利地运行。
- 这种方法包括系统地改变/改进数据集,以提高您的 ML 应用程序的准确性。
- 处理数据是这种方法的核心目标。
数据驱动/以数据为中心的难题
Data-driven vs data-centric |Source
许多人经常对以数据为中心的方法和数据驱动的方法感到困惑。数据驱动方法是一种从数据中收集、分析和提取见解的方法。它有时被称为“分析”另一方面,以数据为中心的方法专注于使用数据来定义您首先应该创建什么。
- 以数据为中心的架构指的是一种系统,其中数据是主要的永久资产,而应用程序会发生变化。
- 数据驱动架构意味着通过吸收大量数据来创造技术、技能和环境。
现在让我们谈谈以数据为中心的方法与以模型为中心的方法有什么不同,以及首先需要它。
以数据为中心的方法与以模型为中心的方法
对于数据科学家和机器学习工程师来说,以模型为中心的方法似乎更令人愉快。这是可以理解的,因为从业者可能会使用他们的知识来解决特定的问题。另一方面,没有人愿意花一整天的时间来标记数据,因为这被认为是一次性的工作。
然而,在今天的机器学习中,数据是至关重要的,但它在人工智能计划中经常被忽视和错误处理。结果,数百个小时被浪费在基于错误数据的模型微调上。这很可能是您的模型准确性较低的根本原因,与模型优化无关。
以模型为中心的 ML | 以数据为中心的 ML |
---|---|
编写代码是中心目标
|
处理数据是中心目标
|
|
优化模型,使其能够处理数据中的噪声
|
与其收集更多的数据,不如投资更多的数据质量工具来处理嘈杂的数据
数据经过标准预处理后被固定
|
代码/算法固定
|
|
模型被迭代改进
|
迭代了数据质量
|
来源:与 Andrew 关于 MLOps 的对话:从以模型为中心到以数据为中心的人工智能
你不必完全以数据为中心;有时候关注模型和代码是很重要的。做研究和改进模型很好,但数据也很重要。我们倾向于在关注模型的同时忽略数据的重要性。最好的方法是采用一种同时关注数据和模型的混合方法。根据您的应用程序,您可以更多地关注数据,而不是模型,但是两者都应该考虑。
对以数据为中心的基础架构的需求
以模型为中心的 ML 指的是主要关注优化模型架构及其参数的机器学习系统。
Model-centric ML application | Source: Author
上图中描述的以模型为中心的工作流适用于少数行业,如媒体和广告,但也可以考虑医疗保健或制造业。他们可能面临以下挑战:
1。需要高级定制
与媒体和广告行业不同,拥有多种商品的制造企业无法使用单一的机器学习系统来检测其所有产品的生产故障。相反,每一个制造出来的产品都需要一个训练有素的 ML 模型。
虽然媒体公司有能力让整个 ML 部门处理每一个小的优化问题,但需要几个 ML 解决方案的制造企业在规模上无法遵循这样的模板。
2。大型数据集的重要性
在大多数情况下,公司没有大量的数据点来处理。相反,他们经常被迫处理微小的数据集,如果他们的方法是以模型为中心的,则容易产生令人失望的结果。
Andrew NG 解释了 他如何认为以数据为中心的人工智能更有价值,并在他的人工智能演讲中倡导社区向以数据为中心的革命。 他给出了一个钢铁缺陷检测问题陈述的例子,其中以模型为中心的方法未能提高模型的准确性,而以数据为中心的方法将准确性提高了 16%。
数据在人工智能研究中极其重要,采取优先获得高质量数据的策略至关重要——毕竟,相关数据不仅稀有和嘈杂,而且获得起来极其昂贵。这个想法是,人工智能应该以同样的方式被对待,就像我们在建造房子时会关心最好的材料一样。应该在每一个层次上对它们进行评估,而不是一次性事件。
采用以数据为中心的基础架构
Data-centric ML application | Source: Author
在实施以数据为中心的架构时,将数据视为比应用程序和基础架构更持久的基本资产。这种方法不需要单一的数据库或数据存储库,而是需要对数据有统一的理解和描述。以数据为中心的 ML 使数据共享和移动变得简单。
那么,以数据为中心的机器学习到底涉及到什么?在实施以数据为中心的方法时,您应该考虑哪些基本因素?
1.数据标签质量
数据标注是将一个或多个标签分配给数据的过程。标签与应用于数据的特定值相关联。当大量图像被错误标记时,结果比使用较少但准确的图像时低。
标签提供了有关数据集内容和结构的详细信息,其中可能包括数据集中表示的数据类型、度量单位和时间段等组件。提高标签质量的最佳方法是找出标签中的不一致之处,并按照标签说明进行操作。在本文的后面,我们将了解更多关于数据质量的重要性。
2.数据扩充
数据扩充是一项数据分析任务,涉及通过内插法、外推法或其他方法创建数据点。它可以用于为机器学习引入更多的训练数据,也可以用于制作具有不同程度真实感的合成图像或视频帧。它有助于增加相关数据点的数量,例如通过创建您的模型在整个训练期间尚未看到的数据来增加有缺陷的生产组件的数量。
然而,添加数据并不总是最好的选择。去除导致高方差的噪声观测值可以提高模型归纳新数据的能力。
3.特征工程
特征工程是通过改变输入数据、先验知识或算法向模型添加特征的过程。它用于机器学习,以帮助提高预测模型的准确性。
提高数据质量包括改善输入数据和目标/标签。特征工程对于添加原始形式中可能不存在但可以产生显著差异的特征是至关重要的。
4.数据版本化
在任何软件应用程序中,数据版本控制都扮演着重要的角色。作为开发人员,您希望通过比较两个版本来追踪 bug,并发现一些不再有意义的东西。或者您可以通过再次部署该特定版本来防止该错误。管理数据集访问以及每个数据集在整个时间内的多个版本是困难且容易出错的。数据版本化是维护数据最重要的步骤之一——它有助于跟踪数据集的变化(添加和删除)。版本控制使得代码协作和数据集管理变得更加容易。
版本化也使得从概念验证到生产的 ML 管道管理变得容易,这就是 MLOps 工具的作用。您可能想知道为什么在“数据版本化”的上下文中讨论 MLOps 工具。这是因为在机器学习应用程序的开发中,管理数据管道是一项非常困难的任务。版本控制确保了再现性和可靠性。以下是几个最好的数据版本化平台:
Neptune 是为研究和生产团队开发的 MLOps 的元数据存储。它为您提供了一个记录、存储、显示、组织、比较和查询机器学习生命周期中生成的所有元数据的中心。在数据版本化的背景下,使用 Neptune 您可以:
使用工件跟踪模型训练运行中的数据集版本。
- 查询以前运行的数据集版本,以确保您在相同的数据集版本上进行训练。
- 在 Neptune UI 中组织数据集版本元数据。
- 参见代码示例,了解关于 Neptune 数据版本控制的更多信息。
weights & bias(WandB)是一个为研究人员和深度学习团队提供机器学习工具的平台。WandB 帮助您进行实验跟踪、数据集版本控制和模型管理。使用 WandB,您可以:
使用工件进行数据集版本化、模型版本化,并跨机器学习管道跟踪依赖性和结果。
- 您可以将完整的数据集直接存储在工件中,或者使用工件引用指向其他系统中的数据,如 S3、GCP 或您的本地机器。
- 参见代码示例,了解更多关于 WandB 数据版本控制的信息。
DVC 是一个机器学习项目的开源平台。DVC 帮助数据科学家和开发人员进行数据版本管理、工作流管理和实验管理。DVC 让你:
在 Git commits 中捕获数据和模型的版本,同时将它们存储在本地或云存储中。
- 在不同的数据内容之间切换。
- 生成元文件,描述要跟踪的数据集、ML 工件。
- 参见代码示例,了解更多关于 DVC 数据和模型版本的信息。
5.领域知识
领域知识在以数据为中心的方法中非常有价值。主题专家经常能发现 ML 工程师、数据科学家和标签员不能发现的小差异。在 ML 系统中仍然缺少领域专家的参与。如果有额外的领域知识,ML 系统可能会表现得更好。
以数据为中心的方法的优势
变得更加以数据为中心的优势有很多,从提高报告速度和准确性到做出更明智的决策。以数据为中心的基础架构具有诸多优势:
提高准确性,将数据作为战略资产有效地确保更精确的估计、观察和决策。
- 消除复杂的数据转换。
- 减少数据错误和不一致。
- 对内部和外部趋势提供有价值的见解,帮助您做出更好的决策。
- 减少开支。
- 使关键利益相关者更容易获得数据。
- 减少数据冗余。
- 提高数据质量和可靠性。
- 数据量和数据质量哪个优先?
在进一步讨论之前,我想强调的是,更多的数据并不等于更好的数据。当然,一个神经网络不能用一些图像来训练,但现在的重点是质量而不是数量。
数据质量
它指的是可访问的数据量。主要目标是收集尽可能多的数据,然后训练神经网络来学习映射。
如上图所示,大多数 Kaggle 数据集并没有那么大。在以数据为中心的方法中,数据集的大小并不那么重要,一个小质量的数据集可以做很多事情。
Data | Source (image by author)
数据质量
顾名思义,数据质量就是质量。如果你没有数百万的数据集,这没有什么区别;重要的是它们质量高,标签贴得好。
在上图中,您可以看到标注数据的不同方式;单独标注或者组合标注都没有问题。例如,如果数据科学家 1 单独标记菠萝,但数据科学家 2 标记它合并,数据将不兼容,导致学习算法变得混乱。主要目标是保持标签的一致性;如果你是独立标注的,确保所有的标注都是一样的。
Different approaches to drawing bounding boxes | Source: inspired by Andrew Ng*, image by author *
数据注释的一致性至关重要,因为任何差异都可能使模型偏离轨道,并使您的评估不准确。因此,您需要仔细定义注释指南,以确保 ML 工程师和数据科学家一致地标记数据。 根据research统计,常用数据集中大约有 3.4%的样本被错误标注,其中大型模型受到的影响最大。
在上图中,吴恩达解释了小型数据集中一致性的重要性。上图说明了无人机的电压和速度之间的关系。如果数据集很小但标注一致,您可以自信地拟合曲线并获得更高的精度。
Importance of consistency in small datasets | Source
低质量的数据意味着缺陷和不准确可能会被无限期地检测出来,而不会产生任何后果。**模型的准确性取决于您的数据质量;**如果你想做出正确的决定,你需要准确的信息。属性差的数据存在包含错误和异常的风险,这在使用预测分析和建模技术时会非常昂贵。
说到数据,多少才算多?
您拥有的数据量至关重要;你必须有足够的数据来解决你的问题。深度网络是低偏差、高方差的计算机,我们认为方差问题的解决方案是更多的数据。但是多少数据才够呢?这是一个比你想象的更难回答的问题。 Yolov5 建议道:
每节课至少 1.5k 张图片
- 每个类至少 10k 个实例(标记为对象)总计
- 拥有大量的数据是一个好处,而不是必须的。
以数据为中心的方法的最佳实践
如果您采用以数据为中心的方法,请记住以下几点:
确保 ML 项目生命周期中高质量数据的一致性。
- 使标签一致。
- 利用生产数据获得及时反馈。
- 使用误差分析来关注数据的子集。
- 消除噪声样本;如上所述,数据越多并不总是越好。
- 哪里可以找到好的数据集?
获得高质量的数据集是一项重要的任务。所以,这里有几个网站,你可以免费获得这样的数据集。
第一个是数据科学界众所周知的。在 Kaggle 中,您可以找到进行数据科学工作所需的所有代码和数据。它拥有超过 50,000 个公共数据集和 400,000 个公共笔记本,允许它快速完成任何分析。
Datahub 是一个数据集平台,主要关注商业和金融。许多数据集,如国家、人口和地理边界列表,目前都可以在 DataHub 上获得,还有更多正在开发中。
Graviti 是一个新的数据平台,主要为计算机视觉提供高质量的数据集。个人开发人员或组织可以轻松地访问、共享和更好地管理大量开放数据。
结论
在本文中,我们了解了以数据为中心的方法与以模型为中心的方法有何不同,以及如何让您的机器学习应用程序更加以数据为中心。我们不必把自己局限在一个单一的方向,代码和数据在人工智能的旅程中都扮演着重要的角色。在以模型为中心和以数据为中心的方法之间进行选择没有硬性规定,但是数据集的健壮性不应该被忽视。
数据质量必须在人工智能开发的每一个阶段得到维护和提高,根据定义,每一个阶段都需要不同的框架和工具。如果你想更深入地了解这一点,我在下面分享了一些参考资料来帮助你开始。
希望你喜欢这篇文章,继续尝试!
参考资料和推荐读物
References and recommended reading
数据清理过程:应该是什么样子?
原文:https://web.archive.org/web/https://neptune.ai/blog/data-cleaning-process
数据清理就是通过修改、添加或删除数据来为分析做准备的过程。这个过程通常也称为数据预处理。对于数据科学家和机器学习工程师来说,在数据清理领域非常熟练非常重要,因为他们或他们的模型将从数据中获得的所有见解都直接取决于对数据进行的预处理的质量。
在这篇博文中,就分类特征而言,我们将仔细研究数据清理的概念。
经过以上这几点,我尽量解释,给出图片参考来辅助理解,代码演示等等。
在本文结束时,您不仅会知道什么是数据清理,还会对数据清理中涉及的步骤、如何进行这些步骤以及最重要的是如何充分利用您的数据有一个完美的理解。所以,让我们继续前进。
为什么我们需要清理我们的数据?
有时,在我们能够从中提取有用的信息之前,需要对数据进行清理/预处理。大多数现实生活中的数据都有很多不一致的地方,比如缺失值、非信息特征等等,因此,在使用数据之前,我们需要不断地清理数据,以便从中获得最佳效果。
举个例子,机器学习过程只处理数字。如果我们打算使用具有文本、日期时间特征和其他非数字特征的数据,我们需要找到一种用数字表示它们而不丢失它们所携带的信息的方法。
比如说:
简单的逻辑回归模型使用线性函数简单地将因变量映射到自变量,例如: y= wx + b
其中:
w 是重量,可以是任何数字。
而 b 是 bias,也是一个数。
如果给你一组数据。【小,中,大】,你发现无法计算:*y = w 小+b
但是如果你将小的编码为 1,中的编码为 2,大的编码为 3,从而将你的数据转换为[1,2,3],你会发现你不仅能够计算=w * 1+b,,而且其中编码的信息仍然被保留。像这样的情况以及更多的情况是我们在数据清理和预处理方面的业务。
数据清洗有哪些步骤?
数据清理只是我们在准备数据进行分析的过程中对数据执行的一系列操作的统称。
数据清理的一些步骤是:
- 处理缺失值
- 编码分类特征
- 离群点检测
- 转换
- 等等。
处理缺失值
预处理数据时遇到的最常见的问题之一是数据中的值缺失的问题。它们非常常见,可能是由于:
- 填写数据的人有意或无意的遗漏,或者根本不适用于他们。
- 将数据输入计算机的人的疏忽。
数据科学家如果不小心,可能会从包含缺失值的数据中得出错误的推断,这就是为什么我们需要研究这种现象,并学会有效地解决它。
早期的机器学习库,如 scikit learn,不允许将缺失值传递给它们。这带来了一定的挑战,因为在将数据传递给 scikit learn ML 模型之前,数据科学家需要迭代许多方法来处理缺失值。最近的机器学习模型和平台已经消除了这一障碍,尤其是梯度增强机器,如 Xgboost,Catboost,LightGBM 等。
我个人喜欢的一种方法是 Catboost 的方法,它允许您在三个选项(禁止、最小和最大)中进行选择。“禁止”将缺失值视为错误,而“最小”将其设置为小于特定要素(列)中的所有其他值。通过这种方式,我们可以确定,在特征的基本决策树分割过程中,这些丢失的值也被视为。
LightGBM 和 XGboost 也以非常方便的方式处理缺失值。但是,在预处理的时候,尽量多尝试一些方法。处理你自己,使用一些我们上面讨论过的库,一些其他的工具,比如 automl,等等。
缺失值通常分为三类:
- 完全随机缺失():缺失值完全随机缺失,如果我们没有任何信息、原因或任何可以帮助计算它的东西。例如,“我是一个非常困倦的研究生,不小心把咖啡打翻在我们收集的一些书面调查上,所以我们丢失了所有本来会有的数据。”
- 随机缺失( MAR ) :一个缺失的值,如果我们有信息、理由或任何东西(特别是从其他已知值)可以帮助计算它,那么它就是随机缺失的。例如,“我管理一项调查,其中包括一个关于某人收入的问题。女性不太可能回答关于收入的问题。”
- 不随意遗漏()。丢失的变量的值与它丢失的原因有关。例如,“如果我管理一项包含某人收入问题的调查。低收入人群回答这个问题的可能性要小得多”。因此,我们知道为什么这些数据点可能会丢失**
**## 我们如何在 Python 中检测缺失值?
在我们处理丢失的值之前,我们应该学习如何检测它们,并根据丢失值的数量、我们拥有的数据量等等来决定如何处理我们的数据。我喜欢并经常使用的一个实现是为一个列设置一个阈值,以决定它是可修复的还是不可修复的,哈哈。(50–60%对我来说是这样)。
下面,您将看到一个函数,它实现了我们在上一段中讨论的思想。
def missing_removal(df, thresh, confirm= None):
holder= {}
for col in df.columns:
rate= df[col].isnull().sum() / df.shape[0]
if rate > thresh:
holder[col]= rate
if confirm==True:
df.drop(columns= [i for i in holder], inplace= True)
return df
else:
print(f'Number of columns that have Nan values above the thresh specified{len(holder)}')
return holder
速记 :
如果 confirm 设置为 true,将删除缺失值百分比高于阈值集的所有列,如果 confirm 设置为 None 或 False,该函数将返回数据中所有列的缺失值百分比列表。在您的数据上尝试一下。太酷了。
既然我们能够检测到数据中缺失的值,并丢弃不可恢复的值,保留可恢复的值,那么让我们继续讨论如何实际修复它们。
有两种方法可以解决这个问题:
1。统计插补:
随着时间的推移,这种方法已被证明是有效的。你所要做的就是用列的均值、中值、众数来填充列中缺失的数据。伙计们,相信我。
Scikit-learn 提供了一个名为simple imputr的子类,以这种方式处理我们丢失的值。
下面的简短描述将有助于更好地理解统计插补。
from sklearn.impute import SimpleImputer
cols= df.columns
imputer= SimpleImputer(strategy= 'most_frequent')
df= imputer.fit_transform(df)
df= pd.DataFrame(df, columns= cols)
2。链式方程的多重插补(小鼠):
在这种方法中,一列及其缺失值被建模为数据中其他列的函数。重复该过程,直到先前计算的值和当前值之间的容差非常小并且低于给定的阈值。
Scikit-learn 提供了一个名为iterative inputr的子类,以这种方式处理我们丢失的值。
下面是一个简短的描述,希望能让你巩固这个概念。
from sklearn.experimental import enable_iterative_imputer
from sklearn.impute import IterativeImputer
cols= df.columns
imputer= IterativeImputer(max_iter= 3)
df= imputer.fit_transform(df)
df= pd.DataFrame(df, columns= cols)
希望到目前为止,我们讨论的内容足以让您有效地处理丢失的值。
想了解更多关于缺失值的信息,请查看 Matt Brems 的这篇精彩文章。
编码分类特征
什么是分类特征?
好吧,我的朋友们,分类特征是只取离散值的特征。它们不采用连续值,如 3.45、2.67 等。分类特征可以具有大、中、小、1- 5 作为等级、是和否、1 和 0、黄色、红色、蓝色等值。它们基本上代表了类别,例如年龄组、国家、肤色、性别等。
通常,它们以文本格式出现,其他时候,它们以数字格式出现(大多数人经常无法识别这种格式)。
如何识别分类特征?
这没什么大不了的,大多数时候,分类特征是以文本格式出现的,这就是你识别它们所需要的。
如果,这是一种排名形式,它们实际上是以数字的形式出现的。那么,要做的是检查一列中唯一值的数量,并将其与该列中的行数进行比较。比方说,一列有 2000 行,只有 5 或 10 个唯一值,您很可能不需要圣人告诉您该列是分类列。这没有规则,这只是直觉,你可能是对的,也可能是错的。所以要自由,尝试新事物。
编码类别
给定一个分类特征,正如我们在上面检查过的,我们面临一个问题,将每个特征中的唯一类别转换为数字,同时不丢失其中编码的信息。基于一些可观察的特征,有各种编码分类特征的方法。
还有两类分类特征;
- 有序范畴特征 :这种特定特征中的范畴之间存在着内在的顺序或关系,如大小(小、大、中)、年龄组等。
- 名义分类特征: 特征的类别之间没有合理的顺序,例如国家、城市、名称等。
上面两个类的处理方式不同。我在研究名词性范畴特征时使用的一些方法有:
- 一键编码
- 频率/计数编码
- 目标均值编码
- 有序整数编码
- 二进制编码
- 省略一个编码
- 证据权重编码
对于有序分类特征,我们仅使用:
- 标签编码或顺序编码
现在,我们将尝试一个接一个地学习这些方法。我们也会尽可能用 python 实现它们,并使用一个叫做 category_encoders 的 python 库。
您可以使用 pip install category_encoders 安装库。
一键编码
一键编码是对名词性分类特征进行编码的最有效的方法之一。此方法为列中的每个类别创建一个新的二进制列。理想情况下,我们会删除这些列中的一列,以避免列之间的共线性,因此,具有 K 个唯一类别的要素将在数据中产生额外的 K-1 列。
这种方法的一个缺点是,当一个特征有许多独特的类别或数据中有许多分类特征时,它会扩展特征空间。
上图真正解释了一键编码的概念。以这种方式对特征进行编码消除了所有形式的等级。
下面描述了该方法在 python 中的实现:
import pandas as pd
data= pd.get_dummies(data, columns, drop_first= True)
频率/计数编码
这个方法同样非常有效。它根据名词性分类特征在特征(列)中出现的频率为其引入层次结构。这与计数编码非常相似,因为计数编码可以采用任何值,而频率编码被规范化为范围 0 和 1。
下面描述了该方法在 python 中的实现:
def freq_enc(df, cols):
for col in cols:
df[col]= df[col].map(round(df[col].value_counts()/len(df),4))
return df
def count_enc(df, cols):
for col in cols:
df[col]= df[col].map(round(df[col].value_counts()))
return df
目标均值编码
这个方法背后的想法其实很高明。这种方法非常独特,因为它在计算中使用了目标列,这在一般的机器学习实践中很少见。分类特征中的每个类别都被替换为该类别的目标列的平均值。
这是一种非常好的方法,但是如果它编码了太多关于目标的信息,可能会导致过度拟合,因此,在使用这种方法之前,我们需要确保这种分类特征与目标列不是高度相关的。
通过映射,用来自训练数据的存储值对测试数据进行编码。
下面描述了该方法在 python 中的实现:
def target_mean_enc(df, cols, target_col):
mean_holder= {}
for col in cols:
col_mean= {}
cat= list(df[col].unique())
for i in cat:
data= df[df[col]== i]
mean= np.mean(data[target_col])
col_mean[i]= mean
mean_holder[col]= col_mean
return mean_holder
上面的函数返回一个字典,其中包含被编码的列的平均值。然后将字典映射到数据上。见下文:
有序整数编码
这种方法与目标均值编码非常相似,只是它更进一步,根据类别的目标均值大小对类别进行排序。
实施有序整数编码后,数据帧如下所示:
下面描述了该方法在 python 中的实现:
def ordered_interger_encoder(data, cols, target_col):
mean_holder= {}
for col in cols:
labels = list(enumerate(data.groupby([col])[target_col].mean().sort_values().index))
col_mean= {value:order for order,value in labels}
mean_holder[col]= col_mean
return mean_holder
省略一个编码
这种方法也非常类似于目标均值编码,除了在每个级别,它计算目标均值,而忽略特定级别。目标均值编码仍然用于测试数据(更多信息请查看)。
下面描述了该方法在 python 中的实现:
from category_encoders import leave_one_out
binary= leave_one_out(cols= ['STATUS'])
binary.fit(data)
train= binary.transform(train_data)
test= binary.transform(test_data)
二进制编码
二进制编码的工作方式很独特,在某种意义上,它也创造了额外的功能,几乎类似于一键编码。首先,它根据独特的特征在数据中出现的方式给它们分配等级(不要烦恼!,这个排名没有任何意义)。然后,等级被转换为以二为基数的数字系统(二进制)。然后,各个数字被拆分到不同的列中。
下面描述了使用 category_encoders 库的方法演示:
from category_encoders import BinaryEncoder
binary= BinaryEncoder(cols= ['STATUS'])
binary.fit(data)
train= binary.transform(train_data)
test= binary.transform(test_data)
证据权重编码
这是一种已经在信用风险分析中使用了 70 年的方法。它通常用于转换逻辑回归任务的特征,因为它有助于揭示我们以前可能看不到的特征之间的相关性。此方法只能在分类任务中使用。
它简单地通过将 *ln(p(好)/p(坏))*应用到列中的每个类别来转换分类列。
其中:
*p(好)*是目标列中的一类表示 p(1)
而 *p(坏)*是第二个类别,它可能就是 p(0)。
下面描述了使用 category_encoders 的这种方法的实现:
from category_encoders import WOEEncoder
binary= WOEEncoder(cols= ['STATUS'])
binary.fit(data)
train= binary.transform(train_data)
test= binary.transform(test_data)
标签编码或顺序编码
这种方法用于编码名义分类特征;我们只是简单地根据我们能从中推断出的数量来给每一类分配数字。
下面描述了该方法在 python 中的实现:
df['size']= df['size'].map({'small':1, 'medium':2, 'big':3})
df
在这篇文章的过程中,参考了某些机器学习库,如 scikit learn 和 category_encoders 。其他一些有助于数据预处理的 python 库包括:Numpy、Pandas、Seaborn、Matplotlib、Imblearn 等等。
然而,如果你是那种不喜欢写太多代码的人,你可以看看诸如 OpenRefine 、 Trifacta 牧马人和等工具。
结论
到目前为止,我们讨论的大多数概念的代码实现都有清晰的例子,可以在这里找到。
我希望这篇文章能够让您深入了解分类编码的概念以及如何填充缺失值。
你应该使用哪一个?
数据清理是一个迭代的过程,因此尽可能多地尝试这些方法,并坚持使用最适合您的数据的方法。**
数据探索和可视化的顶级工具及其优缺点
原文:https://web.archive.org/web/https://neptune.ai/blog/data-exploration-and-visualization-best-tools
当你在从事数据科学项目或试图找到数据洞察力来制定计划时,有两个关键步骤是不可避免的——数据探索和数据可视化。
数据探索是 EDA 的组成部分(探索性数据分析)。无论你在后面的阶段决定做什么(创建/选择机器学习模型或总结你的发现),都将取决于你在探索阶段做出的假设。这不是一个单一的步骤阶段,但我们在数据探索过程中可以确定很多关于我们的数据,例如检查数据分布、查找相关性、查找异常值和缺失值等。
数据可视化不是数据分析项目中任何特定阶段的一部分。在我们的项目中,我们可以在任何一点用视觉来表现数据。数据可视化只不过是表格或图形与数据(输入或输出)之间的映射。数据可视化有两种形式——表格和图形。
我们需要可视化作为数据的可视化总结,因为它更容易理解以识别关系和模式。在数据探索阶段使用了许多可视化工具来发现异常值、特征之间的相关性等。我们还使用图表和图形来检查模型的性能,或者对数据进行分类或聚类。
选择正确的图表来传达您的数据发现也很重要。使用折线图代替散点图可能没有意义。我们在日常工作中会用到或看到一些基本且广泛使用的图表——在数据科学和其他领域:
- 折线图
- 条形图
- 柱状图
- 箱形图
- 散点图
- 热图
在试图做出准确假设的同时,我们需要最好的工具来探索和可视化数据。市场上有几种可用的工具和库。记住所有的库几乎是不可能的,决定使用哪一个库可能会令人困惑。这篇文章的目的是:
- 总结一些最好的数据探索和可视化工具——Matplotlib, scikit learn , plotly , seaborn , pandas , D3 , bokeh , altair , yellowbrick ,leaf, tableau 。
- 通过一些例子熟悉这些工具
- 理解对可视化工具的需求
- 了解这些工具之间的区别以及如何选择
引入 Matplotlib 是为了模仿 MATLAB 支持的所有图形,但形式更简单。多年来,图书馆增加了多种功能。不仅如此,许多可视化库和工具都建立在 Matplotlib 之上,具有新的、交互式的和吸引人的视觉效果。
要了解有关 Matplotlib 的更多信息,让我们使用数据集来解锁并了解一些函数的工作原理:
import pandas as pd
netflix_df = pd.read_csv('netflix_titles.csv')
netflix_df.head(2)
我们有内容类型、标题、添加日期和其他信息。但是我们想用这些信息做什么呢?我们可以找到网飞有多少节目和电影(根据数据集),或者我们可以看到哪个国家制作了更多的内容。
import matplotlib.pyplot as plt
counts = netflix_df["type"].value_counts()
plt.bar(counts.index, counts.values)
plt.show()
在上面的代码中,你可以看到我们已经将 matplot 的 pyplot 作为 plt 导入。每个 pyplot 函数对图形进行一些更改——创建图形、创建绘图区域、绘制一些线、在图中引入标签等。然后,我们使用 pyplot 作为 plt 来调用条形图,并将数据可视化。
这里需要记住的一点是,每次创建新的绘图时,我们都必须使用 plt.show()命令。如果想避免这种重复的任务,可以在导入 matplotlib 后使用下面的命令。
%matplotlib inline
除了创建简单的条形图之外,您还可以做很多事情。您可以提供 x 和 y 标签,或者您可以根据它们的值给条形赋予不同的颜色。您可以选择更改标记、线型和宽度,添加或更改文本、图例和注释,更改地块的限制和布局,等等。
我们也可以使用 Matplotlib 来发现数据中的异常。让我们尝试创建一个定制的情节。
import pandas as pd
from sklearn.datasets import load_boston
import matplotlib.pyplot as plt
boston = load_boston()
x = boston.data
y = boston.target
columns = boston.feature_names
boston_df = pd.DataFrame(boston.data)
boston_df.columns = columns
fig = plt.figure(figsize =(10, 7))
ax = fig.add_axes([0, 0, 1, 1])
ax.set_xlabel('Distance')
bp = ax.boxplot(boston_df['DIS'])
plt.title("Customized box plot")
plt.show()
因为这个包提供了灵活性,所以当你开始使用它时,选择甚至记住一些东西可能会有点棘手。幸运的是,文档包含现实生活中的例子,每个情节的相关细节,以及我们需要的所有其他信息。不要感到不知所措,只要记住一个问题可以有不止一个解决方案。
现在我们对 Matplotlib 有了一些了解,让我们讨论一下它的优点和缺点,以及哪些工具可以与它集成。
优势
- 快速高效,基于 NumPy 和 SciPy 构建。
- 让你完全控制你的图表和情节,你可以做一些改变,使你的视觉效果更容易理解。
- 大型社区和跨平台支持,它是一个开源库。
- 几个高质量的绘图和图表。
不足之处
- 没有互动剧情,只有静态剧情。
- 制作定制图时,需要大量重复的代码。
- 您可以完全控制每一步的图形,因此您必须定义一个 matplotlib 函数,这可能很耗时。
Matplotlib 集成
很多流行的 Python 可视化库都是基于 Matplotlib 构建的。例如,seaborn 使用 matplotlib 来显示图形创建后的绘图。不仅仅是这样,很多工具也集成了Matplotlib——Neptune . ai就是其中之一。
成就
第一张黑洞图像是用 NumPy 和 Matplotlib 制作的。它也用于体育数据分析。
Scikit learn 是由 David Cournapeau 在 Google Summer code 项目中开发的。后来,在 2010 年,FIRCA 把它带到了另一个水平,并发布了该库的测试版。Scikit learn 已经走过了漫长的道路,现在它是最有用的健壮库。它是在 NumPy、SciPy 和 Matplotlib 之上用 Python 构建的。
它并不专注于任何数据科学项目的一个方面,而是提供了大量用于数据清理、管理、建模等的有效工具。
它拥有以下工具:
- 分类
- 回归
- 使聚集
- 降维
- 型号选择
- 预处理
数据探索和可视化适合哪里?Scikit Learn 提供了一系列工具来满足探索性数据分析的要求——发现问题并通过转换原始数据来恢复问题。
如果您正在寻找数据集进行实验,Scikit learn 有一个数据集模块,其中有一些流行的数据集集合。您可以像下面这样加载数据集,并且您不必将它下载到本地机器上。
from sklearn.datasets import load_iris
data = load_iris()
Scikit learn 在进行预处理(即清洁和处理。假设您的数据集中几乎没有缺失值。有两种处理方法:
- 删除所有缺少值的行/列,
- 输入一些值。
删除行/列并不总是一个好的选择,所以我们估算值——零、平均值等。
让我们看看如何使用 scikit 的 impute 模块来实现这一点。
import numpy as np
import pandas as pd
X = pd.DataFrame(
np.array([1,2,3, np.NaN, np.NaN, np.NaN, -7,
0,50,111,1,-1, np.NaN, 0, np.NaN]).reshape((10,3)))
X.columns = ['feature1', 'feature2', 'feature3']
from sklearn.impute import SimpleImputer
imp_mean = SimpleImputer(missing_values=np.nan, strategy='mean')
imp_mean.fit_transform(df)
上面,我们使用了一个简单的估算器模块来创建一个估算器,用平均值替换空值。Scikit learn 是唯一一款拥有几乎所有功能/模块的工具。没有其他工具像 Scikit learn 一样提供简单的输入模块。
当涉及到特性缩放或归一化分布时,Scikit learn 在预处理模块中有可用的函数:StandardScalar、MinMaxScalar 等。它也有功能工程模块。Scikit 只处理数字数据,所以您需要将分类变量转换成数字来浏览数据。
scikit learn 在数据探索方面处于领先地位,但在数据可视化方面用处很小。可视化模块仅用于可视化指标,如混淆指标、权衡曲线、roc 曲线或召回精度曲线。在下一个例子中,我们将看到如何使用可视化功能。
from sklearn import datasets
from sklearn.model_selection import train_test_split
iris = datasets.load_iris()
X = iris.data
y = iris.target
class_names = iris.target_names
X_train,X_test,y_train,y_test=train_test_split(
X,y,test_size=0.25, random_state=0)
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import plot_confusion_matrix
lr=LogisticRegression(C=1,random_state=0)
lr.fit(X_train,y_train)
plot_confusion_matrix(lr, X_test, y_test,display_labels=class_names,
cmap=plt.cm.Blues)
plt.show()
尽管 Scikit 有一些可视化模块,但它仍然不支持任何回归问题的可视化。但是,毫无疑问,它是最有效、最容易适应的数据挖掘工具。
优势
- 开源。
- 强大的社区支持。
- 随时可用的高效和最佳性能的数据探索实用程序。
- Scikit learn APIs 可用于将其工具集成到不同的平台中。
- 提供可用于自动化机器学习工作流的管道实用程序。
- 易于使用,它是一个完整的包,依赖于少量的库。
不足之处
- Scikit learn 只处理数字数据,必须对分类数据进行编码。
- 它的灵活性很低,而使用任何函数时,除了所提供的参数之外,你不能改变任何东西。
之前的两个工具没有任何交互式可视化。这些工具大部分都是用 Python 构建的,在视觉效果方面灵活性有限。
Plotly 开发在线数据分析和可视化工具。它为 Python、R 和 MATLAB 等不同平台和框架提供了图形和分析工具。它有一个数据可视化库 plotly.js,这是一个用于创建图表的开源 js 库。为了让 Python 使用它的实用程序,plotly.py 构建在它的基础上。
它支持 40 多种独特的图表类型,涵盖统计、金融、地理、科学和 3D 用例。它使用 D3.js,HTML 和 CSS,这有助于集成许多交互式功能,如放大和缩小,或鼠标悬停。
让我们看看如何使用 plotly 在情节中引入交互性。
pip install plotly==4.14.3
from sklearn import datasets
import pandas as pd
iris = datasets.load_iris()
iris_df = pd.DataFrame(iris.data)
iris_df.columns = ['Sepal.Length','Sepal.Width','Petal.Length','Petal.Width']
import plotly.graph_objs as go
data = [go.Histogram(x=iris.data[:,0])]
layout = go.Layout( title='Iris Dataset - Sepal.Length', xaxis=dict(title='Sepal.Length'), yaxis=dict(title='Count') )
fig = go.Figure(data=data, layout=layout)
fig
你可以在上面看到,plotly 的 plot 可以让你保存图像,放大和缩小,自动缩放等等。您还可以看到,在鼠标悬停后,我们可以看到 x 轴和 y 轴的值。
让我们使用 plotly 绘制更多的图表,以了解它如何帮助最终用户。
为了理解变量之间的关系,我们需要一个散点图,但当我们有许多数据点时,很难读懂这个图。鼠标悬停功能有助于轻松读取数据。
data = [go.Scatter(x = iris_df["Sepal.Length"],y = iris_df["Sepal.Width"],mode = 'markers')]
layout = go.Layout(title='Iris Dataset - Sepal.Length vs Sepal.Width', xaxis=dict(title='Sepal.Length'), yaxis=dict(title='Sepal.Width'))
fig = go.Figure(data=data, layout=layout)
fig
如果你希望你的图表具有交互性、吸引力和可读性,plotly 就是你的答案。
优势
- 你可以在 JavaScript 不知道的情况下用它构建交互式的情节。
- Plotly 允许你公开分享情节,甚至不需要分享你的代码。
- 简单的语法,几乎所有的图都使用相同的参数序列。
- 你不需要任何技术知识来使用 plotly,你可以使用图形用户界面来创建视觉效果。
- 为 3D 绘图提供多种交互式工具。
不足之处
- 当我们试图创建复杂的地块时,布局定义变得复杂。
- 与其他工具不同,它根据工具限制每天的 API 调用。
- 公共图表的可用性可能是一个好处,但对其他人来说可能是一个问题。
Matplotlib 是很多工具的基础,Seaborn 就是其中之一。在 Seaborn,您可以用最少的努力创建有吸引力的图表。它为常见的统计图提供了高级功能,以使其信息丰富且具有吸引力。
它与 pandas 紧密集成,并接受 pandas 数据结构格式的输入。Seaborn 没有重新实现任何情节,但调整了 Matplotlib 的功能,使我们可以通过提供最少的参数来使用这些情节。
Seaborn 从 Matplotlib 收集了一些常见的图,并对它们进行了分类:关系图(replot)、分布图(displot)和分类图(catplot)。
- 回复图–散点图、线图
- disp plot-hist plot、kdeplot、ecdfplot、rugplot
- catplot 卡通、全彩、方块式出图、violinplot 出图、pointplot、barplot
如果我们可以直接使用它们,为什么还要对情节进行分类呢?转折来了!Seaborn 允许您直接使用分类绘图,这被称为轴级绘图。这些图与 histplot()、lineplot()一样,都是独立的图,是 Matplotlib 的直接替代,尽管它们允许自动添加轴标签和图例等一些更改。当你想一起使用两个图,或玩更多,使定制的图,你需要使用图类别:图级绘图。
让我们尝试一些情节,看看 seaborn 是多么容易。
import pandas as pd
breast_cancer_df = pd.read_csv("data.csv")
plt.figure(figsize= (10,10), dpi=100)
sns.heatmap(breast_cancer_df.corr())
只需两行就能创建热图!现在我们将尝试一些我们已经用其他工具尝试过的图。
plt.figure(figsize=(8,5))
ax = sns.countplot(x="diagnosis", data=breast_cancer_df)
plt.show()
我们只是创建了一个计数图,没有计算任何东西,与 Matplotlib 非常不同。
图书馆不仅仅限于上述地块。它还具有 joinplot、subplot 或 regplot 函数,可以帮助用最少的代码创建定制的和统计的图。
优势
- 您可以轻松定制情节。
- 默认方法比 Matplotlib 更具视觉吸引力。
- 有一些 Matplotlib 没有的内置情节:facet 和 regression。对于回归,用一个函数你可以创建回归线,置信区间和散点图。
- 与 matplotlib 相比,Seaborn 可以很好地处理 pandas 数据结构。
不足之处
- 没有互动情节。
- Seaborn 易于可视化,并且更容易从多个图表中获得洞察力。
- 自动创建多个图形,这有时会导致 OOM(内存不足)问题。
Python 中最流行的用于数据分析和操作的库之一。它最初是作为一种对财务数据进行定量分析的工具。正因为如此,它在时序用例中非常流行。
大多数数据科学家或分析师处理表格格式的数据,如。csv,。xlsx 等。Pandas 提供了类似 SQL 的命令,使得加载、处理和分析数据变得更加容易。它支持两种类型的数据结构:序列和数据帧。这两种数据结构可以保存不同的数据类型。Series 是一维索引数组,dataframe 是二维数据结构——表格格式,在处理现实生活中的数据时很流行。
让我们看看如何定义 series 和 dataframe,并了解一些特性。
ser1=pd.Series(breast_cancer_df['area_mean'])
ser1.head()
你可以执行几乎所有的操作,使用我们将在熊猫系列中进一步讨论的所有功能。您还可以为您的系列提供索引。
data = pd.Series([5, 2, 3,7], index=['a', 'b', 'c', 'd'])
data
另外,你可以传递字典数据(键值对象),它也可以被转换成序列。
breast_cancer_df.describe()
只需一行代码,我们就可以查看数据。这就是熊猫的力量。
假设我们想要创建主数据帧的子集,这也可以用几行代码来完成。
subset_df=breast_cancer_df[["id", "diagnosis"]]
subset_df
print("print data for one column id: ",breast_cancer_df["id"])
print("print all the data for one row: ",breast_cancer_df.iloc[3])
让我们看看熊猫是如何处理缺失数据的,首先检查哪一列有缺失值。
data = {'Col1': [1,2,3,4,5,np.nan,6,7,np.nan,np.nan,8,9,10,np.nan],
'Col2': ['a','b',np.nan,np.nan,'c','d','e',np.nan,np.nan,'f','g',np.nan,'h','i']
}
df = pd.DataFrame(data,columns=['Col1','Col2'])
df.info()
非空计数列将显示有多少非空值可用。您可以删除具有空值的行或估算一些值。
我们可以用不同的方式处理字符串值,但是我们不会深入到那个细节层次。我们也可以使用熊猫进行统计计算,如计算平均值、平均数、中位数等。有许多字符串函数可用,如覆盖小写/大写、子串、替换字符串和使用正则表达式进行模式匹配。
Pandas 提供了查看数据(头部或尾部)、创建子集、搜索和排序、查找变量之间的相关性、处理缺失数据、整形-连接、合并等功能。
不仅如此,熊猫还有可视化工具。然而,它只画基本的情节,但是它们很容易使用。与 Matplotlib 或其他工具不同,您只需提供一个额外的命令 plt.show()来打印绘图。
breast_cancer_df[['area_mean','radius_mean','perimeter_mean']].plot.box()
上面的图是用一行命令识别异常值。它还允许您改变图的颜色、标签等。
corr = breast_cancer_df[['area_mean','radius_mean','perimeter_mean']].corr()
corr.style.background_gradient(cmap='coolwarm').set_precision(2)
上面的两个图表很容易创建,但是想象一下,如果我们想要为乳腺癌数据创建一个条形图,并且想要知道每种诊断类型的计数。我们首先需要找到计数,然后只能绘制箱线图。熊猫不提供定制剧情。为了使用您选择的绘图,您必须首先处理数据,然后将适当的数据输入绘图函数。
优势
- 数据的可读表示。
- 广泛的文件格式兼容性。
- 一个广泛的功能集可用,如 SQL 格式加入,合并和过滤数据。
- 高效处理大型数据集。
- 支持常见的可视化图形和绘图。
不足之处
- 与 3D 数据兼容性差。
- 与 NumPy 相比,消耗更多内存。
- 序列对象的索引速度较慢。
D3.js 是一个 JavaScript 库,用于在 web 浏览器中创建动态和交互式可视化。它使用 HTML、CSS 和 SVG 来创建数据的可视化表示。D3 代表数据驱动文档,它是由 Mike Bostock 创建的。它是在线分析数据可视化的最佳工具之一,因为它通过结合可视化组件和数据驱动方法来操纵 DOM。
我们可以使用 Django 或 Flask web 框架来创建一个网站。这样,我们可以利用 Python 的简单性和 D3 惊人的情节集合。Python 将作为后端系统工作,D3 可以为前端集成 HTML、CSS 和 SVG。如果您的需求是创建一个仪表板,您可以简单地使用您想要分析的数据并使用 D3.js 来显示它。
在这里用 D3 代码解释一个网站、网页或仪表板的例子可能有点困难,但是让我们看看 D3 提供了什么。
首先,具有美学上令人愉悦的圆形布局的关系可视化或网络流可以编码为–弦图,并且该代码的结果可以让读者赏心悦目
将负面类别堆叠在左边,正面类别堆叠在右边的图表。
用下面的图表,你可以看到层次和大小将随着你改变深度而调整。你可以在这里找到源代码。
D3 有大量的情节,你很少需要从头开始编码。你可以选择任何情节,做你想要的改变。尽管毫无疑问你将不得不写很多代码,但是更多的代码意味着更大的灵活性。
优势
- D3 是灵活的,它不提供特定的特性,并且让你完全控制创建你选择的可视化。
- 高效,可以处理大型数据集。
- D3 是数据驱动的文档,这使得它更适合数据可视化,是数据可视化的最佳工具。
- 它配有大约 200k 的视觉效果。
不足之处
- 它应该用于在线分析。
- 生成一个 D3 可视化是非常耗时的。
- 由于语法复杂,它有一个陡峭的学习曲线。
- 不能用于笔记本电脑,仅专注于基于网络的分析。
Bokeh 是一个 Python 数据可视化库,允许用户生成交互式图表和绘图。类似于 plotly,因为这两个库都允许您创建 JavaScript 支持的图表和绘图,而无需编写任何 JS 代码。Bokeh 像 plotly 和 D3.js 一样给出主动交互支持,像缩放、平移、选择、保存剧情。
Bokeh 有两个不同的接口/层,这让开发人员可以根据他们的需要和他们想花多少时间编码来组合它们。下面我们通过一些例子来了解一下这些接口的区别和用法。
散景模型
这为开发人员提供了一个底层接口。可以通过设置各种属性的值来配置图表。这样,开发人员可以根据需要操作属性。
from bokeh.models import HoverTool
hover = HoverTool(
tooltips=[
("(x,y)", "($x, $y)"),
]
)
p = figure(plot_width=400, plot_height=400, tools=[hover])
p.triangle([5, 3, 3, 1, 10], [6, 7, 2, 4, 5], size=[10, 15, 20, 25, 30], color="blue")
show(p)
散景.绘图
在这个界面中,你可以自由地通过组合视觉元素来创建情节:圆形、三角形、线条等。,并添加交互工具:缩放、跨越等。交互元素将在 bokeh.model 的帮助下添加。
from bokeh.io import output_notebook, show
from bokeh.plotting import figure
output_notebook()
p = figure(plot_width=400, plot_height=400)
p.triangle([5, 3, 3, 1, 10], [6, 7, 2, 4, 5], size=[10, 15, 20, 25, 30], color="blue")
show(p)
还有一个叫做 bokeh.chart 的界面,它有预建的视觉效果,比如折线图、条形图、面积图、热图,但它已经被弃用了。
在许多方面,散景都是数据可视化的一个好选择,因为它为您提供了 Matplotlib 的简单性和使您的图表更具交互性的选项。
优势
- 它提供了一个低级界面的选择,开发者/分析师将有更大的灵活性来改变图形。
- 允许您转换 Matplotlib、ggplot.py 和 seaborn 的图表和绘图。
- 互动剧情。
- 可以将图导出为 PNG 和 SVG 文件格式。
- 散景产生不同格式的输出–html、笔记本和服务器。
不足之处
- 提供有限的交互选项。
- 还没有一个大的支持社区,正在经历许多开发。
- 没有 3D 图形功能。
- 您必须在创建任何图之前定义输出模式,即。笔记本电脑、服务器和网络浏览器模式。
Altair 是一个声明式数据可视化库。它构建在 vega lite 上,允许您通过定义 JSON 格式的属性来创建数据分析的可视化。你不用写任何 json 声明,而是 Python。Altair 将输入转换为 vega lite 的字典格式。
它基本上是 vega lite 的 Python 接口。Altair 支持图表定义中的数据转换。
Altair 提供内置图表。条形图,折线图,面积图,直方图,散点图等。让我们画一些图来看看 Altair 如何帮助我们通过视觉来探索数据。
import altair as alt
import pandas as pd
source = pd.DataFrame({
'a': ['Col1', 'Col2', 'Col3','Col4', 'Col5', 'Col6'],
'b': [28, 55, 43, 50, 30, 99]
})
alt.Chart(source).mark_bar().encode(
x='a',
y='b'
)
您可以看到 Altair 为您提供了保存图像、查看源(数据)和在 vega 中编辑图表的选项。当您在 vega 编辑器中打开图表时,您将看到以下内容。
您的 Python 代码将被翻译成 JSON 格式,以便您在 vega 中使用它。Altair 提供的不仅仅是简单的图表,它允许您组合两个图表并在它们之间创建依赖关系。
优势
- 简单易用,因为它建立在 vega lite 可视化语法之上。
- 产生有效且吸引人的可视化效果只需要最少的代码。
- 为您提供了在 vega lite 中编辑图形的选项。
- 让您专注于理解数据,而不是纠结于显示数据。
不足之处
- 提供交互式图表,但与大多数工具不在同一级别。
- 不支持三维可视化。
YellowBrick 是一个机器学习可视化库,有两个主要依赖项:Scikit learn 和 Matplotlib。它高度关注特征工程和评估 ML 模型性能。它具有以下可视化功能:
- 特征可视化器–异常值、数据分布、降维、等级特征
- 目标可视化器–训练数据中的特征相关性、类别平衡
- 回归可视化工具–残差图、预测检查、参数选择
- 分类可视化工具——ROC、AUC、混淆矩阵
- 聚类可视化工具–肘方法、距离图、轮廓
- 模型选择–交叉验证、学习曲线、功能重要性、功能消除
- 文本建模可视化工具——标记频率、语料库分布、离差图
- 非 scikit 的可视化工具–缺失值,散点图
该列表可以帮助您确定哪个图/实用程序应该用于哪种需求。为了更好地了解 YellowBrick,我们来看一些例子。
from sklearn.tree import DecisionTreeClassifier
from yellowbrick.features import FeatureImportances
clf = DecisionTreeClassifier()
viz = FeatureImportances(clf)
viz.fit(X_sample, y_sample)
viz.poof()
看起来 YellowBrick 是数据建模之前、期间和之后的数据探索的结合。这是一个真正意义上的数据探索工具。
优势
- 它使许多工作更容易,如功能选择,超参数调整,或模型评分。
- 在 Yellowbrick 的帮助下,数据科学家可以快速轻松地评估他们的模型。
- 唯一进行模型可视化的可视化工具。
不足之处
- 不支持交互式可视化。
- 不支持三维绘图。
Folium 是一个用于可视化地理空间数据的 Python 库,是 js 库 fleed . JS 的包装器。fleed . JS 是一个用于交互式地图的开源 JS 库。follow 采用了 Python 的数据角力和 fleet . js 的映射特性。
该库使用来自 OpenStreetMap、MapBox、Cloudmade API 的 tilesets。您可以通过添加切片图层、绘制标记、显示方向来自定义地图。在插件的帮助下,Folium 确实可以帮助开发者轻松创建定制地图。
在地图上可视化地理空间数据有助于更好地理解数据。您可以获得位置数据点的可视化表示,并且它们很容易与世界联系起来。像许多疾病案例一样,在地图上显示国家、州和城市的信息有助于更容易地包含信息。
让我们用叶子画出我们的第一张地图,看看它有多简单。
import folium
from folium.plugins import MarkerCluster
m = folium.Map(location=[28.7041, 77.1025], zoom_start=10)
popup = "Delhi"
marker = folium.Marker([28.7041, 77.1025], popup=popup)
m.add_child(marker)
m
只需输入纬度和经度,我们就能画出地图并标记出来。让我们来看看,当您可以以不同格式查看地图时,我们如何添加功能。让我们添加瓷砖层。
import folium
from branca.element import Figure
from folium.plugins import MarkerCluster
popup = "Delhi"
fig=Figure(width=500,height=300)
m = folium.Map(location=[28.7041, 77.1025])
fig.add_child(m)
folium.TileLayer('Stamen Terrain').add_to(m)
folium.TileLayer('Stamen Toner').add_to(m)
folium.TileLayer('Stamen Water Color').add_to(m)
folium.LayerControl().add_to(m)
m
Folium 让开发者更容易避免使用谷歌地图、在地图上放置标记和显示方向的麻烦。在 leav 中,你可以只导入几个库,画一个地图,然后专注于输入和理解数据。
Tableau 是最好的数据可视化工具之一。组织、管理、可视化和理解数据极其容易。它有简单的拖放功能,但也有工具可以帮助发现模式和发现数据的洞察力。
使用 Tableau,您可以创建一个仪表板,它只不过是不同视觉效果的集合。仪表板就像一个故事板,您可以在其中包含多个图,使用各种布局和格式,并轻松启用过滤器来选择特定数据。例如,您可以创建一个仪表板来检查品牌营销活动的表现。
在 Python 中集成不同类型的数据源可能需要大量的编码和工作,但使用 Tableau 这样的商业智能工具,这将是一项点击式的工作。它有许多数据连接器,如 Amazon Athena、Redshift、Google Analytics、Salesforce 等。
这是一个商业智能工具,对管理数据的支持有限,但它允许分析师使用 Python 或 r。通过使用脚本编程,分析师可以向 Tableau 提供干净的数据,并创建更好的视觉效果。要将 Python 与 Tableau 联系起来,你可以在 Tableau 的网站上查看这个博客。
这是一个典型的 Tableau 仪表板的例子,它看起来不像一个剪报吗?
优势
- Tableau 可以轻松处理大型数据集,同时还能提供更快的计算速度。
- 它有大量的图表。
- 它的效率,你的阴谋往往只是几个点击。
- 允许您结合 Python 来执行复杂的任务并改进可视化。
- 支持各种数量的数据源。
- 有网页版和桌面版。
不足之处
- 桌面版可能很贵。
- Tableau 的网页版是公开的,这可能会引起一些安全问题。
- 当您处理通过 http 请求的数据时,比如 xml、JSON,这可能是一个挑战。
结论
市场上有许多工具和库,我们根据自己的需求、能力和预算来选择它们。在整篇文章中,我讨论了一些用于数据探索和可视化的最佳工具。这些工具中的每一个都有自己的最佳方式,它们有自己的系统和结构来更深入地挖掘数据并理解数据。
数据探索对于业务、管理和数据分析师来说非常重要。没有探索,你会经常发现自己处于盲点。所以,在你做任何重大决定之前,分析可能发生的事情,或者过去发生的事情是一个好主意。换句话说,可视化您的数据以做出更好的决策。
如何进行图像分割和物体检测的数据探索(我不得不艰难地学习的东西)| Neptune 博客
多年来,我一直在研究对象检测和图像分割问题。我的一个重要认识是,人们不会像通常在任何其他非图像机器学习项目中那样,在数据探索和结果分析上投入同样多的努力和重视。
为什么会这样?
我认为有两个主要原因:
- 人们没有深入理解对象检测和图像分割模型并将它们视为黑盒,在这种情况下,他们甚至不知道要看什么和假设是什么。
- 从技术的角度来看,这可能相当乏味,因为我们没有好的图像数据探索工具。
在我看来,图像数据集并不是一个例外,了解如何调整系统以匹配我们的数据是成功的关键一步。
在这篇文章中,我将与你分享我如何处理图像分割和对象检测问题的数据探索。具体来说:
- 为什么你应该关心图像和物体的尺寸,
- 为什么小对象会成为许多深度学习架构的问题,
- 为什么解决阶级不平衡会很难,
- 为什么一个好的可视化值一千个指标,
- 数据扩充的陷阱。
需要对图像分割和目标检测进行数据探索
数据探索是许多机器学习过程的关键。也就是说,当涉及到对象检测和图像分割数据集时,没有直接的方法来系统地进行数据探索。
使用常规影像数据集与使用对象和分割数据集有许多不同之处:
- 标签与图像紧密结合。突然之间,你不得不小心对待你的图像,因为它会破坏图像-标签-映射。
- 通常每个图像有更多的标签。
- 更多的超参数来调整(特别是如果您在自定义数据集上训练的话)
这使得评估、结果探索和错误分析更加困难。您还会发现,为您的系统选择一个单一的性能指标可能相当棘手——在这种情况下,手动探索可能仍然是一个关键步骤。
数据质量和常见问题
在处理任何机器学习问题(包括图像分割、对象检测)时,你应该做的第一件事是评估质量和理解你的数据。
训练对象检测和图像分割模型时常见的数据问题包括:**
- 图像尺寸和长宽比(特别是处理极值)
- 标签构成–不平衡、边界框大小、长宽比(例如许多小对象)
- 数据准备不适合您的数据集。
- 建模方法与数据不一致。
如果你在与 COCO 等典型基准数据集显著不同的定制数据集上训练,这些将特别重要。在接下来的章节中,我将向您展示如何发现我提到的问题以及如何解决它们。
一般数据质量
这个步骤很简单,也很明显,而且这个步骤对于所有的图像问题都是一样的,不仅仅是物体检测或者图像分割。我们现在需要做的是:
- 获得数据集的总体感觉,并对其进行视觉检查。
- 确保它没有损坏,并且不包含任何明显的伪像(例如,只有黑色的图像)
- 确保所有的文件都是可读的——你不会想在培训过程中发现这一点的。
我的建议是尽可能多的想象图片。有多种方法可以做到这一点。根据数据集的大小,有些数据集可能比其他数据集更合适。
- 使用 matplotlib 在 jupyter 笔记本中绘制它们。
- 使用专用工具,如 google facets 来探索图像数据
- 使用 HTML 渲染在笔记本中可视化和浏览。
我是最后一个选项的超级粉丝,它在 jupyter 笔记本上非常好用(甚至可以同时处理成千上万张图片!)尝试用 matplotlib 做这件事。还有更多:你可以安装一个悬停缩放扩展,允许你放大到单个图片,以高分辨率进行检查。
Fig 1. 500 coco pictures visualized using html rendered thumbnails
图像尺寸和长宽比
在现实世界中,数据集不太可能包含相同大小和纵横比的图像。检查基本数据集纵横比、图像宽度和高度等统计数据将帮助您做出重要决策:
你能和你应该吗?做破坏性的大小调整?(破坏性意味着改变 AR 的大小调整)
对于非破坏性的调整大小,你想要的输出分辨率和填充量应该是多少?
深度学习模型可能有你必须根据上述调整的超参数(例如锚点大小和比率),或者它们甚至可能对最小输入图像大小有很强的要求。
一个特例是,如果你的数据集包含非常大的图像 (4K+),这在卫星图像或某些医学模式中并不罕见。对于 2020 年的大多数尖端型号,由于内存限制,每个(服务器级)GPU 甚至无法容纳一个 4K 映像。在这种情况下,您需要弄清楚什么实际上对您的 DL 算法有用。
我看到的两种方法是:
- 在图像补片上训练您的模型(在训练期间随机选择或在训练前提取)
- 调整整个数据集的大小,以避免每次加载数据时都这样做。
Fig 2. Histogram of image aspect ratios in the coco dataset
总的来说,我认为大多数数据集属于 3 类中的一类。
- 均匀分布,其中大部分图像具有相同的尺寸–这里你唯一要做的决定是调整多少大小(如果有的话),这主要取决于对象的面积、大小和长宽比)
- 略微呈双峰分布,但大多数图像的纵横比在(0.7 … 1.5) 范围内,类似于 COCO 数据集。我相信其他“看起来很自然”的数据集也会遵循类似的分布——对于那些类型的数据集,你应该可以使用非破坏性的调整大小- >填充方法。填充是必要的,但要达到可管理的程度,并且不会使数据集变得太大。
- 具有大量极值的数据集(非常宽的图像与非常窄的图像混合)–这种情况要复杂得多,有更先进的技术来避免过度填充。您可以考虑根据长宽比对成批图像进行采样。请记住,这可能会给您的采样过程带来偏差——因此,请确保它是可接受的或不够强。
mmdetection 框架通过实现一个基于 AR 采样的 GroupSampler 来支持这一点
图 3 和图 4。coco 数据集中具有极限纵横比的示例图像(调整大小并填充)
标签(物体)大小和尺寸
这里我们开始看我们的目标(标签)。我们尤其想知道尺寸和长宽比是如何分布的。
为什么这很重要?
根据你的建模方法**,大多数框架都有设计限制**。正如我前面提到的,这些模型旨在在基准数据集上表现良好。如果由于某种原因你的数据不同,训练他们可能是不可能的。让我们从 detectron2 来看看 Retinanet 的默认配置:
ANCHOR_GENERATOR:
SIZES: !!python/object/apply:eval ["[[x, x * 2**(1.0/3), x * 2**(2.0/3) ] for x in [32, 64, 128, 256, 512 ]]"]
你可以看到,对于不同的特征图,我们生成的锚点会有一定的大小范围:
- 例如,如果您的数据集只包含非常大的对象,那么可能会大大简化模型,
- 另一方面,让我们假设你有带有小对象的小图像(例如 10x10px ),在这种配置下,你可能无法训练模型。
当涉及到盒子或遮罩尺寸时,要考虑的最重要的事情是:
- 宽比
- 尺寸(面积)
Fig 5. aspect ratio of bounding boxes in the coco dataset
这个分布的尾部(图 3)相当长。会有极端纵横比的情况。根据用例及数据集的不同,忽略它或不忽略它都可以,这需要进一步检查。
Fig 6. Mean area of bounding box per category
对于基于锚的模型(大多数对象检测/图像分割模型)来说尤其如此,其中存在将基础事实标签与预定义的锚框(aka。先前的方框)。
请记住,您使用超参数来控制这些先前的盒子是如何生成的,比如盒子的数量、它们的纵横比和大小。毫不奇怪,您需要确保这些设置与您的数据集分布和预期一致。
Fig 7. The Image shows anchor boxes at different scales and aspect ratios.
需要记住的一件重要事情是,标签将与图像一起转换。因此,如果在预处理步骤中缩小图像,ROI 的绝对尺寸也会缩小。
如果你觉得对象大小可能是你的问题中的一个问题,并且你不想把图像放大太多(例如为了保持期望的性能或内存占用)你可以尝试用裁剪>调整大小的方法来解决这个问题。请记住,这可能是相当棘手的(你需要处理的情况下会发生什么,如果你切过一个边界框或分割掩模)
另一方面,从建模的角度来看,大对象通常不会有问题(尽管你仍然必须确保它与锚点匹配)。它们的问题更加间接,本质上一个类的对象越大,它在数据集中就越有可能被低估。大多数情况下,给定类别中对象的平均面积与(标签)数量成反比。
部分标记的数据
当创建和标记图像检测数据集时,缺少注释是一个潜在的大问题。最糟糕的情况是,你的基本事实中已经有了假阴性。所以本质上你没有注释对象,即使它们存在于数据集中。
在大多数建模方法中,没有被标记或者与锚点不匹配的一切都被认为是背景。这意味着它会产生相互矛盾的信号,这将对学习过程造成很大伤害。
这也是为什么您不能真正将数据集与非重叠类混合并训练一个模型的原因(尽管有一些混合数据集的方法——例如,通过将一个数据集软标记为在另一个数据集上训练的模型)
Fig 8. Shows the problem of mixing datasets – notice for example that on the right image a person is not labeled. One way to solve this problem is to soft label the dataset with a model trained on the other one. Source
失衡
当涉及到对象检测时,类不平衡可能是一个小问题。例如,通常在图像分类中,可以容易地对数据集进行过采样或下采样,并控制每个类对损失的贡献。
Fig 9. Object counts per class
您可以想象,当您有共现类对象检测数据集时,这更具挑战性,因为您不能真正丢弃一些标签(因为您会发出关于背景是什么的混合信号)。
在这种情况下,您最终会遇到与部分标记的数据段落中所示相同的问题。一旦开始在图像级别上进行重采样,您必须意识到多个类将同时被上采样。
注意:
您可能想尝试其他解决方案,如:
- 增加损失的权重(使一些框或像素的贡献更高)
- 以不同的方式预处理数据:例如,您可以进行一些自定义裁剪,在对象级别重新平衡数据集
理解增强和预处理序列
预处理和数据扩充是任何计算机视觉系统不可或缺的一部分。如果你做得好,你可以获得很多,但如果你搞砸了,它真的会让你付出代价。
数据扩充是迄今为止最重要和最广泛使用的正则化技术(在图像分割/对象检测中)。
将其应用于对象检测和分割问题比简单的图像分类更具挑战性,因为一些变换(如旋转或裁剪)不仅需要应用于源图像,还需要应用于目标图像(遮罩或边界框)。需要目标转换的常见转换包括:
- 仿射变换,
- 裁剪,
- 扭曲,
- 缩放,
- 旋转
- 还有很多。
对成批的增强图像和目标进行数据探索以避免代价高昂的错误(丢弃边界框等)是至关重要的。
注意:
基本增强是 PyTorch 或 Tensorflow 等深度学习框架的一部分,但如果你需要更高级的功能,你需要使用 python 生态系统中可用的增强库之一。我的建议是:
最小预处理设置
每当我构建一个新系统时,我都希望它在预处理和增强层面上保持非常基础,以最小化早期引入 bug 的风险。我建议你遵循的基本原则是:
- 禁用增强
- 避免破坏性的大小调整
- 务必目视检查输出
让我们继续 COOC 的例子。从前面的步骤中我们知道:
我们的大多数图像具有:
- 纵横比=宽度/高度= 1.5
- 平均 avg _ width = 600,avg_height = 500。
将平均值设置为我们的基本预处理调整大小值似乎是一件合理的事情(除非模型方面强烈要求具有更大的图片),例如,resnet50 主干模型的最小大小要求为 32×32(这与下采样层数有关)
在 Albumentations 中,基本的设置实现如下所示:
- longest maxsize(avg _ height)–这将基于最长的边重新缩放图像,保持纵横比
- PadIfNeeded(avg_height,avg_width,border_mode='FILL ',value=0)
图 10 和 11。MaxSize - >为两个长宽比相差很大的图片填充输出
正如你在图 10 和 11 中看到的,预处理产生了一个 500×600 的图像,两个图片都有合理的 0 填充。
当您使用填充时,有许多选项可以填充空白空间。在基本设置中,我建议您使用默认常量 0 值,
当你尝试更高级的方法时,比如反射填充,总是在视觉上探索你的增强。记住,你正在冒引入假阴性的风险,尤其是在对象检测问题中(反映一个没有标签的对象)
Fig 12. Notice how reflection-padding creates false negative errors in our annotations. The cat’s reflection (top of the picture) has no label!
增强-旋转
旋转是强大而有用的补充,但应该谨慎使用。请看图 13。下面是使用 Rotate(45)->Resize->Pad 管道生成的。
Fig 13. Rotations can be harmful to your bounding box labels
问题是,如果我们使用标准的边界框(没有角度参数),覆盖一个旋转的对象可能效率较低(框面积对对象面积将增加)。**这种情况发生在旋转增强期间,可能会损坏数据。**请注意,我们还在左上角引入了假阳性标签。这是因为我们对图像进行了裁剪旋转。
我的建议是:
- 如果你有很多长宽比远非 1 的对象,你可能要放弃这些。
你可以考虑的另一件事是使用 90,180,270 度的非裁剪旋转(如果它们有意义的话)来解决你的问题(它们不会破坏任何边界框)
补充——关键要点
如您所见,空间变换可能相当棘手,可能会发生许多意想不到的事情(尤其是对于对象检测问题)。
因此,如果您决定使用这些空间增强,请确保进行一些数据探索,并直观地检查您的数据。
注意:
你真的需要空间扩增吗?我相信在很多情况下,你不需要它们,像往常一样让事情变得简单,逐渐增加复杂性。
根据我的经验,对于自然外观的数据集(类似于 coco ),以下管道是一个很好的起点(没有空间变换):
transforms = [
LongestMaxSize(max_size=500),
HorizontalFlip(p=0.5),
PadIfNeeded(500, 600, border_mode=0, value=0),
JpegCompression(quality_lower=70, quality_upper=100, p=1),
RandomBrightnessContrast(0.3, 0.3),
Cutout(max_h_size=32, max_w_size=32, p=1)
]
当然,像 max_size 或 cutout sizes 这样的东西是任意的,必须进行调整。
Fig 14. Augmentation results with cutout, jpeg compression and contrast/brightness adjustments
最佳实践:
有一件事我还没有提到,但我觉得很重要:总是加载整个数据集(连同你的预处理和增强管道)。
%%timeit -n 1 -r 1
for b in data_loader: pass
两行代码,会节省你很多时间。 首先,您将了解数据加载的开销是多少,如果您发现明显的性能瓶颈,您可能会考虑立即修复它。更重要的是,您将发现以下潜在问题:
- 损坏的文件,
- 无法转换的标签等
- 任何可能中断训练的可疑情况。
结果理解
对于这些类型的问题,检查模型结果和执行错误分析可能是一个棘手的过程。只有一个指标很难告诉你事情的全部,如果你有一个指标,解释它可能是一个相对困难的任务。
让我们来看看官方的 coco challenge 和那里的评估过程(我将展示的所有结果都是针对 resnet50 主干的 MASK R-CNN 模型)。
Fig 15. Coco evaluation output
它返回由 IOU(预测值和实际值的交集)和面积划分的各组观察值的 AP 和 AR。因此,即使是官方的 COCO 评价也不仅仅是一个指标,这是有充分理由的。
让我们重点关注 IoU=0.50:0.95 符号。
**这意味着:AP 和 AR 计算为不同 IoU 设置(从 0.5 到 0.95,步长为 0.05)计算的精度和召回的平均值。**我们在这里得到的是一个更健壮的评估过程,在这种情况下,如果一个模型在两方面(定位和分类)都很好,它就会得到高分
当然,您的问题和数据集可能不同。也许你需要一个极其精确的检波器,在这种情况下,选择 AP@0.90IoU 可能是个好主意。
(coco eval 工具的)缺点是,默认情况下,所有类和所有图像的所有值都是平均的。这在类似竞赛的设置中可能没问题,在这种设置中,我们希望评估所有类上的模型,但是在现实生活中,当您在自定义数据集(通常只有较少的类)上训练模型时,您真的想知道您的模型在每个类的基础上表现如何。
查看每个职业的指标非常有价值,因为它可能会给你重要的见解:
- 帮助您更好地构建新数据集
- 在数据扩充、数据采样等方面做出更好的决策。
Fig 16. Per class AP
图 16。给你很多有用的信息,你可能会考虑一些事情:
- 向低性能类添加更多数据
- 对于得分较高的类,也许您可以考虑对它们进行降采样,以加快训练速度,并可能有助于其他不太频繁的类的性能。
- 找出任何明显的相关性,例如小对象表现不佳的类。
可视化结果
好的,如果只看单一指标还不够,你应该怎么做?
我肯定会建议花一些时间进行手动结果探索,结合来自之前分析的硬指标——可视化将有助于您了解全局。
由于探索图像检测和图像分割模型的预测可能会变得相当混乱,我建议你一步一步来。在下面的 gif 上,我展示了如何使用 coco inspector 工具来实现这一点。
Fig 17. All the predictions and ground-truths visualized
在 gif 上,我们可以看到所有重要信息是如何可视化的:
- 红色面具——预测
- 橙色遮罩-预测和地面真相遮罩的重叠
- 绿色面具-地面真相
- 虚线边界框–误报(没有匹配的预测)
- 橙色方框真阳性
- 绿色盒子——基本事实
结果理解–每幅图像得分
通过观察硬性指标和视觉检查图像,我们很可能对正在发生的事情有一个很好的了解。但是查看随机图像的结果(或按类别分组)可能不是最佳的方式。如果你真的想深入研究并发现你的模型的边缘情况,我建议计算每个图像的度量(例如 AP 或 Recall)。
下面是我通过这样做找到的一张图片的例子。
Fig 18. Image with a very low AP score
在上面的例子中(图 18。)我们可以看到两个错误的肯定停止标志预测——由此我们可以推断,我们的模型理解停止标志是什么,但不理解其他交通标志是什么。
也许我们可以向我们的数据集添加新的类,或者使用我们的“停止标志检测器”来标记其他交通标志,然后创建一个新的“交通标志”标签来解决这个问题。
Fig 19. Example of an image with a good score > 0.5 AP
有时我们还会了解到,我们的模型做得比单从分数上看起来更好。这也是有用的信息,例如,在上面的示例中,我们的模型检测到笔记本电脑上有一个键盘,但这实际上在原始数据集中没有标记。
COCO 格式
起初,coco 数据集的组织方式可能有点吓人。
它由一组相互映射的字典组成。它还打算与 pycocotools / cocotools 库一起使用,后者在数据集元数据文件之上构建了一个相当混乱的 API。
尽管如此,coco 数据集(和 coco 格式)成为组织对象检测和图像分割数据集的标准方式。
在 COCO 中,我们遵循边界框编码的 xywh 惯例,或者我喜欢称之为 tlwh : (左上宽高),这样你就不会把它和例如 cwh : **(中心点,w,h)混淆。**掩码标签(分段)是游程编码的( RLE 解释)。
Fig 20. The coco dataset annotations format
拥有一个被广泛采用的标准仍然有非常重要的优势:
- 标注工具和服务导出和导入 COCO 类数据集
- 评估和评分代码(用于 coco 竞赛)已经过很好的优化和实战测试。
- 多个开源数据集紧随其后。
在前一段中,我使用了 COCO eval 功能,这是遵循 COCO 标准的另一个好处。为了利用这一点,您需要以构建 coco 数据集的相同方式格式化您的预测,然后计算指标就像调用:COCOeval(gt_dataset,pred_dataset)一样简单
COCO 数据集资源管理器
为了简化数据和结果探索的过程(尤其是对象检测),我写了一个在 COCO 数据集上操作的工具。
本质上,您为它提供基础真实数据集和预测数据集(可选),它将为您完成其余工作:
- 计算我在这篇文章中提出的大部分指标
- 轻松可视化数据集地面真相和预测
- 检查 coco 指标,每类 AP 指标
- 检查每个图像的分数
要使用 COCO 数据集资源管理器工具,您需要:
git clone https://github.com/i008/COCO-dataset-explorer.git
- 下载我在示例中使用的示例数据或使用您自己的 COCO 格式的数据:
如果您下载了示例数据,您将需要提取它。
tar -xvf coco_data.tar
您应该具有以下目录结构:
COCO-dataset-explorer
|coco_data
|images
|000000000139.jpg
|000000000285.jpg
|000000000632.jpg
|...
|ground_truth_annotations.json
|predictions.json
|coco_explorer.py
|Dockerfile
|environment.yml
|...
- 设置包含所有依赖项的环境
conda env update;
conda activate cocoexplorer
- 运行 streamlit 应用程序,在 COCO 格式和图像目录中指定包含地面实况和预测的文件:
streamlit run coco_explorer.py -- \
--coco_train coco_data/ground_truth_annotations.json \
--coco_predictions coco_data/predictions.json \
--images_path coco_data/images/
**注意:**您也可以使用 docker:
sudo docker run -p 8501:8501 -it -v "$(pwd)"/coco_data:/coco_data i008/coco_explorer \
streamlit run coco_explorer.py -- \
--coco_train /coco_data/ground_truth_annotations.json \
--coco_predictions /coco_data/predictions.json \
--images_path /coco_data/images/
最后的话
我希望通过这篇文章,我让你相信对象检测和图像分割中的数据探索与机器学习的任何其他分支一样重要。
我相信我们在项目这一阶段所做的努力最终会有回报的。
我们收集的知识使我们能够做出更明智的建模决策,避免多重训练陷阱,并使您对训练过程和模型产生的预测更有信心。
阅读下一篇
Python 中的图像处理:你应该知道的算法、工具和方法
9 分钟阅读|作者 Neetika Khandelwal |更新于 2021 年 5 月 27 日
图像定义了世界,每张图像都有自己的故事,它包含了许多在许多方面都有用的重要信息。这些信息可以借助于被称为图像处理的技术来获得。
它是计算机视觉的核心部分,在机器人、自动驾驶汽车和物体检测等许多现实世界的例子中起着至关重要的作用。图像处理允许我们一次转换和操作数千幅图像,并从中提取有用的见解。它在几乎每个领域都有广泛的应用。
Python 是为此目的广泛使用的编程语言之一。它惊人的库和工具有助于非常有效地完成图像处理任务。
通过本文,您将了解处理图像并获得所需输出的经典算法、技术和工具。
让我们开始吧!
如何解决 MLOps 堆栈的数据接收和功能存储组件
正如数据科学领域的每个从业者所知,数据 是机器学习的主要燃料。值得信赖的数据源和高质量的数据收集和处理可以支持大量潜在的 ML 用例。但是拥有一个治理良好的数据仓库需要组织中的每个团队全心全意地照顾和管理他们产生、摄取、分析或利用的每个数据点。数据质量责任分散到每个人身上。它不仅仅依赖于数据工程团队。
Main properties of Data Quality | Source
如今组织中最常见的数据架构是 Lambda 架构。它的特点是有独立的批处理和流管道将数据接收到数据湖中,数据湖由一个着陆或原始阶段组成,其中 ELT 进程转储原始数据对象,如事件或数据库记录转储。
这些原始数据随后被接收到更有组织的数据湖表(例如 Parquet 文件)中,然后被充实到数据仓库中。进入数据仓库的数据是不同业务领域的逻辑组织信息,称为数据集市。这些数据集市很容易被数据分析师查询和被业务涉众探索。每个数据集市可以与不同的业务单元或产品领域相关联(营销、订阅、注册、产品、用户…) 。
Example of a typical Data Architecture in Google Cloud Platform | Source
还有其他的参考架构模式,例如, Kappa 或 Delta,后者得到了商业产品的大量支持,例如【】Databricks 和【】Delta Lake 。
这些基础数据架构模式为分析工作负载铺平了道路。 OLAP 大数据数据库和处理引擎,如 Spark 和 Dask 等,已经实现了存储和计算硬件的解耦,允许数据从业者与海量数据进行交互,以进行数据分析和数据科学。
随着 MLOps 、DataOps 的兴起,以及软件工程在生产机器学习中的重要性,出现了不同的创业公司和产品来解决服务特征的问题,如 Tecton 、 HopsWorks 、盛宴、 SageMaker 特征店、 Databricks 特征店、顶点 AI 特征店
此外,每个大规模从事生产数据科学的公司,如果没有使用前面提到的工具之一,都已经建立了自己的内部功能商店(例如,优步是第一个发布自己构建 ML 平台方法的公司,随后是 Airbnb)。
在本文中,我们将解释特性商店解决的一些概念和问题,就像它是一个内部平台一样。这是因为我们认为理解底层组件以及它们之间的概念和技术关系更容易。我们不会深究商业产品。
我们还将讨论构建和购买之间的紧张关系,这是当今业界从业者的热门话题,以及实现这一决策的最佳方式。
什么是功能商店?
去年,一些博客和 ML 世界中有影响力的人将 2021 命名为功能商店年。我们将在下一节讨论这背后的原因。但是,什么是功能商店呢?
Featurestore.org给出的简短定义是:
“一个用于机器学习的 数据管理层 ,允许共享&发现功能并创建更有效的机器学习管道。”
这很准确。简单地扩展一些细节,特征库由一组技术、架构、概念和语义组件组成,这些组件使 ML 从业者能够创建、摄取、发现和获取用于进行离线实验和开发在线生产服务的特征。
功能存储的组件
Components of a feature store | Source
我们应该开始定义什么是特征向量,因为它是特征库处理的核心实体。
- 特征向量:这是一个数据元素,包含一个实体标识符和一组在某个时间点描述该元素的属性或特征。例如,实体标识符可以是一个用户 ID ,并且属性可以包含以下值:(时间 _ 自 _ 注册、n _ 购买、ltv _ 值、is _ 免费 _ 试用、平均 _ 购买 _ 每月、累计 _ 购买、最后 _ 购买 _ts 等)
现在,我们来解释托管这些特征向量的不同存储组件:
**离线存储:**这是一个分析数据库,可以接收、存储和提供离线工作负载的特征向量,如数据科学实验或批量生产作业。通常,每一行都包含一个由实体 ID 和给定时间戳唯一标识的特征向量。这个组件通常具体化为 S3、红移、BigQuery、Hive 等。
**在线商店:**也称为热数据,该存储层旨在为低延迟预测服务提供功能。该数据库现在用于以毫秒级速度提取要素。Redis、DynamoDB 或 Cassandra 是扮演这一角色的常见候选人。键值数据库是最好的选择,因为在运行时不经常需要复杂的查询和连接。
**特征目录或注册表:**理想情况下,这是一个很好的 UI,可以发现特征和训练数据集。
特性商店 SDK: 这是一个 Python 库,抽象了线上和线下商店的访问模式。
**元数据管理:**该组件用于跟踪来自不同用户或管道的访问、摄取过程、模式更改以及这类信息。
离线和在线服务 API: 这是一个代理服务,位于 SDK 和在线及功能硬件之间,以方便功能访问。
在下面的时间顺序图中,我们可以看到自 2017 年优步发布其著名的米开朗基罗以来围绕 feature store 的关键里程碑的总结。几年后,在几个商业和操作系统产品推出后,我们已经看到行业从业者广泛接受了功能商店的概念。一些组织如 featurestore.org 的 T2 和 T4 的 mlops.community 应运而生。
Feature Store Milestones | Source
在与 MLOps 的关系中,特性存储本身受到影响,并影响堆栈的其他组件,如数据仓库、数据湖、数据作业调度程序、生产数据库等。也是。我们将在后面详细讨论这种关系,即功能商店在 MLOps 框架的大图中处于什么位置?
现在,让我们讨论一下 ML 工程师在产品特征工程方面面临的一些主要问题。
围绕功能商店的争论
特征摄取和获取的标准化
在存在适当的要素存储之前,每个数据科学团队使用非常不同的工具存储和获取要素。这些工作传统上被视为数据工程管道的一部分。因此,围绕这些工作的库、SDK 和工具是数据工程师使用的。根据团队的专业知识、成熟水平和背景,他们可以是非常多样化的。
例如,您可以在同一组织中看到以下情况:
- 团队 A: 团队对数据工程不是很了解。他们使用裸露的熊猫和带有 psycopg 连接器的 SQL 脚本在 Redshift 中存储离线特性,使用 boto 在 DynamoDb 中存储在线特性。
- 团队 B: 团队成熟,自主。他们建立了一个库,使用 sqlalchemy 或 PySpark 进行大数据作业,抽象出与几个数据源的连接。他们还有自定义的包装器,用于向 DynamoDb 和其他热门数据库发送数据。
这在大型组织中非常典型,在这些组织中,ML 团队不是完全集中的,或者 ML 跨团队不存在。
在不同项目中使用相同数据库的团队倾向于围绕它们构建包装器,这样他们就可以抽象连接器并封装公共实用程序或领域定义。这个问题已经被团队 b 解决了。但是团队 A 不太熟练,他们可能会开发另一个内部库来以更简单的方式处理他们的特性。
这导致了团队之间的摩擦,因为他们想在整个组织中推行他们的工具。这也降低了团队的生产力水平,因为每个团队都在以自己的方式重新发明轮子,将开发人员与项目联系起来。
通过引入特性存储 SDK,两个团队可以利用相同的接口与 Redshift 和 DynamoDb 以及其他数据源进行交互。团队 A 的学习曲线会更陡,但他们会保持相同的操作标准。因此,总体生产率将会提高。这允许更好的特性治理。SDK 通常隐藏其他 API 调用来记录用户请求和版本数据集,允许回滚等。
大多数商业特性商店都提供特定的 SDK 来与他们的中心服务进行交互。例如,在下一个片段的中,您可以看到如何构建一个从 Feast 获取特性的数据集。
Build a dataset fetching features from Feast | Source
这不仅对标准化特色商店运营有价值,而且对抽象线上和线下商店的硬件也有价值。数据科学家不需要知道离线存储是 BigQuery 还是 Redshift 数据库。这是一个很大的好处,因为您可以根据用例、数据等使用不同的源。
时间旅行数据
如果我们想预测一个用户是否会购买一个产品,我们必须建立一个包含直到那个特定时刻的特征的数据集。我们需要非常小心不要引入未来的数据,因为这会导致 数据泄露 **。**但是如何?
如果我们将未来数据引入关于每个观察的训练数据集中,机器学习模型将学习不可靠的模式。当将模型投入实时生产时,它将无法访问相同的功能(除非你可以旅行到未来),其预测能力将会退化。
回到产品购买预测的例子,假设您想要使用关于用户的特定特征,例如,保存在购物车中的商品数量。训练数据集将包含关于看到并购买产品的用户(正标签)和看到但没有购买产品的用户(负标签)的事件。如果您想使用购物车中的商品数量作为一个特性,那么您需要专门查询那些记录在同一个会话中添加到购物车中的每个商品的事件,并且就在 purchase/seen 事件之前。
Tecton: Time Travel in ML | Source
因此,在构建这样一个数据集时,我们需要专门查询关于每个事件在那个时间点可用的特征。有必要再现事件发生的世界。
如何有一个准确的图片?
记录并等待:你只需要记录特定的特性,比如n _ cumulative _ items _ in _ the _ cart,,然后我们就可以知道用户在那个时间点有多少商品。主要的缺点是这种特性收集策略需要时间来为用例收集足够的数据点。但另一方面,实现起来也很容易。
回填 : 该技术基本上旨在在给定的时间点重建期望的特征。例如,通过查看记录的事件,我们可以在每次购买之前将所有商品添加到购物车中。然而,这可能会变得非常复杂,因为我们必须为每个要素选择时间窗口截止点。这些查询通常被称为时间点连接。
快照 : 基于定期转储生产数据库的状态。这允许在任何给定的时间点拥有特性,缺点是连续快照之间的数据更改将不可用。
用于生产的功能可用性
当一个新的 ML 用例被提出时,有经验的 ML 工程师倾向于在运行时(在线)考虑哪些特性是可用的。在大多数情况下,设计支持特性的系统是 ML 架构中最耗时的部分。
让最新的特征向量准备好被馈送给 ML 模型以进行预测不是一件容易的任务。涉及到许多组件,需要特别注意将它们粘合在一起。
生产中的特征可能来自非常不同的来源。它们可以在请求体参数中提供给算法,可以从特定的 API 中获取,从 SQL 或 NoSQL 数据库中检索,从 Kafka 主题事件中检索,从键值存储中检索,或者可以从其他数据中即时计算和导出。每一个都意味着不同程度的复杂性和资源容量。
这些来源是什么?
- 请求车身参数
这是接收用于预测的特征的最简单方式。获取这些特性并将它们传递给 ML 模型的责任被委托给推理 API Web 服务的客户或消费者。然而,这并不是最常见的特征供给方式。事实上,请求参数往往包含从其他来源获取特征向量所需的唯一标识符。这些通常是用户 id、内容 id、时间戳、搜索查询等。
- 数据库
根据特性模式和延迟的可发展性需求,特性可以存在于不同的数据库中,如 Cassandra、DynamoDb、Redis、PostgreSQL 或任何其他快速 NoSQL 或 SQL 数据库。从在线服务获取这些功能非常简单。您可以使用任何 Python 库,如用于 DynamoDb 的 boto、用于 redis 的 pyredis、用于 PostgreSQL 的 psycopg2、用于 mysql 的 mysql-connector-python、用于 cassandra 的 cassandra-driver 等等。
数据库中的每一行都有一个主键或索引,在运行时可用于每个预测请求。其余的列或值将是您可以使用的功能。
为了填写这些表格,我们可以根据要计算的特征的性质使用不同的方法:
- **批处理作业:**这些是计算密集型、繁重且“缓慢”的,这就是为什么它们只提供由它们需要多新鲜所定义的特定类型的功能。当构建不同的用例时,你会意识到不是每个模型都需要实时特性。如果你使用的是产品的平均评分,你不需要每秒计算一次平均值。像这样的大多数特征只需要一个日常计算。如果该功能需要高于 1 天的更新频率,您应该开始考虑批处理作业。
An example of a batch processing | Source
谈到常见的技术堆栈,老朋友们开始为不同的目的和规模服务:
- 气流+ DBT 或 Python 是调度和运行这些作业的良好开端。
- 如果在分布式内存方面需要更大的规模,我们可以开始考虑 Kubernetes 集群来执行 Spark 或 Dask 作业。
一些流程编排工具的替代品是 Prefect、Dagster、Luigi 或 Flyte。看看数据科学编排和工作流工具的对比。
Building ML pipeline with Feature | Source
这里有两个重要的维度需要考虑——频率和复杂度。例如,计算单个交易的“当前价格与月平均价格的标准差”既是实时的,也是复杂的汇总。
Amazon SageMaker Feature Store Streaming Ingestion | Source
除了有一个收集事件的流工具(Kafka)之外,我们还需要一个高速和可伸缩的(每秒处理任意数量的事件)功能即服务(如 AWS Lambda)来读取和处理这些事件。更重要的是,转换服务需要支持聚合、分组、连接、自定义函数、过滤器、滑动窗口,以便在给定的时间段内每隔 X 分钟或小时计算数据,等等。
特性存储在 MLOps 架构中处于什么位置?
特征库是 ML 平台的固有部分。如前所述,自从第一批 ML 车型投入生产以来,它就一直是其中的一部分,但直到几年前,这一概念才在 MLOps 世界中获得了自己的身份。
可以使用 Neptune、MLFlow 或 SageMaker Experiments 等实验跟踪工具来跟踪要素数据源。也就是说,假设您正在训练一个欺诈检测模型,并且您使用了另一个团队构建的一些共享功能。如果您将这些要素元数据记录为参数,则在跟踪实验时,它们将与您的实验结果和代码一起被版本化。
The Killer Feature Store: Orchestrating Spark ML Pipelines and MLflow for Production | Source
此外,当模型处于生产阶段时,它们成为关键部分。现场直播时,有几个组件需要同步和密切监控。如果其中一个失败,预测可能会很快降级。这些组件是功能计算和摄取管道以及来自生产服务的功能消费。计算管道需要以特定的频率运行,以便特征的新鲜度不会影响在线预测。例如:如果一个推荐系统需要知道你昨天观看的电影,那么在你再次进入媒体流服务之前,应该运行特征管道!
如何实现功能商店?
在本节中,我们将讨论不同的架构,这些架构可以针对数据科学团队的不同阶段和规模来实施。在这篇非常好的文章中,你可以看到作者如何使用需求层次来非常明确地展示哪些是你需要解决的主要问题。他将 访问 需求,包括透明性和血统,作为比 服务 更基础性的需求。我不完全同意,因为产品中的特性可用性释放了更高的商业价值。
下面给出的建议将基于 AWS 服务(尽管它们可以很容易地与其他公共云服务互换)。
最简单的解决方案
这种架构基于托管服务,托管服务需要较少的维护开销,更适合能够快速运行的小型团队。
我的初始设置是 Redshift 作为离线存储,DynamoDB 作为在线键值存储,Airflow 管理批量特征计算作业。此外,Pandas 作为两种选择的数据处理引擎。在这种架构中,所有要素计算管道都在 Airflow 中进行调度,并且需要使用 Python 脚本来接收数据,这些脚本从红移或 S3 中提取数据,对其进行转换,并将其放入 DynamoDB 以用于在线服务,然后再次放入红移以用于离线要素存储。
The initial setup | Source: author
中型功能商店
如果您已经在处理大数据、接近实时的功能需求以及跨数据科学团队的可重用性需求,那么您可能正在寻求跨功能管道的更多标准化和某种程度的可重用性。
在这种情况下,当数据科学团队规模相对较大时(比如说,超过 8-10 名数据科学家),我会建议开始使用第三方功能商店供应商。首先,我会探索 Feast,因为它是最常用的开源解决方案,并且可以在现有的基础设施上工作。您可以将 Redshift 用作离线特性存储,将 DynamoDB 或 Redis 用作在线特性存储。对于延迟要求较低的在线预测服务,后者速度更快。 Feast 将通过他们的 SDK 和网络用户界面(尽管仍处于试验阶段)帮助分类和提供功能。如果你想要一个全面管理的商业工具,我恳求你尝试一下泰克顿。
如果有大数据需求,现在可以使用普通 Python 或 Spark 开发特性计算管道,利用 Feast SDK 管理数据摄取。
Running Feast in production | Source
在这种规模下,也很可能有一些实时特性和新鲜度需求的用例。在这种情况下,我们需要一个流媒体服务,将功能直接吸收到在线功能商店中。我们可以使用 Kinesis 服务和 AWS Lambda 将特征向量直接写入 Redis 或 DynamoDB。如果需要窗口聚合,那么 Kinesis 数据分析、KafkaSQL 或 Spark Streaming 可能是合理的选择。
企业级功能商店
在这个阶段,我们假设该公司有大量的数据科学家为不同的业务或技术领域创建不同类型的模型。为这种规模的开发团队设置架构的一个关键原则是提供一个可靠的、可伸缩的、安全的、标准化的数据平台。因此,SLA、GDPR、审计和访问控制列表是必须实施的强制性要求。在每个组织规模中,这些都是需要考虑的要点,但在这种情况下,它们扮演着重要的角色。
feature store explained | Source
技术领域的大多数大公司都根据自己的需求、安全原则、现有基础设施和托管可用性建立了自己的功能商店,以避免在服务完全托管的情况下出现单点故障。
但如果情况并非如此,并且你正在运行一个公共云繁重的工作负载,那么使用 AWS SageMaker 功能商店或 GCP Vertex AI 功能商店可能是不错的选择。他们的 API 与开源产品非常相似,如果你已经在使用 SageMaker 或 Vertex,那么设置他们的特性存储服务应该很简单。
Amazon SageMaker Feature Store for machine learning | Source
Databricks 还提供嵌入式功能存储服务,这也是一个很好的选择,可以与像 MLFlow 这样的工具完美兼容。
Databricks Feature Store | Source
购买还是制造的问题
MLOps 的格局一直由脸书、网飞、优步、Spotify 等大玩家主导和塑造。这些年来,通过他们非常有影响力的工程师和博客。但是 ML 团队应该能够认识到他们在自己的组织、团队和业务领域中运作的环境。一个 20 万用户的应用程序不需要 2000 万用户的规模、标准化和僵化。这就是为什么合理规模的 m lops成为不在 FAANG 类公司工作的资深从业者的热门话题。
Explanation of a feature store | Source
谁应该建立一个功能商店?
正如本文开头所提到的,在内部构建一个类似于商店的功能平台和购买一个商业或开源产品,如 T2 盛宴、霍普斯沃斯、T3 或 T4 泰克顿 T5 之间,存在着一场持续的争斗。这种紧张关系的存在主要是因为这些产品在其架构和 SDK 中可能会有某种程度的固执己见。因此,这些工具中的大多数需要有一个中央服务来处理在线商店上的功能服务,这成为生产 ML 服务的单点故障。
此外,一些其他产品是完全 SaaS,成为一些团队不确定的关键部分。因此,ML 工程师怀疑是否在他们的 MLOps 旅程中过早地使用这些工具。
在中小型公司或初创公司中,ML 和数据工程团队共享相同的技术堆栈是非常常见的。出于这个原因,迁移到一个特性商店可能会引起很大的麻烦,并暴露一些隐藏的成本。在计划、遗产维护、操作性、两面性等方面。,它成为另一个具有不同于传统数据工程的特定 SDK 的基础设施。
谁应该购买功能商店?
为了从商业功能商店中获取最大价值,您的用例以及数据科学团队的设置需要与它们提供的核心优势保持一致。严重依赖实时复杂 ML 用例的产品,如推荐系统、动态定价或欺诈检测,是最能利用这些工具的产品。
一个庞大的数据科学家团队也是拥有特征库的一个很好的理由,因为它将提高生产率和特征的可重用性。除此之外,它们通常提供一个很好的 UI 来发现和探索特性。尽管如此,商业特性库 SDK 和 API 提供了一组标准,以更为一致的方式获取和检索特性。作为副产品,数据被治理,可靠的元数据总是被记录。
在各种各样的 ML 团队领域中,上述情况并不总是满足的,并且建立这些新的商业栈有时仅仅是工程师的个人开发愿望,以跟上新技术的发展。
这就是为什么仍然有团队没有迁移到一个完整打包的特性库,而是仍然依赖现有的数据工程栈来运行他们的产品特性工程层。在我看来,这是完全正确的。
总而言之,特性存储只是在现有的数据工程堆栈上添加了一个方便的外壳,以提供统一的访问 API,一个发现和管理特性集的漂亮 UI,保证在线和特性存储之间的一致性,等等。但是所有这些特性并不是每个 ML 团队用例的关键。
结论
我希望这篇文章提供了一个关于什么是特性存储的广阔的视野。但更重要的是,它们之所以必要的原因,以及构建时需要解决的关键组件。
功能存储对于提升数据科学行业的生产服务是必要的。但是你需要他们背后的工程师。ML 工程师角色对于处理特征管道是至关重要的,因为它们只是一种特定类型的数据转换和摄取过程。像这样的混合角色使数据科学家能够更加专注于实验方面,并保证高质量的交付成果。
此外,我特别注意解释了构建与购买的困境。从我个人的经验来看,这个问题在任何一个成熟的 ML 团队中迟早都会出现。我试图描述它们对实现速度和标准化至关重要的情况,但也留下了一些思考,即为什么环境意识对于实现这项新技术是必要的。有经验的高级角色应考虑他们所处的 MLOps 旅程阶段。
功能商店(商业和开源)世界还很年轻,还没有一个统一的和公认的方法来处理所有不同的用例和需求。所以,在和一个人安定下来之前,尝试所有的方法。
参考
- 特色商店——需求层次
- 功能商店讲解:三种常见架构|功能形式
- 特征存储-现代数据堆栈
- 回到未来:解决机器学习中的时间旅行问题|泰克顿
- 数据集时间旅行概述 Max Halford
- “用 Apache Samza 彻底改变数据库”,作者 Martin Kleppmann
- 时态数据库–wiki wand
- 利用特征库构建实时 ML 管道| Adi Hirsch tein 著
- 生产中的奔跑盛宴
- 黑仔特色店:协调生产用 Spark ML 管道和 ML flow
- 需要特色店吗?
如何进行数据标注和数据收集:原则和过程
原文:https://web.archive.org/web/https://neptune.ai/blog/data-labeling-and-data-collection
如果你发现自己想知道数据集是如何建立的,你不是唯一一个。在机器学习中,我们的模型是其输入数据的表示。一个模型是基于输入的数据工作的,所以如果数据是坏的,那么这个模型的性能就很差。垃圾进,垃圾出。
为了建立好的模型,我们需要高质量的数据。但是,收集和标记大量高质量的数据既耗时又昂贵。您还必须转换数据,只有这样,数据才能成为构建模型的宝贵资产。
有一些方法可以使这个过程变得更容易,并从公开的来源或第三方提供商那里收集您需要的数据。在本文中,我们将探索不同的数据收集和标注方法。
构建 ML 模型的数据收集原则
为了预测和评估问题的可能结果,我们需要收集包含我们答案的数据。这些数据将为我们提供对问题的可行见解,帮助我们可视化模式并预测未来趋势。
在我们找到这些数据之前,有一些事情需要考虑:
- 问题理解,
- 数据收集方法,
- 预算,
- 数据一致性。
问题理解
在你开始收集数据之前,你必须首先尽可能地了解你要解决的问题。你需要回答这样的问题:
- 任务是有人监督的还是无人监督的?
- 如果监督,是回归任务还是分类任务?
- 如果无监督,是聚类还是关联?
- 是加固问题吗?
还有更多。如果你觉得自己对问题理解得不够好,就不要急着走这一步,需要多少时间就花多少时间去探索。
数据收集方法
收集不同类型的数据有不同的方法。不是每种方法都适合你的问题。使用正确的方法将有助于避免数据集因浪费而膨胀。要收集定性或定量数据,您可以使用以下方法:
- 采访,
- 摄像机,
- 录音机,
- 问卷调查,
- 调查,
- 表格,
- 网络抓取/爬行,
- 众包,
- 在线跟踪…
…以及更多!
预算
这是一个需要考虑的特殊因素,手头的预算将决定如何收集数据,是从第三方公司购买,还是手动收集数据,这都取决于预算。
数据一致性
当我们谈论数据一致性时,它仅仅意味着您的数据应该是一致的。
为避免常见问题,请确保:
- 参与数据收集的每个人都确切地知道该做什么,
- 数据被安全地存储并有备份,
- 数据的类型是正确的,例如,如果它是一个回归任务,您应该将数据放在具有预定义结构的表中,以便保持完整性。
从干净的来源收集数据,以后处理数据会更容易。
ML 模型输入的数据标记
标记是数据管道中最耗时的步骤之一。在标记过程中,我们处理数据并添加有意义的信息或标签(标签)来帮助我们的模型学习。
我们的模型将最终预测这些标签。在预测标签时,我们发现了基本事实。这告诉我们我们的模型的预测是如何与现实相符的。你的基本事实越接近现实,你的标签就越好。
在图像识别项目中,贴标签者(将有意义的标签贴在单独数据上的人)可以使用一个框架来显示包含许多对象的图片中的一张脸(标签)。标签由相应数据中的可用特征决定。在人的脸上,有几个特征表示它。脸由嘴、眼睛、眉毛、下巴、鼻子等组成——这些特征加在一起就能决定它是人脸还是挂钟。
没有标签,算法很难分离数据。
过去,数据科学家只会手动标记数据。我们仍然经常这样做,但也有一些方法可以减少使用工具的手工操作。
ML 中的数据标记有两个目标:
- 准确性–衡量数据标签和真实数据之间的相似性。
- 质量–测量数据集中的一致性,即整个数据集是否符合标签标准
让我们看看如何开始标记,从手动方法开始。
手动数据标记
在这里,您只需浏览所有数据点并手动添加标签。当然,到了某个点,就变得不划算了。另外,某些参数或标签无法手动有效完成。
我们可以使用的一种方法是手动标记一些数据,将其用于训练,并通过 predict 函数将其余未标记的数据输入到模型中。预测的标签将被标注到数据中。这样可以节省很多时间。
让我们来看看一些数据标注技术:
语义的
计算机视觉中使用的一种流行的注释技术。它通过实例分割、定位和分类使对象可检测。它通过将图像分成更容易分析的片段来简化图像。
包围盒
这是一种注释,我们在对象周围创建一个假想的框。该框是对象的参考点,可用于勾画对象的 X 和 Y 坐标。该算法可以快速定位它正在寻找的对象,同时节省计算资源和内存,从而提高整体标记效率。
关键点
在现实生活中,当提到关键点时,它意味着所有其他点中最重要的一点。深度学习中的关键点是指图像中的兴趣点及其空间位置。例如,一张脸,这里的关键点是眼睛,鼻子,下颌线,耳尖等等,它们使脸可以从其他物体中识别出来。
长方体
在某些情况下,我们需要的不仅仅是一个边界框——我们需要一个长方体。长方体是 3D 对象,可以从 2D 图像表示中提取 3D 图形的立方体。这些 3D 人物可以用于增强现实、自动驾驶汽车、机器人、无人机等等。这些对象的注释可以在长方体应用程序之后完成。
不同的工具有不同的特性,所以我们来看看:
- 自动化程度,
- 用户体验和界面,
- 数据安全,
- 存储,
- 支持的文件类型。
MLOps 工具前景找到最适合您的使用案例的 MLOps 工具。
一些流行的数据标注工具有:
亚马逊拥有的最好的标签工具之一,这要归功于扩展的自动化和定制的工作流程服务。这是一个完全受管理的数据标注工具,使用基础事实进行标注,以确保更好地预测标注。
**标注—**训练前使用元数据标注数据的过程。
合并–将两个或多个注释组合在一起,为训练数据生成一个可靠的标签。
使用注释合并,当标签的置信度较低时,数据点将被附加到一个“由人类检查”的类中。这防止了标签中的错误。在 Sage Maker 中,您可以使用尽可能多的贴标机。使用更多的贴标机产生更好的结果,但也增加了贴标价格。
这个工具有一个很酷的用户友好的界面,它很容易使用和省时。它支持 3D 点云、音频、视频、图像等等。它通过注释和标签提高数据质量。
显著特征:
- 亚马逊 Sage Maker Ground truth 可以用亚马逊机械土耳其人实现,
- 价格非常灵活,
- 贴标由内部和外部贴标机辅助
- 多帧分类,
- 它可以提取实体,
- 处理图像、视频和文本。
这是一个用于计算机视觉的开源数据标记工具。它是基于网络的,支持使用多边形、矩形、圆形和线点的图像注释,便于分类。您也可以查询注释。它在 Python 中可用,您可以在使用 pip 命令安装后在您的本地环境中运行它。LabelMe 是安全的,因为您的数据只在您和您的操作环境之间移动。
显著特征:
- 它是免费使用的,
- 它易于使用,
- HTML 或 JavaScript 的自定义函数,
- 分割掩模提取。
不幸的是,它没有团队协作功能,也不支持真实世界的注释和质量检查。
用于图像标注的开源图形标注工具。它还标记图像中的对象边界框。它是用 Python 写的,用户界面使用 QT。
它是免费的,可以用 pip 命令 pip3 install labelImg 下载。
LabelImg 支持 VOC XML 或 YOLO 格式的标签,也可以创建一个 XML 文本文件格式。但是最好使用默认的文件格式,即 VOC XML。
这是一种端到端的服务,可以处理地理、文本、视频、音频和图像数据。
用户可以最大限度地控制和定制任务、工作流和质量检查。这是一个 20 多年前首次建立的付费标签平台。他们提供众包服务和 API 集成。这是一个非常安全的数据标签平台。
Lionbridge AI 还为某些情况提供了人类标记的数据。项目可以从头开始构建,我们可以收集数据,对其进行注释,执行数据验证和语言评估。
这个平台还为项目收集数据,包括数据输入、文本摘要、聊天机器人训练数据等等。
显著特征:
- 在这个平台上,有超过 300 种语言可用于项目启动,
- 用于计算机视觉的 2D 和 3D 包围盒,
- 自动驾驶的地标标注,
- 质量保证,
- 语法和拼写纠正,
- 语音识别,为 NLP 任务提供语音助手,
- 如果需要,可以集成 API。
这是一个众包平台,在这里你可以设计、协调和发布人工智能任务(HITs)。AMT 为数据标签服务提供按需劳动力,并很快产生结果。你可以在预算范围内定义和描述你的任务。
要使用这个工具,您必须在平台上注册,定义您的任务并运行它。
任务定义非常重要,并不像听起来那么简单。你需要考虑:
- 你的预算,
- 任务类型(多任务或单任务、翻译等)。),
- Turker 的需求特征(年龄组、语言能力、特定地理位置等。),
- 工作能有多有效,多准确。
有了一个精确、清晰的任务定义和易读的说明,你就可以置身于支付或祈祷的两难境地。这意味着你可以选择支付更多的贴标机,并将点击分成更小的任务,这将产生更准确的结果——或者你可以在更一般的任务上使用更少的 Turkers,获得不太准确的结果。在成本效益和数据质量之间取得平衡并不容易。
Amazon Mechanical Turk 是一个非常棒的数据标签、众包等平台。唯一的问题是它不能让你完全控制你的数据。此外,安全性不是很好,这可能会导致较低的数据集质量。由于语言障碍、不清楚的任务说明或其他问题,所使用的 Turkers/人类贴标机可能会篡改数据。
Label studio 是一个开源平台,提供在网络上运行的数据标注服务。它在后端用 Python 构建,在前端结合了 FMST 和 React。它为不同的数据类型提供了广泛的标签,包括图像、文本、音频、时间序列等等。
该工具可在任何浏览器上使用。它产生高精度,并且易于在 ML 应用中使用,用于为未标记数据的标签提供预测,并且执行连续的主动学习。
要使用 Label Studio,您需要:
- 使用 pip install label-studio 将它安装到您的命令 shell 中,
- 创建 label studio 帐户来管理您的标注项目,
- 设置您的标签项目,
- 定义要在数据集上执行的标注类型,
- 添加您想要应用的注释器,
- 导入数据并开始标注。
显著特征:
- 配置简单,
- 支持对不同数据类型的标注操作,
- 在任何网络浏览器中进行评估,
- 伟大的自动化,
- 易于使用,
- 由于标注精度高,可获得高水平的精确数据集。
这是一个训练数据平台,允许您定制从标记到迭代的过程。它促进了内部流程和平台之间的轻松协作和集成,使使用和创建优化数据集变得容易。LabelBox 有一个用于执行分析任务的命令。
显著特征:
- 伟大的迭代为改进的数据集提供精确的标注,
- 团队协作。
CVAT(计算机视觉标注工具)是一个计算机视觉的标注工具。它的开源支持图像和视频注释,并且是基于网络的。
它创建了一个边界框,为建模准备基于计算机视觉的数据,但它很难使用。你只能通过谷歌 Chrome 浏览器使用它,而且它没有一个好的质量控制机制,因为你必须手动操作。掌握这个工具也需要时间,但是一旦你掌握了,它的功能就非常强大。
VoTT(视觉对象标记工具)是一个用于计算机视觉(视频和图像)的标记工具,由微软开发。您可以通过浏览器使用它,或者从源代码构建它。web 浏览器不支持本地文件中的数据。它使用边界框进行处理。
这是一个相对易于使用的数据注释工具,具有自动 ML 特性和人在回路中的交互。用户可以上传数据(图像、视频、文本)和创建项目。项目可以由团队成员或由 Dataturks 提供的第三方注释者来管理。
该平台在 GitHub 上是开源的,其工具允许用户使用多边形和边界框来分割图像或检测对象。
在 NLP 中,它提供了广泛的数据注释,可以处理 PDF、Docs、CSV 等文件。
标记数据而不损失质量,并具有最高的安全性。这个工具使用现代网络技术来提供干净清晰的集成。它处理与计算机视觉相关的数据类型,即图像。它使用 2D 包围盒,长方体,多边形,多段线,地标,等等,进行物体检测。
显著特征:
- 数据质量有保证,
- 数据的安全性得到保证,
- 它很容易使用,
- 它支持流行的数据类型,
- 自动化,
- 性价比高,
- 它拥有强大的 API,便于管道集成。
这个平台为计算机视觉数据、自然语言处理和自动化提供了大量的可能性。我们可以快速标记、训练和部署 AI 模型,并过滤掉不相关的数据。
显著特征:
- 为高精度模型提供全面管理的数据标注服务,
- 保证数据安全,
- 为您的注释创建丰富的元数据。
如果你正在寻找一个专门从事 NLP 的平台,Datasaur 是最好的候选之一。多用户交互,实现高效的劳动力管理,并通过使用预先训练的模型进行培训来提高培训数据的质量。它还支持多种文本数据格式,包括 CSV 和 JSON,并保证了数据的安全性和质量。
命名实体识别(NER)是一种功能,用于发现数据中的某些实体并为其提供含义(如“名词”),还用于词性和共指解析。它识别数据中出现的各种词类,并定位引用同一实体的文本。
显著特征:
- 它部署到公共/私有云,
- 数据隐私和安全性得到保证,
- 省时,
- 标签准确度很高。
摘要
工具 | 数据类型 | 安全性 | 费用 | 特征 |
---|---|---|---|---|
亚马逊地面真理智者
|
图片、视频、文字、3D 点、音频
|
t 对您的静态和传输中的数据进行加密,数据仍在您的控制之下,而访问可以通过 AWS 身份和访问管理(IAM)进行控制。
|
这招相当便宜有效。这是一个付费的标签工具。
|
图像分类、对象检测、语义分割、视频多帧对象分类、视频多帧对象跟踪和视频片段分类。
它还提供自动标记功能,如“自动分段”、“自动 3D 长方体捕捉”和“传感器与 2D 视频帧融合”。
因为它像一个 python 包,开发仍在进行中,但现在它缺乏安全策略,但数据在本地文件中相当安全。
|
免费使用,并向公众开放投稿。
|
有无多边形、矩形、圆形、直线、点和图像级标志标注,视频标注。
由于注释是离线完成的,因此数据安全保存在本地文件中。
|
这是一个免费的开源工具。
|
用 Python 写的,图形界面用 QT。
支持热键,方便标注。
严格基于窗口的 app,无浏览器支持。
它只使用边界框。
地理,文字,视频,音频,图像
|
数据安全性高,有保障。
|
它是一个付费的标注工具。
|
最大化控制和定制任务、工作流和质量检查
用于计算机视觉的 2D 和 3D 边界框,用于自动驾驶的地标标注。
文本、图像、视频、音频
| |
它是免费的,可以在任何浏览器上运行
|
使用包围盒、多边形检测物体。标记和识别音频中的情感。标签精度极高
数据加密,google cloud 用于存储,被
用户查看时自动解密使用 Auth0 进行认证。
|
这是一个基于小时费率的付费工具。
|
内部流程与平台之间的轻松协作和集成,使其易于使用和创建优化的数据集。
数据被固定在此工具上
|
这是一个开源工具。
|
它用包围盒、多边形、折线、关键点、3D 长方体来标注。功能强大,但有一些死角,如有限的网络浏览器访问等。
使用令牌提供安全性,当且仅当令牌相同时,数据才能被多人访问。
|
它是免费开源的。
|
web 浏览器不支持来自本地文件的数据
适用于云存储数据,您可以从本地或云存储提供商导入数据,并支持项目跟踪指标。
可以作为原生 app 安装在操作系统上。
尚未可知的不安全感
|
这是一个开源的、付费的工具。
|
有无自动 ML 功能和人在回路中的互动。
提供可离线贴标的 docker。
图像,视频,传感器,3D 点
|
这里用到的是网络安全和数据匿名。
注释者用来标记数据的设备上的下载或存储功能可能被禁用。
|
这是一个按小时或工作量付费的工具。
|
提供 2D 包围盒、长方体、折线、地标、多边形进行标注。
用于自动驾驶汽车、座机等。
员工遵守安全标准和数据隐私原则,
可在安全设施中添加背景检查和注释,以提高安全性。
| |
用包围盒应用程序从文档中识别和提取结构化文本。
多分类可用。
多边形,边界框用于标注。
跨视频帧的对象标注。
质量保证检查点存在。
文本、音频、图像、视频
|
它可以防止数据泄露,部署到公共/私有云和本地。
数据只能由设定的特权团队访问。
|
付款是标注所需的
。
|
合同摘要&理解,
产品评论可以分析
词性和共指消解
它将图片中的文本转换成 ML 文本。
它在自然语言处理中应用广泛,支持命名实体识别、依存、文档标注、光学字符识别、词性、共指。
|
现在你知道了数据收集和标注是怎么回事,你有一些工具可以在下一个项目中试用。在你的实验中找到你自己的最佳实践和好运!
数据标签软件:数据标签的最佳工具
原文:https://web.archive.org/web/https://neptune.ai/blog/data-labeling-software
在机器学习和 AI 开发中,数据标注的方面是必不可少的。您需要一组结构化的训练数据,以便 ML 系统可以从中学习。
创建精确标注的数据集需要付出很多努力。数据标注工具非常方便,因为它们可以自动完成特别繁琐的标注过程。
最重要的是,这些工具可以简化整个数据集创建过程的协作和质量控制。您可以从任何类型的数据中获得准确的训练数据集,并且可以将其与 ML 管道连接起来。
因此,在本文中,我们将探索 10 种最佳数据标注工具。
亚马逊 SageMaker Ground Truth 是亚马逊最先进的自动数据标注服务。该工具提供了一种完全托管的数据标注服务,可简化机器学习数据集的实施。
借助 Ground Truth,您可以轻松构建高度准确的训练数据集。有一个定制的内置工作流程,通过它您可以在几分钟内高精度地标记您的数据。该工具支持不同类型的标注输出,例如文本、图像、视频和 3D 云点。
自动 3D 长方体捕捉、消除 2D 图像中的扭曲以及自动分段工具等标记功能使标记过程变得简单和优化。它们大大减少了标注数据集所需的时间。
在整个过程中,您将:
- 将原始数据输入亚马逊 S3。
- 使用内置的自定义工作流程创建自动标签任务。
- 从一组贴标机中进行准确选择。
- 具有辅助标注功能的标签
- 生成准确的训练数据集。
地面实况的主要好处是:
- 它是自动的,很容易使用。
- 它提高了数据标注的准确性。
- 它的标记功能大大减少了时间。
你可以在这里观看概览视频。
Label Studio 是一个 web 应用程序平台,提供数据标注服务,并探索多种数据类型。它使用 React 和 MST 的组合作为前端,Python 作为后端。
它为每一种可能的数据类型提供数据标签:文本、图像、视频、音频、时间序列、多域数据类型等。所得到的数据集具有高精度,并且可以容易地用于 ML 应用中。该工具可从任何浏览器访问。它以预编译的 js/CSS 脚本的形式分发,可以在每个浏览器上运行。还有一个将 Label Studio UI 嵌入到应用程序中的特性。
为了执行准确的标注并创建优化的数据集,该工具:
- 从各种 API、文件、Web UI、音频 URL、HTML 标记等获取数据。
- 将数据传输到标签配置,该配置有三个主要的子流程:
- 从各种来源获取不同类型数据的任务。
- 完成过程以 JSON 格式提供标记的结果。
- 预测过程以 JSON 格式提供可选的标注结果。
- 机器学习后端添加了流行和高效的 ML 框架,以自动创建准确的数据集。
好处是:
- 支持不同类型数据的标记。
- 易于使用和自动化。
- 可以在任何网络浏览器中访问,也可以嵌入到个人应用程序中。
- 使用精确的标注工作流生成高级数据集。
Sloth 是一个开源的数据标记工具,主要用于标记计算机视觉研究的图像和视频数据。它为计算机视觉中的数据标记提供了动态工具。
该工具可被视为一个框架或一组标准组件,用于快速配置专为您的需求定制的标注工具。Sloth 允许您编写自己的定制配置,或者使用默认配置来标记数据。
它让你书写和分解你自己的观想项目。您可以处理从安装到标记的完整过程,并创建正确记录的可视化数据集。树懒很容易使用。
好处是:
- 它简化了图像和视频数据的标记。
- 为计算机视觉创建精确数据集的专用工具。
- 您可以自定义默认配置来创建自己的标注工作流。
LabelBox 是一个流行的数据标注工具,它为精确的数据标注和创建优化的数据集提供了一个迭代的工作流程。平台界面为机器学习团队提供了一个协作环境,以便他们可以轻松有效地交流和设计数据集。该工具提供了一个命令中心来控制和执行数据标注、数据管理和数据分析任务。
整个过程包括:
- 管理外部贴标服务,劳动力和机器标签。
- 不同数据类型的优化。
- 用于训练和标记数据并进行预测的分析和自动迭代过程,以及主动学习。
好处是:
- ML 团队协作的集中指挥中心。
- 易于完成任务,具备完整的沟通能力。
- 通过主动学习迭代您的过程,以执行高度精确的标注并创建改进的数据集。
Tagtog 是一个基于文本标注的数据标注工具。标注过程针对文本格式和基于文本的操作进行了优化,为基于文本的人工智能创建专门的数据集。
该工具的核心是一个自然语言处理(NPL)文本注释工具。它还提供了一个平台来管理手动标记文本的工作,采用机器学习模型来优化任务,等等。
有了这个工具,你可以自动从文本中获得相关的洞察。它有助于发现模式、识别挑战和实现解决方案。该平台支持 ML 和字典注释、多种语言、多种格式、安全云存储、团队协作和质量管理。
过程很简单:
- 以任何文件格式导入基于文本的数据。
- 自动或手动执行标记。
- 使用 API 格式导出精确的数据集。
好处是:
- 它易于使用,对所有人都非常方便。
- 它非常灵活,您可以将它集成到您自己的应用程序中,提供个性化的工作流程和工作人员。
- 这既省时又省钱。
Playment 是一个多功能的数据标注平台,提供定制的安全工作流,通过 ML 辅助工具和复杂的项目管理软件来构建高质量的训练数据集。
它为各种用例提供注释,例如图像注释、视频注释和传感器融合注释。该平台支持端到端的项目管理,具有标签平台和自动扩展的劳动力,以优化具有高质量数据集的机器学习管道。
它具有工作流定制、自动化标签、集中式项目管理、劳动力协作、内置质量控制工具、基于业务的动态扩展、安全云存储等功能。这是一个非常棒的工具,可以标注数据集并为 ML 应用程序生成高质量的精确数据集。
好处是:
- 具有集中项目管理中心的一体化工具。
- ML 团队无缝参与的协作平台。
- 易于使用,并通过内置的自动化工具实现自动化。
- 非常重视质量控制。
Dataturk 是一个开源的在线工具,主要为标记文本、图像和视频数据提供服务。它允许您上传数据、与员工协作并开始标记数据,从而简化了整个流程。这让您可以在几个小时内构建准确的数据集。
它支持各种数据注释需求,如图像边界框、文档中的 NER 标记、图像分割、词性标记等。用于员工协作的简单易用的用户界面。
整个过程很简单:
- 基于所需的注释创建项目。
- 以任何相关格式上传所需数据。
- 引入劳动力并开始标记/贴标签。
好处是:
- 开源工具,让所有人都可以使用这些服务。
- 用于团队和标签之间协调的简单 UI 平台。
- 高度简化的标注过程可在短时间内创建数据集。
LightTag 是另一个文本标注工具,旨在为 NLP 创建精确的数据集。该工具被配置为在与 ML 团队的协作工作流中运行。它提供了一个高度简化的 UI 体验来管理工作人员并使注释变得容易。该工具还为精确标注和优化数据集创建提供了高质量的控制功能。
好处是:
- 超级简化的 UI 平台,便于标签流程和团队管理。
- 更快更有效的数据标注,没有任何复杂的功能麻烦。
- 减少时间和项目管理成本。
Superannotate 是最快的数据注释工具,专门设计为计算机视觉产品的完整解决方案。它提供了一个端到端的平台来标记、训练和自动化计算机视觉管道。它支持多级质量管理和有效协作,以提高模型性能。
它可以轻松地与任何平台集成,以创建无缝的工作流程。该平台可以处理图像、视频、激光雷达、文本/NLP 和音频数据的标注。借助高性能工具、自动预测和质量控制,该工具可以以最高的精度加速注释过程。
好处是:
- 该平台支持智能预测和主动学习,以创建更准确的数据集。
- 它利用迁移学习方法来提高整体训练的效率。
- 它支持手动和自动贴标,具有适当的质量保证结构。
CVAT 是一个强大的开源计算机视觉标记工具。它主要支持图像和视频注释。CVAT 有助于图像分割、图像分类和对象检测等任务。这个工具对于它所做的工作来说非常强大,但是不容易使用。
整体工作流程和用例有点难以理解。掌握这个工具需要训练。CVAT 只能通过谷歌 Chrome 浏览器访问。网络界面很难适应。该工具在标注和数据集生成方面效率很高,但缺乏质量控制机制,因此您需要手动执行。
好处是:
- 该工具是开源的,对于基于图像和视频的注释非常高效。
- 它支持自动标记。
结论
数据标注或标记一直是机器学习和人工智能领域的重要组成部分。在标注工具出现之前,标注数据集中的每个数据点所需的手动工作效率非常低,容易出错,而且非常困难。
现在,有了上面提到的最先进的工具,由于自动化、团队管理、预测分析和迭代学习,这个过程变得更加容易。因此,随着不同变量的变化,数据集更加精确和优化。
这些工具使得数据科学家和 ML 开发者的工作变得更加容易。不同应用的数据集随时可用。由于能够将标记的数据集传输到机器学习模型,整体基于人工智能的工作和模型创建变得更容易、更准确和优化。
克里斯萨纳瓦特·卡韦桑穆昂
InstaMobile 的开发者关系
只是一个典型的内向开发者,美国——没有上瘾,对人工智能和区块链充满热情。
阅读下一篇
利用机器学习项目改善工作流程的最佳 7 种数据版本控制工具
5 分钟阅读| Jakub Czakon |年 10 月 20 日更新
跟踪所有用于模型和实验的数据并不容易。这需要很多时间,而且不仅仅是管理和跟踪文件。你需要确保每个人都在同一个页面上,并同时跟踪最新版本的变化。
使用正确的软件,你可以毫不费力地做到这一点!一个好的数据版本控制工具可以让你拥有一个统一的数据集和一个强大的实验库。
它还将实现所有团队成员之间的顺畅协作,因此每个人都可以实时跟踪变化,并始终知道发生了什么。
这是系统化数据版本控制、改进工作流程和最小化出错风险的好方法。
因此,请查看这些用于数据版本控制的顶级工具,它们可以帮助您实现工作自动化并优化流程。
如果您关心可再现性、可追溯性和 ML 模型血统,那么数据版本化工具对您的工作流程至关重要。
它们帮助您获得一个工件的版本,一个数据集或模型的散列,您可以在以后使用它来识别和比较。通常,您会将此数据版本记录到您的元数据管理解决方案中,以确保您的模型训练是版本化的和可重复的。
如何选择数据版本化工具?
要为您的工作流选择合适的数据版本化工具,您应该检查:
- 支持您的数据形态:它是如何支持视频/音频的?它是否为表格数据提供了一些预览?
- 易用性:在你的工作流程中使用起来有多容易?它给你的执行增加了多少开销?
- Diff and compare :可以比较数据集吗?你能看到你的图像目录的不同吗?
- 它与您的堆栈配合得如何:您能否轻松连接到您的基础设施、平台或模型培训工作流?
- 你能让你的团队参与进来吗:如果你的团队不采用它,工具再好也没用。所以,记住你的队友的技能和偏好。
这里有一些值得探索的工具。
机器学习中的数据谱系:方法和最佳实践
原文:https://web.archive.org/web/https://neptune.ai/blog/data-lineage-in-machine-learning
数据应该是组织最宝贵的资产。然而,直到最近才出现这种情况,所以很少有人有处理数据和利用数据创造更多价值的经验。
随着管理人员对数据越来越熟悉,许多组织正在采用跟踪数据血统的做法,这已经成为推动组织提高数据效率的稳定支持。
什么是数据血统?
数据谱系是数据背后的故事。它从数据的创建点到消费点跟踪数据。这个数据流管道包括输入和输出点、数据经历的转换和建模过程、记录分析、可视化以及其他几个不断被跟踪和更新的过程。
数据沿袭的目标是观察数据的整个生命周期,以便可以升级和利用管道来获得最佳性能。
数据血统与数据来源
数据血统经常与数据起源混淆,因为这种区别非常微妙,很容易被忽略。两者都有一个共同的目标,那就是通过跟踪和观察来为优化服务,但是在较高的层次上,数据血统是数据起源的子集。
数据沿袭通过跟踪数据的旅程(包括起源、目的地、转换和经历的过程)来特别关注数据,而数据起源则另外跟踪影响数据的所有系统和过程。
因此,数据沿袭处理关于数据(元数据)的数据,而数据起源处理关于影响数据的过程的信息。
为什么数据沿袭是必要的?
关于数据之旅及其经历的环境的知识提供了对数据当前状态的大量控制,可用于导航数据解决方案的最佳路线。
然而,使数据谱系成为绝对必要的是组织和行业之间日益增长的竞争和数据效率或专业知识。几年前,智能数据或统计解决方案是为组织提供竞争优势的好方法。然而,如今大多数组织都希望优化他们的数据资产。对数据的控制和了解正逐渐成为一种竞争优势。
以下是将数据沿袭视为提高数据效率的关键因素之一的几个理由:
数据是一种不断发展的动态资产,依赖静态数据可能会对业务决策和结果产生不利影响。不断收集、更新和验证数据是一个关键的过程。数据沿袭在升级数据的过程中非常有用,尤其是因为它具有跟踪能力。升级数据不仅仅是获取新数据,还包括理解旧数据集的相关性。数据沿袭有助于将新数据与旧的相关数据相结合,这样数据消费者(如开发人员、业务团队和利益相关者)就可以从数据资产中获得最大价值。
由于数据沿袭而记录的元数据会自动提供可用于合规性审计的详细信息,或者有助于提高数据管道的安全性。这也有助于理解数据流的结构和过程,并为即兴创作留出充足的空间。一致地跟踪元数据还可以减少技术债务,从而降低风险管理和法规遵从性的总体成本。
在实际场景中,经常需要将数据从一个数据源迁移到另一个数据源。这意味着在迁移过程中,一些细节,如位置、格式、存储、带宽、安全问题等。必须事先知道。数据沿袭非常适合这种设置,因为它几乎可以立即提供深入的细节,并且节省了成本和时间。有了可用的元数据集,还可以根据目标和源系统的参数自动化和标准化迁移过程。
数据沿袭对于维护数据的完整性至关重要,而数据的完整性对企业至关重要。通过不断跟踪数据的细节,可以在数据不一致、不相关或过时的情况下即时更新并提醒用户。开发、销售、营销和业务运营等多个部门依靠数据来改进他们的流程。新鲜健康的数据可以为商业决策带来巨大的速度和价值。
谁从数据沿袭中受益?如何受益?
因为组织中的几个部门依赖于数据沿袭,所以让我们更近距离地观察依赖者,以进一步理解对数据沿袭的需求。
每个处理数据的组织都有一个 ETL 部门,负责提取、转换和加载过程。它是从数据源提取数据,应用所需的转换,然后与目标系统共享数据的过程。ETL 开发人员处理大量的数据,数据沿袭可以方便地检测 ETL 过程中的错误,并创建详细的传输报告。
安全专家和开发人员经常想方设法保护数据管道易受攻击的端点。数据沿袭始终如一地带来关于这些端点的关键信息,这有助于通过排列和组合进行实验。关于漏洞、死亡和导致它们的过程的记录,提供了更大的安全改进空间。
业务团队使用多个报告,在数据沿袭的帮助下,他们可以轻松地导航到报告的来源,并在必要时验证数据。
数据管理员是负责组织数据资产质量的个人。因此,数据管理员应该知道他/她所管理的数据的来龙去脉,而数据血统使得这个过程更加准确、透明和用户友好。
数据沿袭的方法
以下是执行数据沿袭跟踪的几种方法:
- 通过数据标记传承
这种方法基于一个假设,即转换工具始终与数据相关,并且在执行转换后标记数据。为了跟踪标记,了解标记的格式很重要,这样就可以在管道中发现它。该方法仅在仅部署了已知转换工具的封闭系统中是可靠的。
这是在完全由组织控制的封闭环境中追溯血统的时候。几乎每种类型的数据支持(数据湖、存储工具、数据管理和处理逻辑)都是环境的一部分。因此,沿袭也被限制在数据环境的边界,并且不知道外部的过程。
数据沿袭通过解析读取代码或转换逻辑,以了解数据如何达到其当前状态。在处理转换逻辑时,它能够追溯到以前的状态,并完成端到端的沿袭追踪。基于解析的沿袭不是技术不可知的,因为它需要理解数据上部署的编码语言和转换工具。这直接限制了该过程的灵活性,尽管它是最先进的谱系追踪技术之一。
这种数据沿袭的方法不适用于负责数据转换的代码。相反,该过程只观察数据并寻找模式来跟踪血统,这使得它完全与技术或算法无关。这不是一个非常可靠的方法,因为它容易丢失代码中根深蒂固的模式。
跨管道的数据沿袭
为了捕获端到端的沿袭,必须在数据管道的每个阶段和流程中跟踪数据。以下是执行数据沿袭的各个阶段:
数据收集或接收阶段是数据进入核心系统的阶段。数据沿袭可用于跟踪源系统和目标系统的重要信息,以验证数据、映射和转换的准确性。密切跟踪系统也有助于更容易地识别错误。
数据处理占据了创建数据解决方案的整个过程的很大一部分。它涉及到多种转换、过滤器、数据类型、表和存储位置。记录每个步骤的元数据不仅有助于合规性和生产速度,还能使开发过程更加丰富和高效。它使开发人员能够更详细地分析流程成功或失败背后的原因。
- 数据存储和访问阶段
组织通常部署大型数据湖来存储他们的数据。数据沿袭可用于跟踪访问权限、端点的生命特征和数据事务。这将提高安全性和合规性的自动化程度,鉴于数据湖的规模和复杂性,这是一个巨大的优势。
用户使用一系列功能(如连接和过滤)提出多个数据查询。有些功能在处理器上负担很重,因此效率较低。数据沿袭可以观察查询,以跟踪和验证流程以及由流程产生的不同版本的数据。同时,它还帮助优化查询,并提供包括最佳解决方案实例的报告。
数据沿袭的最佳实践
数据谱系是一个不断发展的学科,其过程正在快速改进。这里有一些基本的最佳实践可以保持这种势头:
到目前为止,组织的一般实践都是手工记录血统。鉴于生产的动态性和快节奏,手动跟踪不再可行。还建议使用同类最佳的数据目录来提高自动化程度。他们集成 AI 和 ML 来组合来自多个系统的元数据,以形成血统的逻辑流。它还具有从元数据中提取和形成结论的能力。
数据总是容易出错,这就是为什么在沿袭追踪中包含不同流程和工具的所有者非常重要。所有者最接近并最了解其应用程序生成的细节,并且能够足智多谋地指出记录或流程中的缺陷或错误。
- 包含元数据源
包括由处理、转换或传输数据的不同过程生成的数据,对于最准确地跟踪数据谱系至关重要。因此,应该将这些过程在数据上创建的元数据纳入沿袭跟踪。
- 渐进式提取和验证
为了最准确地映射谱系,建议按照数据管道的各个阶段连续记录元数据。这创建了一个定义良好的时间线,并以可读性更好的格式组织了大量的元数据日志。这种数据的渐进验证也变得更容易,从而可以首先验证高级连接。一旦它们清楚了,更深层次的复杂性就可以逐层验证了。渐进式方法在读取或提取数据时保持逻辑模式并减少错误。
尽管数据谱系是一个相对较新的学科,但它已经在后台发展了多年。最初,这些工具都是版本控制系统,最终扩展到更大的数据谱系学科。让我们浏览几代版本控制工具,了解它是如何给我们带来数据血统的。
几代数据沿袭平台:
**第一代:**第一代版本跟踪是原始的、完全手动的,主要由一个通过“锁”访问文档的人来管理。
第二代:第二代是一个巨大的进步,因为它允许社会协作,允许多个用户,通常是内部用户,来处理代码。唯一致命的缺点是代码合并的效率很低,需要开发人员在最终提交之前从外部合并代码。
**第三代:**第三代致力于克服第二代工具的缺点,并允许开发人员,不仅仅是内部的,而是全球的,在提交后的后期阶段协作并合并他们各自的有差异的版本。世界范围的网络和容易合并的设施允许巨大的扩展能力,特别是在开源社区。
**第四代:**版本控制的最后一代,也是现在的一代,是像 Pachyderm 这样的数据谱系平台的一部分。它在第三代的基础上即兴发挥,通过相当开放的过程实现版本控制,进入人工智能解决方案的生产。第四代的工作是跟踪系统中涉及的所有流程和工具,如云、存储、数据版本、算法等,同时保持不变性。总的来说,它成功地跟踪了数据管道的端到端流程。
数据沿袭的工具/平台:
下面是一些流行的数据沿袭工具。
Talend data catalog 是一个一站式资源,用于获取对您的数据进行处理的过程的详细信息。它可以搜索、提取、管理和保护来自多个来源的元数据,并能够自动搜索这些来源。
IBM DataStage 将分析、云环境、治理和数据操作结合在一个为人工智能开发而构建的平台中。它通过基于容器的架构提供高质量的数据。
Datameer 为构建数据管道提供了可视化的无代码体验,并允许数据专家协作来发现、访问、建模和传输数据。高质量的用户体验和强大的技术支持使 Datameer 成为强有力的竞争者。
Neptune 提供了一个单一的平台和仪表板来跟踪元数据、数据日志,并提供简单的功能,如名称空间和基本的日志记录方法来组织和组合几种类型的 ML 元数据。Neptune 的用户界面也显示数据版本控制文件,用户只需指定他们想要记录的类型。Neptune 的整体视觉体验包括图表、图像和表格,这使得该平台对于数据跟踪来说非常用户友好。
数据谱系的未来
在过去的几年中,一些新的学科已经开始发展,其影响已经触及了几个行业的边界。5G、边缘计算、物联网,当然还有人工智能等技术将产生大量宝贵的数据。为了充分利用这一容量,定义良好的跟踪系统是未来的需要,而该基础设施的基础是当前的责任。
一旦这些技术随着云进一步扩展,数据必然会暴露给外部代理,如连接到物联网的物理系统、边缘服务器和一般的云。数据转换将发生在遥远和断开的位置,这些位置通常是易受攻击的端点,有可能将数据管道置于危险之中。
通过安全地管理即使在今天仍在快速增长的庞大数据环境,数据血统将成为早期接受者的竞争优势。有了沿袭,跟踪错误和漏洞就容易多了,这样负责的系统就可以快速升级。此外,采用数据谱系的扩展好处,如降低成本、高可伸缩性、合规性、高数据和流程质量,预计将成为基于数据的行业的必备好处。
资源
数据预处理综合指南
原文:https://web.archive.org/web/https://neptune.ai/blog/data-preprocessing-guide
根据 2020 年国际数据公司的预测,2020 年将有 59z 字节的数据被创建、消费、捕获和复制。当我们回到 2012 年时,这一预测变得更加有趣,并且发现 IDC 预测到 2020 年数字世界将只达到 40zb**,而不仅仅是 2020 年的。**
实际数字和预测数字之间的巨大差距是有原因的,最大的原因是新冠肺炎·疫情。全球隔离让每个人都上网,数据生成量疯狂飙升。毫不奇怪,2020 年到 2024 年已经被命名为新冠肺炎数据激增的年份。这需要能够管理和优化数据的人员、流程和技术,以便快速获得有利可图的见解。
像数据管理和数据处理这样的技能变得非常有价值。这就是为什么本文是数据预处理步骤和技术的综合指南,让您进入这个新世界。
什么是数据预处理?
任何与数据相关的项目都有相当大一部分是关于数据预处理的,数据科学家花费大约 80%的时间准备和管理数据。数据预处理是分析、过滤、转换和编码数据的方法,以便机器学习算法可以理解和处理处理后的输出。
为什么数据预处理是必要的?
从数据中学习的算法只是对数据库中的值进行运算的统计方程。所以,俗话说“垃圾进去了,垃圾就出来了”。只有进入机器的数据是高质量的,你的数据项目才能成功。
在从现实世界场景中提取的数据中,总是存在噪声和缺失值。这是由于手动错误、意外事件、技术问题或各种其他障碍造成的。算法不能消耗不完整和有噪声的数据,因为它们通常不是为处理缺失值而设计的,噪声会破坏样本的真实模式。数据预处理旨在通过彻底处理手头的数据来解决这些问题。
如何进行数据预处理?
在我们进入一步一步的数据处理的细节之前,让我们来看看一些工具和库,它们可以用来执行数据处理,并使数据处理更易于管理!
工具和库
可以通过工具和库来简化数据预处理步骤,使该过程更易于管理和执行。如果没有特定的库,one liner 解决方案可能需要数小时的编码来开发和优化。
用 Python 进行数据预处理: Python 是一种支持无数开源库的编程语言,可以用一行代码计算复杂的运算。例如,对于缺失值的智能插补,只需使用 scikit learn 的插补库包。或者,对于缩放数据集,只需调用预处理库包中的 MinMaxScaler 函数。 预处理库包中有无数数据预处理函数可用。
Autumunge 是一个伟大的工具,作为 python 库平台构建,为机器学习算法的直接应用准备表格数据。
用 R 进行数据预处理: R 是一个主要用于研究/学术目的的框架。它有多个包,就像 python 库一样,支持数据预处理步骤。
用 Weka 进行数据预处理: Weka 是一款支持数据挖掘和数据预处理的软件,通过内置的数据预处理工具和机器学习模型进行智能挖掘。
**使用 RapidMiner 进行数据预处理:**与 Weka 类似,RapidMiner 是一款开源软件,拥有各种支持数据预处理的高效工具。
既然我们有了支持多种功能的适当工具,让我们深入研究数据预处理步骤。
数据预处理的目的
在您恰当地收集了数据之后,需要对其进行探索或评估,以发现关键趋势和不一致之处。数据质量评估的主要目标是:
获取数据概述:了解存储数据的数据格式和整体结构。此外,找到数据的属性,如平均值,中位数,标准分位数和标准差。这些细节有助于识别数据中的异常情况。
**识别缺失数据:**缺失数据在大多数现实世界的数据集中很常见。这可能会破坏真实的数据模式,甚至会导致更多的数据丢失,因为数据集中有几个单元格丢失了。
**识别异常值或异常数据:**一些数据点远离主要数据模式。这些点是异常值,可能需要丢弃以获得更高精度的预测,除非算法的主要目的是检测异常。
**消除不一致:**就像缺少值一样,真实世界的数据也有多种不一致,如拼写错误、列和行填充不正确(例如:性别列中填充的薪金)、重复数据等等。有时,这些不一致可以通过自动化来处理,但大多数情况下需要手动检查。
以下是一些流行的数据预处理技术,可以帮助您实现上述目标:
处理缺失值
缺失值是现实世界数据集中经常出现的问题,因为现实生活中的数据存在物理和人工限制。例如,如果传感器从特定来源捕获数据,传感器可能会停止工作一段时间,从而导致数据丢失。同样,不同的数据集有不同的问题会导致数据点丢失。
我们需要处理这些缺失的值,以最佳地利用可用的数据。以下是一些屡试不爽的方法:
**删除有缺失值的样本:**当样本数量较多,且一行/样本中缺失值的计数较多时,此选项很有用。对于其他情况,不推荐使用这种解决方案,因为它会导致大量数据丢失。
**用零替换缺失值:**有时这种技术对基本数据集有效,因为相关数据假设零为基数,表示该值缺失。然而,在大多数情况下,零本身可以表示一个值。例如,如果传感器生成温度值,而数据集属于热带地区。类似地,在大多数情况下,如果缺少的值用 0 填充,那么它会误导模型。只有当数据集独立于其效果时,0 才能用作替换。例如,在电话账单数据中,“账单金额”列中缺少的值可以替换为零,因为它可能表示用户当月没有订购该计划。
**用均值、中值或众数替换缺失值:**您可以通过使用均值、中值或众数等统计函数替换缺失值,来处理上述因错误使用 0 而导致的问题。尽管它们也是假设,但这些值更有意义,与 0 这样的单一值相比,它们更接近近似值。
**插值缺失值:**插值有助于根据给定的步长生成某个范围内的值。例如,如果在值为 0 和 10 的单元格之间的列中有 9 个缺失值,插值将用 1 到 9 的数字填充缺失的单元格。可以理解的是,在插值之前,数据集需要根据更可靠的变量(如序列号)进行排序。
**外推缺失值:**外推有助于填充超出给定范围的值,如某个特征的极值。外推法借助另一个变量(通常是目标变量)来比较有问题的变量,并用引导参考填充它。
**用其他特征建立一个模型来预测缺失值:**这是我们提到的所有技术中最直观的。这里,算法研究除实际目标变量之外的所有变量(因为这将导致数据泄漏)。该算法的目标变量成为具有缺失值的特征。如果训练有素,该模型可以预测缺失点并提供最接近的近似值。
缩放比例
不同的列可以出现在不同的范围内。例如,可以有一列是距离单位,另一列是货币单位。这两列将具有截然不同的范围,使得任何机器学习模型都难以达到最佳计算状态。
用更专业的术语来说,如果考虑使用梯度下降,梯度下降算法将需要更长的时间来收敛,因为它必须处理相距很远的不同范围。下图显示了同样的情况。
Gradient Descent Convergence
左侧的图表具有缩放的要素。这意味着特性被降低到彼此可比较的值,因此优化函数不必采取重大跳跃来达到最佳点。算法(如决策树)不需要缩放,因为它不是基于距离的。然而,基于距离的模型必须毫无例外地具有缩放的特征。
一些流行的缩放技术有:
**最小-最大缩放器:**最小-最大缩放器缩小任意选择范围之间的特征值。例如,在 0 和 5 之间。
**标准定标器:**标准定标器假设变量呈正态分布,然后将其缩小,使标准差为 1,分布以 0 为中心。
**鲁棒定标器:**当数据集中存在离群值时,鲁棒定标器效果最佳。在移除中间值后,它会根据四分位数范围调整数据。
Max-Abs Scaler: 类似于 min-max scaler,但不是给定的范围,而是将特征缩放到其最大绝对值。数据的稀疏性得以保留,因为它不将数据居中。
Scikit Learn 的 预处理库包可以提供一个线性解决方案来执行上述所有缩放方法。
异常值处理
异常值是与数据中观察到的主要模式不一致的数据点。它们可以通过将计算从实际模式中移除而导致预测中断。
异常值可以在箱线图的帮助下检测和处理。箱线图用于确定中位数、四分位数范围和异常值。要移除异常值,需要记录最大和最小范围,并相应地过滤变量。
特征编码
有时,数据是机器无法处理的格式。例如,对于只依赖数字的模型来说,包含字符串值(如名称)的列没有任何意义。所以,我们需要处理数据来帮助模型解释它。这种方法叫做。有多种方法可以对类别进行编码。这里有几个让你开始:
**### 经典编码器
标签/序数编码 : 以序数(顺序)方式嵌入从 1 到 n 的值。“n”是列中的样本数。如果一列有 3 个城市名称,标签编码将为不同的城市分配值 1、2 和 3。当分类值没有固有顺序时,不建议使用这种方法,例如城市,但是这种方法适用于有序类别,例如学生成绩。
**一个热编码:**当数据没有固有的顺序时,可以使用一个热编码。一种热编码为每个类别生成一列,并在该类别出现的任何一行中分配一个正值(1),当该类别不存在时分配 0。这样做的缺点是,一个要素会生成多个要素,从而使数据变得庞大。在你没有太多特性的情况下,这不是问题。
二进制编码 : 这解决了一个热编码的笨重。每个分类值都被转换成二进制表示,并且为每个二进制数字创建一个新列。与一个热编码相比,这压缩了列的数量。对于分类列中的 100 个值,一个热编码将创建 100(或 99)个新列,而二进制编码将创建更少的列,除非值太大。
**BaseN 编码:**这类似于二进制编码,唯一的区别是基数。与二进制的基数 2 不同,任何其他基数都可以用于巴森编码。基数越高,信息损失越大,但编码器的压缩能力也会不断提高。公平的交易。
散列:散列意味着使用数学函数从一个类别中生成值。这就像一个热编码(有一个真/假函数),但是有一个更复杂的函数和更少的维度。由于结果值的冲突,哈希运算会丢失一些信息。
贝叶斯编码器
这些编码器从目标变量借用信息,并将它们映射到列中的类别。当类别数量非常大时,这种技术非常有用。在这种情况下,如果使用经典的编码器,将会增加许多倍的维数,给模型带来不必要的麻烦。当特征的数量非常大时,一个称为维数灾难的问题会降低机器学习模型的效率,因为它们仍然不足以处理大量的特征。
目标编码:只有目标变量中对应于特征中某一类别的那些行的平均值被映射到该类别。必须通过将测试数据分开来处理数据泄漏和过度拟合的问题。
**证据权重编码:**证据权重(WoE)是一个证据(或一个值)支持或否定一个假设的程度的度量。WoE 通常用宁滨技术对连续变量进行编码。
**留一编码:**类似于目标编码,但在计算平均值时会保留当前样本的值。这有助于避免异常值和异常数据。
**James-Stein 编码:**取对应目标均值的加权平均值以及整个目标变量的均值。这有助于减少过拟合和欠拟合。权重是基于估计的值的方差来决定的。如果构成平均值的值的方差很大,则表明该平均值不太可靠。
特征创建和聚合
可以从原始要素创建新要素。例如,如果名为“总时间”和“总距离”的两个特征可用,您可以创建速度特征。这为该模型提供了一个新的视角,该模型现在可以检测速度和目标变量之间的逻辑关系。
类似地,您可以这样做来构建其他直观的特性,比如基于工作日和周末的公里数,或者高峰时间的速度。在深度学习模型的情况下,神经网络层可以识别原始特征之间的复杂关系,因此我们不需要将基于公式的特征输入到 DL 模型中。
类似地,可以适当地聚合特征以减少数据量,并且还可以创建相关信息。例如,在降雨预报的时间序列模型中,数据必须根据天进行聚合,以便可以评估每天的总降雨量。全天的几个降雨测量记录不会给时间序列模型增加多少价值。
降维
机器学习模型还不足以处理大量的特征,遵循“垃圾进,垃圾出”的规则。在他们的书《变量和特征选择导论》中,Guyon 和 Elisseeff 写道:
变量选择的目标有三个:提高预测器的预测性能,提供更快、更具成本效益的预测器,以及更好地理解生成数据的基本过程。
使用不相关和冗余的特征将使模型变得不必要的复杂,甚至可能降低预测分数。特征选择的主要优点是:
- **减少处理时间:**数据量越少,训练和预测越快。更多的特征意味着模型可以学习更多的数据,并且增加了学习时间。
- **精度提升:**当一个模型没有无关变量需要考虑时,无关因素无法提升模型的得分。
- **减少过度拟合:**无关变量和冗余数据的数量越少,模型决策中的噪声传播就越小。
特征选择可以在许多层面上进行。首先,特征选择技术可以分为单变量和多变量技术。
单变量选择
在单变量选择下的每一种技术中,每一个特征都被单独研究,它与目标变量的关系也被考虑在内。以下是一些单变量特征选择技术:
差异
方差是给定特征变化的量度。例如,如果一个特征中的所有样本都具有相同的值,则意味着该特征的方差为零。重要的是要明白,没有足够方差的列与全是“nan”或缺失值的列一样好。如果特征没有变化,就不可能从中衍生出任何模式。因此,我们检查方差并消除任何显示低或无变化的特征。
方差阈值可能是消除数据集中的要素的好方法,但是在存在少数类(比如,5% 0 和 95% 1)的情况下,即使好的要素可能具有非常低的方差,但最终仍然是非常强的预测器。因此,建议您记住目标比率,并在仅基于方差消除特征之前使用相关方法。
相互关系
相关性是一种单变量分析技术。它检测两个变量之间的线性关系。可以把相关性看作是衡量比例的一个尺度,它只是衡量一个变量的增减如何影响另一个变量。
相关性的一个主要缺点是它不能恰当地捕捉非线性关系,甚至是强关系。下图展示了相关性的利与弊:
Linear relationship
Sine relationship
Correlation scores
第二张图显示了因变量和自变量之间的强正弦波关系。然而,相关性(-0.389)只能勉强捕捉到强依赖性。另一方面,当存在线性相关性时,我们会得到较高的相关分数(0.935),尽管它不如正弦相关性那么强。
有各种各样的相关技术,但基本上所有这些技术都试图追踪两个变量之间的线性关系。有三种流行的相关技术:
皮尔逊相关性:这是最简单的,并且有很多假设。所讨论的变量必须是正态分布的,并且彼此之间具有线性关系。此外,数据必须平均分布在回归线周围。然而,尽管有几个假设,皮尔逊相关对大多数数据都适用。
Spearman 等级相关性:它基于这样一个假设,即变量是按顺序(等级)来衡量的。它跟踪一个变量的可变性,该变量可以映射到被观察的另一个变量。
**Kendall 等级相关性:**这种方法是对两个变量之间的相关性的一种度量,除了基于概率而不是可变性来度量相关性之外,基本上遵循与 Spearman 相同的假设。它是被观察的两个变量有序的概率和不有序的概率之差。
你不仅要对目标(或因变量)进行相关性测试,还要对所有自变量进行相关性测试。例如,如果有两个变量分别与目标具有 90%和 85%的相关性,并且相互之间具有 95%的相关性,那么去掉这两个变量中的任何一个都是有益的。优选地是与目标具有较低相关性的那个。您需要这样做,以消除数据中的冗余信息,从而减少模型的偏差。
交互信息
互信息解决了相关性带来的问题。它有效地捕捉了给定变量之间的任何非线性关系。这有助于我们消除与目标变量没有显著关系的特征,帮助我们加强预测模型。互信息背后的思想是信息增益。它提出了这样一个问题:一个变量能从另一个变量中提取多少信息?或者,使用另一个变量可以跟踪一个变量的多少移动(增加或减少)?
对于相同的关系,正弦波和线性,互信息得分如下:
Mutual information scores
互信息正确地暗示了强正弦波关系,使得它在捕捉关于非线性关系的信息时更有能力。正弦关系的互信息是 0.781,而相同关系的相关性是-0.389。
卡方检验
这是一种统计工具或测试,可用于分类特征组,在频率分布的帮助下评估关联或相关的可能性。
多元选择
也称为包装方法,多变量选择技术每次选取一组特征,并测试该组预测目标变量的能力。
**正向选择:**这种方法从最少数量的特征开始,测量集合在预测时的表现。每次迭代,它都会添加另一个变量,这个变量是根据最佳性能(与所有其他变量相比)选择的。所有集合中具有最佳性能的集合被最终确定为特征集合。
**后向淘汰:**类似于前向选择,只是方向相反。向后消除从所有可能的特性开始,并在每次迭代中测量性能,消除无关的变量,或者与特性集配对时性能很差的变量。
与向前选择相比,向后淘汰通常是首选方法。这是因为在正向选择中,抑制效应会碍事。当一个变量只有在另一个变量保持不变的情况下才能得到最佳利用时,就会出现抑制效应。换句话说,对于新添加的特征,集合中已存在的特征可能变得不重要。为了避免这种情况,可以使用 p 值,尽管这是一个有点争议的统计工具。
**递归特征消除:**类似于向后消除,但它用递归方法代替了迭代方法。这是一个贪婪的优化算法,与一个模型一起寻找优化的特性集。
线性判别分析(LDA) :帮助您找到特征的线性组合,将两个或多个类别的分类变量分开。
ANOVA: 又名“方差分析”,类似于 LDA,但使用一个或多个分类特征和一个连续目标。这是一个统计测试,测试不同组的平均值是否相似。
**嵌入式方法:**一些机器学习模型自带内置的特征选择方法。它们被设计为根据特征在预测目标方面的性能对特征应用系数。表现不佳的变量的系数非常低或为零,这就(几乎)完全将它们从学习方程中忽略了。嵌入方法的例子是岭和套索模型,它们是回归问题中使用的线性模型。
摘要
至此,我们已经完成了本指南的所有内容。请注意,这里提到的每一步都有几个副主题,值得他们自己的文章。我们探索的步骤和技术是最常用和最流行的工作方法。
完成数据预处理后,可以将数据分为训练集、测试集和验证集,用于模型拟合和模型预测阶段。感谢阅读,祝你的模特好运!
资源/参考链接
电子商务行业中的数据科学和机器学习:内部人士谈论工具、用例、问题等等
机器学习已经毫无保留地吞没了我们的个人和私人空间,扩展到了只受我们理解能力限制的领域。曾经用于统计的数学模式现在正被用于理解和预测人类行为。
神经和语言计算的进步为复杂的应用开辟了道路,通过求解矩阵分解方程来增强用户体验和客户指控。产品/客户到产品/客户的关系可以在稀疏矩阵中映射出来,以深入研究购买模式,并应用顺序模式分析来获得对客户群的一致理解。尽管机器学习的基本思想(减少错误)保持不变,但成本函数却截然不同
更令人印象深刻的是,用于计算这些模式的算法还很不成熟,因此这些算法还有很大的完善空间。这些算法是计算密集型的,因为它们中的大多数处理使用高阶矩阵。
目前,大多数电子商务的特定应用围绕着客户细分模型、矩阵分解模型、市场购物篮分析等,偶尔使用最新技术(神经矩阵分解)的实现。
云平台也注意到了零售和电子商务行业中的机会,并推出了易于与 web 应用程序集成的服务/工具。这导致了旨在利用这些云服务为特定用例创建定制模型的多个白皮书的产生。
本文意在从一个数据科学家的角度给大家描绘一幅 电商行业 的图景。请继续阅读!
我作为电子商务数据科学家的典型一天
在电子商务领域,数据科学家的日常生活极具挑战性。你永远无法预测人类的行为,但你有责任去做。当然,你可以分析并获得关于顾客购买模式的随机灵感,也可以见证一个营销决策如何在一夜之间改变你的假设。但是没有什么能比得上看到你的工作节省时间,增加客户的参与体验,同时实现客户的愿景。
举一个假设的例子,一家中小企业的营销活动针对的是错误的客户群,并收到了令人难以接受的结果。尽管该公司没有意识到这一点,但快速的数据分析会指出这一点,并增加其接触适当客户的机会。你每天都能解决这样的问题,这很令人满意。
电子商务中的数据科学和机器学习用例是什么
作为一名在零售领域工作的数据科学家,你所有的首要目标都围绕着“客户”。咄!你可以获得客户,也可以留住客户。因此,选择和优化的问题。在大多数情况下,这两个问题都有独立的解决方案,但在一些罕见的情况下,您可以构建一个解决方案来解决这两个问题。尽管解决方案大致分为两类,但实现这些解决方案的方式却是多种多样的。我可以继续讨论用例,但是我将把这个部分限制在 3 个主要的用例上。
1.推荐引擎
推荐引擎是在线零售领域机器学习用例的缩影。就像知道你想要什么的销售人员一样,推荐引擎会得到你!它根据你过去的购买和互动来理解你,并给你个性化的建议。大多数推荐引擎使用的机器学习技术是矩阵分解算法。尽管背后的数学有点复杂(在下一节的矩阵分解部分会涉及到),但是推荐引擎所能达到的效果是无与伦比的。
推荐引擎可用于定制您客户的体验。您可以为任何客户端快速部署它,因为它们在不同的语言中都可以使用,比如 R、Python、WEKA 等。像网飞、YouTube、亚马逊等公司使用用 Python 构建的推荐引擎,可以很容易地与他们的微服务交互。推荐引擎还允许你携带其他客户的经验,并推荐客户周围的人正在购买的产品。对推荐引擎的唯一警告是高度研究的“冷启动”问题。您需要历史客户数据来构建推荐引擎。没有这一点,就无法构建一个复杂的推荐引擎。有一些变通办法和大量的研究正在着手解决这个问题。
2.客户细分
客户细分在很长一段时间内都被用于目标营销活动。基于客户之间的相似性(例如,地理相似性、购买力等),可以将他们聚集成群体,如忠诚客户、高消费群体等。简而言之,客户细分将客户分成更小的群体,这些群体具有适当的针对性。可以逻辑地或者使用机器学习算法来识别片段。后者几乎总是更有效,因为有时客户之间的相似之处并不明显。
简单地说,客户细分模型是通过聚类技术创建的。有许多可用的技术,但最常用的方法是使用 K-means 聚类技术。一旦集群被创建,高产集群被确定,并集中营销活动运行。识别这些集群需要对你要销售的产品的零售空间有深刻的理解。根据市场动态和全球经济变化,有时集群可能不会像预期的那样运行。因此,在使用客户细分时,你需要考虑风险因素。
3.隐马尔可夫模型
隐马尔可夫模型或 hmm 是数据科学用例的最新发展。它们有着广泛的应用,并且在推动洞察力方面非常富有成效。通过利用丰富的基于位置的数据来获得关于客户的见解,hmm 可用于检测基于位置的购买。HMM 从学习给定用户的位置序列和客户购买的最可能序列开始。概率分数被分配给新的购买,并且这些新的购买基于它们的可能性被推荐给客户。
hmm 还可以用于客户分离,其中它们可以通过马尔可夫序列分析(通过将隐藏状态分配给客户的消费活动)来捕捉客户行为的动态。hmm 也可以用来做流失建模和拖欠预测。使用 hmm 可以做很多事情,因为它们有助于验证客户的信誉,并基于动态数据挖掘预测行为。
零售客户可以使用多种数据科学工具和框架。本节分为三小节,涵盖各种算法、低代码工具和代码密集型工具。
电子商务行业使用的机器学习算法
1.矩阵分解
这种算法也称为矩阵分解法,用于有效地解决复杂的矩阵运算。随着使用神经元优化矩阵计算的深度学习技术的出现,一个简单的嵌入模型就可以完成这项工作。嵌入模型可以是基于用户的嵌入模型或基于产品的嵌入模型。使用神经网络的矩阵分解算法的一种广泛使用的实现是神经协同过滤模型(NCF)。NCF 是一种独特的基于深度学习的推荐引擎架构。它结合了标准矩阵分解的有效性以及神经网络的复杂性,以产生用户/项目的完整表示。
矩阵分解算法用于创建复杂的推荐引擎。矩阵分解模型创建了用户和他们交互过的产品之间的映射。以下面的表格为例,用户 1 购买口罩和消毒剂,而用户 2 购买燕麦片。创建具有这些参考的稀疏矩阵,并且基于用户之间的相似性向相应的新用户推荐这些产品之一。
用户/产品
面罩 | 消毒剂 | 燕麦片 | |
---|---|---|---|
虽然这是矩阵分解模型的一个非常简单的例子,但是实际的算法基本上没有什么不同。用户之间的相似性可以使用客户终身价值或交互得分(通常作为模型的辅助输入)等指标来计算。这些度量既可以手动计算,也可以通过其密集层之一留给神经协同过滤模型。NCF 自动识别用户-产品对,并基于生成的概率分数建议可能的产品。
2.使聚集
聚类是营销团队用来将客户分成逻辑部分(客户细分)的一种非常常用的算法。k 表示聚类是一种广泛使用的聚类变体,因为它在创建有意义的聚类方面非常有效。还有其他技术,如基于密度的聚类、基于网格的聚类等,但它们很少用于创建电子商务用例的模型。理论上,基于密度的聚类应该显示出最好的结果,但实际上 K 意味着聚类几乎总是优于它。
可视化集群的最佳方式是通过气泡。下面展示了如何使用气泡形成星团。
聚类取决于两个重要因素:
您希望创建的分段数(聚类数)
不同段之间的相似性(聚类之间的距离)
- 虽然最佳聚类的数量是数据科学家可以控制的,但聚类之间的距离取决于他们正在处理的数据。您可以使用剪影评分或 Davies-Bouldin 指数等技术来确定最佳聚类,但在某种程度上,您选择的方法将始终取决于您拥有的数据。聚类在帮助你识别可以用于目标营销的客户群方面做得很好。
- 3.分类
分类是一种常见的机器学习方法,有大量的用例。粗略定义的分类是根据历史数据将某些数据点归类的过程。这可以帮助我们将新用户分为潜在买家、忠实客户、购物车放弃者等。分类通常与电子商务用例的推荐引擎一起使用,因为单独的分类不能证明是有效的。矩阵分解使用分类变量(通常是将记录标记为销售或非销售的列)创建用户-产品对。然后,该信息被用于训练分类模型,以将特定的用户-产品对标记为销售或非销售。这可以用来有效地锁定那些最有可能促成销售的产品。
有一些问题陈述可以使用分类直接解决。例如,您的客户想要阻止不在您的网站上进行任何购买的 IP(称为“旁观者”)。旁观者通常无意购买,而且几乎总是不利于网上交易。把一个旁观者变成一个买家是一项不必要的任务,并且没有长期的收益。因此,一些服务器点击率有限的客户端可能会选择阻止 IPs。先发制人地对这些 IP 进行分类可以为在线业务省去很多麻烦。
现在你已经知道了电子商务用例中使用的不同算法,让我们深入到可以帮助你在网站上实现机器学习的工具中。主要有两类,第一类不需要专门的内部数据科学家,而第二类需要内部数据科学家。
在您的电子商务用例中实现机器学习的低代码工具(成本密集型)
1.GA360
Google Analytics 360 是目前最复杂的零售加速器之一。它很容易与 GCP 服务(如 BigQuery)集成,并可用于获取洞察力。GA360 还提供了一个基于启发式的分割模型。虽然它不是一个机器学习实现,但将 GA360 与 BigQuery 结合起来可以帮助您构建一个由用户交互驱动的推荐引擎。由于 GA360 捕捉诸如点击次数、在页面上花费的时间、点击/购买的产品等信息,因此可以根据这些数据点来建模高效的推荐引擎。当然,你将不得不为这两种服务支付高额费用,但这种结合的好处是,即使没有历史用户数据,你也可以定制你的用户体验。因此,这是一个完美的工具,为任何客户寻找建立自己的网上存在。
2.BigQueryML
BigQueryML 是谷歌最复杂的低代码机器学习方法之一,用于构建复杂的机器学习模型。尽管这种方法要求您拥有历史用户数据,但是您不需要担心构建一个好的推荐引擎所需的复杂实现。使用 BigQueryML,您需要做的就是指定您希望运行的矩阵分解的类型,并让 BigQueryML 为您管理一切。假设您的团队缺乏对大量矩阵分解变体的理解,或者假设您想要加快构建推荐引擎的过程,而不需要停下来了解它是如何工作的——输入 BigQueryML 推荐引擎。一个完全托管的服务,它不仅选择合适的模型,还负责部署模型并为您提供推理。权力越大,费用越大!这两种服务都很昂贵,需要相当长的时间才能开始产生回报。
许多电子商务网站都有一个手控聊天机器人,帮助客户进行查询,并根据概述的要求推荐产品。构建一个定制的聊天机器人是一项具有挑战性的任务,但有很多好处。Dialogflow 是一种非常方便的将对话式人工智能与网站、web 应用程序、移动应用程序等集成的方式。您可以使用 DialogFlow CX 来构建一个定制的聊天机器人,它可以很容易地与大多数零售用例集成。这是集成人工智能助手的最快方法之一,人工智能助手不仅可以为客户提供个性化的体验,还可以解决电子商务网站的问题,如购物车故障、购物车放弃、支付声明或交易失败等。DialogFlow 还支持多种语言,不需要数据科学家来配置。这个工具是谷歌云平台套件的一部分,因此不能免费使用。
4.使颗粒化
还记得我们在分类部分谈到的将用户分类为购买者和非购买者对企业的重要性吗?Granify 就是这么做的!它不仅通过识别不会购买产品的客户,还通过使用机器学习来诱使他们购买产品,从而帮助在线零售商。Granify 使用从分类、矩阵分解、图像处理等广泛的技术来准确地描绘客户旅程,并确定客户可能成为买家的最佳旅程点。他们确实有一个非常大胆的目标,即在实施的 90 天内实现大约 4%的收入增长,但这是一个可以使用的创新工具。Granify 不仅在你的零售网站上自动实施机器学习,而且还提供了分析到达你的网站的流量的巧妙方法,完全不需要数据科学团队。你所需要的是一群对他们的业务充满热情并对他们的客户群有深刻了解的人。
低代码方法是为您的在线业务实现方便的机器学习解决方案的快速方法。但这是以向第三方公开/共享您的客户信息为代价的。虽然他们中的大多数都有不使用个人身份信息的政策(PII),但一些客户更进一步,雇佣内部数据科学家来创建他们的定制集成。对于此类用例,在为您的零售客户构建解决方案时,以下工具/技术会派上用场
在您的电子商务用例中实现机器学习的代码密集型工具(经济高效)
TensorFlow 是一个开源的 Python 库,用于创建深度学习机器学习模型。该库的一个非常具体的变体是在 TensorFlow 模型花园中实现神经矩阵分解。这是迄今为止实现复杂的协同过滤推荐引擎最快的方法。因为它是开源的,所以可以免费实现,并且很容易与大多数基础设施集成。但是需要一个强大的 Python 开发人员和一个 ML 工程师在生产环境中训练和部署 NeuMF 模型。
NCF 是用于推荐的协同过滤的通用框架,其中神经网络体系结构被用于对用户-项目交互进行建模。不同于传统的模型,NCF 不求助于矩阵分解(MF)与用户和项目的潜在特征的内积。它用多层感知器取代了内积,可以从数据中学习任意函数。
NCF 的两个实例是广义矩阵分解(GMF)和多层感知器(MLP)。GMF 应用线性核来模拟潜在的特征相互作用,而 MLP 使用非线性核从数据中学习相互作用函数。NeuMF 是 GMF 和 MLP 的融合模型,以更好地建模复杂的用户-项目交互,并统一了 MF 的线性和 MLP 的非线性的优势,用于建模用户-项目潜在结构。NeuMF 允许 GMF 和 MLP 学习单独的嵌入,并通过连接它们的最后一个隐藏层来组合这两个模型。虽然 NeuMF 在 JavaScript 中没有直接实现,但是随着 TensorFlow Js 的出现,您可以将 TensorFlow NeuMF 代码直接导出为 JavaScript 对象,并将其与您的电子商务网站集成。但是请记住,NCF 模型通常很大,需要在您的服务器上有一个专用的存储容器。
Python 是创建机器学习模型和人工智能应用程序最常用的编程语言之一。虽然 Python 本身有许多框架来帮助构建电子商务网站(例如 Flask),但它通常用于使用 SKLearn、TensorFlow、Pytorch、Theano 等库来构建、训练和部署复杂的模型。Python 还打开了构建自然语言处理模型或创建聊天机器人框架的大门。
借助强大的数据科学团队,您可以构建最适合客户用例的定制机器学习模型。此外,一些电子商务网站很容易使用基于 Python 的 web 框架来构建。这样的网站将很容易与你基于 python 的机器学习模型集成。您还可以围绕节点服务器创建包装器,或者使用双节点 Python 服务器来部署您的模型。还可以创建一个专用的微服务或 API,从您的模型中生成推理。因此,使用 Python 的可能性是无限的。
与其他行业有什么不同?
作为一名与零售客户打交道的数据科学家,很难忽视零售领域的独特方面。电子商务行业在很大程度上依赖于客户的互动,而客户是这一切的中心。有人可能会说,你需要一个现有的供应链,一个创新的产品,对该产品的需求,等等,但无论有没有必要的先决条件,一个电子商务网站需要客户访问网站并与之互动。只要你能为你的网站带来流量,你就已经成功了一半。以下一组属性将电子商务行业与任何其他行业区分开来
互联网
互联网是一个巨大的空间,任何人/每个人都在上面。你客户的竞争对手可能在上面,你的潜在买家可能在上面,或者一个阅读这篇文章的技术专家可能在上面。这有一种两重性:你的客户群几乎是无限的,但相比之下,你的买家是微不足道的。这是一个相当大的难题,因此为目标营销、区域限制等开辟了道路。任何初创企业/中小企业(SME)的一个经验法则是,它们不应该增长太快。在互联网上,你无法控制观众。因此,随着顾客的突然到来,你的生意很有可能蒸蒸日上。如果没有合适的基础设施,这可能会产生不利影响。基于互联网的服务的另一个方面是顾客评论像火一样传播。还记得 MySpace 吗?你们中的一些人肯定没听说过 MySpace,但它就是今天的脸书。你在任何其他行业都看不到如此不稳定的客户群!
个性化
众所周知,电子商务行业提供定制体验。让顾客觉得自己与众不同是一种强有力的策略,而且非常有用。没有它是一个明确的失望,并可能导致客户流失。而且你不为体验向顾客收费!这在其他任何行业都很少见。个性化几乎总是一种附加产品或“奢侈”产品。但是对于电子商务行业来说,这是必须要做的事情!
客户范围
预测一个顾客是否能够/愿意购买你的产品只有在网上零售行业才有可能。如果使用得当,网上零售业务可以接触到正确的观众,而不用迈出第一步。这是因为网上有大量的客户。今天,每个人都可以以某种形式访问互联网。互联网上的人数只会增加。这为一般的在线零售商创造了一个更大的接触人群的媒介。将社交媒体加入其中,你就有了一个合适的组合,可以接触到你的受众,而不用花钱在昂贵的实体广告牌上。
分析学
虽然这不是电子商务特有的,但它被在线企业大量使用。事实上,分析的诞生可以追溯到互联网泡沫。分析作为一个领域在零售企业,尤其是在线零售企业中非常普遍。这是因为在线零售商不仅拥有更大的覆盖范围,而且拥有将顾客立即转化为买家的媒介。
搜索引擎排名
搜索引擎排名是一个有争议的问题。这是有争议的,因为要想排名更高,你必须遵守某个营销集团的规则。这些规则通常冗长且不总是一致的。为什么在搜索引擎上排名靠前很重要?普通人的注意力持续时间每年都在急剧下降。这导致一大群人查看呈现给他们的前 4-5 个链接。因此,这是一个相当独特的挑战,因为你不只是在与你的竞争对手竞争,而是与整个互联网竞争。
刚开始做电商最让我惊讶的是什么?
除了这些不同点,电子商务是最酷的数据科学行业之一。我总是惊讶于一个简单的网站如何能够成为几个不同的机器学习微服务的高潮——所有这些服务一起工作以提供整体体验。应用不仅限于一个研究领域。你可以使用计算机视觉、自然语言处理、深度学习、模糊逻辑等等。
令我惊讶的是,电子商务运营转移到云端的速度有多快。在电子商务领域有大量业务的大型零售客户要么提出他们的云基础设施(咳咳!亚马逊)或将他们的整个基础设施转移到一个新兴的云服务提供商(沃尔玛转移到谷歌)。电子商务不再是一个由 Web 开发者驱动的行业。这让我对我能够处理的不同用例有了新的认识。
电子商务行业为自己开辟了一个利基市场,为就业和创新创造了大量空间。虽然这是一个让大型零售商获得更大客户群的空间,但也为小型在线企业推广其产品/服务创造了机会。我一直相信歌利亚粉碎大卫·习语,一个巨大的企业集团最终会通过大规模生产他们的产品来粉碎一个小企业。但是我已经看到许多小企业由于他们的在线存在而蓬勃发展。他们中的一些人利用基本的数据科学技术来接触他们的受众,而其他人则使用第三方广告工具来增加他们网站的流量。
虽然可以写一篇单独的文章来回答这个问题,但零售领域永远不会停止给你带来惊喜。
作为电子商务领域的数据科学家,最大的挑战是什么?
作为在线企业的数据科学家,最具挑战性的任务之一是精心设计一个成立的假设!在任何行业中,提出一个假设通常都是相当具有挑战性的,但是由于电子商务行业的动态性质及其完全不可预测的性质,一个经过深思熟虑的假设往往会失败。它失败不是因为不正确的假设或缺乏所有变量的因素;它之所以失败,是因为客户行为的根本转变。那可能是你需要经常重建和重新部署一个机器学习模型。
另一个挑战是电子商务客户有非常不同的业务需求。这产生了一个尖锐的学习曲线,重叠范围非常小。而客户终身价值、市场篮子分析等基本指标和策略保持不变。它们对特定业务的实现取决于该业务的目标和期望。因此,领域知识只能被部分重用。
另一个挑战是用户个性化选项的饱和。虽然基于 UI 的个性化非常多,但用于增强客户体验的机器学习用例几乎总是推荐引擎。构建推荐引擎永远不会出错,但大多数在线企业都会雇佣数据科学家来构建某种形式的推荐引擎。对一些人来说,这似乎不是一个挑战,但它必须达到一个饱和点。
结论
我希望这篇文章能够让您对电子商务行业有所了解。有许多数据科学用例可供您开始使用。我在下面提供了几个链接,以增强你对我提到的一些概念的理解。更令人兴奋的是,电子商务行业几乎总是在招聘数据科学家。喜欢这篇文章的某些方面,还是想让我详细说明某些方面?请提供您的宝贵反馈
资源:
请务必阅读这篇文章,并在你的网络中分享。
Another challenge is the saturation of options for user personalization. While UI based personalizations are plenty, a machine learning use case for enhancing customer experience is almost always a Recommendation Engine. You can never really go wrong with building a Recommendation Engine but most online businesses hire Data Scientists to build some form of recommendation engine. This might not seem like a challenge to some but it’s got to reach a point of saturation.
Conclusion
I hope this article was able to give you a few insights into the E-commerce industry. There are a lot of Data Science use cases out there that you can start and get your hands dirty with. I have provided a few links below to enhance your understanding of some of the concepts I touched upon. What’s even more exciting is that the E-commerce industry is almost always hiring for a Data Scientist. Like something about the article or want me to elaborate on something? Please do provide your valuable feedback
Resources:
Do read this and share it across your network.
医疗行业中的数据科学和机器学习
数据科学是目前 IT 领域发展最快的领域之一。世界各地的公司都在试图采用数据科学和机器学习并将其整合到他们的系统中。
在本文中,我们将探索数据科学和机器学习如何在医疗行业的不同领域中使用。
正如一句古老的谚语所说,预防胜于治疗,新技术在这两方面都有帮助。想象一下,如果一个医生可以查看你的病史,运行一个数学公式,并预测你可能会得什么病,什么时候会得。
或者如果医生能告诉你身体的哪一部分会恶化,恶化的速度有多快,以及你现在的生活方式。人工智能可以让这一切成为可能。
医药和医疗保健是实施革命性数据科学解决方案的大有可为的行业。技术正在将医学带到一个全新的水平,从计算机化医疗记录到药物发现和治疗后的病人监测。而这仅仅是开始。
“要成为一名优秀的诊断医生,医生需要获得大量的疾病标签,每一个标签都绑定了对疾病及其症状的想法、可能的前因后果以及治愈或转移疾病的可能干预措施。”–丹尼尔·卡内曼
受数据科学和机器学习影响的医疗保健领域
数据管理和隐私
随着组织采用机器学习作为工具来发现模式,从数据中提取知识并处理各种计算困难的任务,以相同的一致性管理和存储数据变得非常重要,没有任何错误。
当数据以相同的一致性(相同的结构格式)存储时,数据科学家和分析师可以使用它来发现模式和趋势,并挖掘手动分析无法发现的信息。
医疗保健行业的数据管理也不例外。它提供隐私和安全性,如果训练得当,它还可以防止攻击和盗窃。
例如,可以训练机器学习和深度学习模型来检测传入数据中的模式。如果它包含任何未经医生或医务人员授权的信息,它可以冻结传入的过程,验证它,并在人工监督的帮助下做出决定。
通过这种方式,我们并没有放弃人类的努力,而是将机器和人类的智慧结合起来,以更好地做出决策。
一个有趣的研究领域是使用深度学习来识别、标记和屏蔽 PII(个人可识别信息)数据。正则表达式和静态规则可以用于此目的,但使用深度学习可以学习组织中使用的特定格式(甚至自定义 PII 类型)。
卷积神经网络(CNN)已经成功地用于图像识别,因此探索它们对于 PII 顺应性的使用是另一种有趣的可能性。
数据科学家还可以使用机器学习和深度学习来建立基线,即通过监控相关属性或特征来确定系统的“正常”行为。然后,他们可以使用基线来检测异常。
这可以防止盗窃,并在医务人员从任何系统检索数据时提供强大的保护,以及防止医疗机构内外的黑客攻击。模型可以控制数据是否由授权人员检索。
最后,技术可以用来存储具有适当的一致性和结构格式的信息,没有任何错误。有了适当的数据一致性,数据科学家和分析师可以更轻松地处理疾病预防、诊断、预测分析、治疗、药物研发等问题。
机器学习如何预防疾病
机器学习可以为我们提供非常困难的问题的答案,比如我们如何防止特定疾病的爆发?这种疾病还有哪些未被发现的症状?在寿命方面对生活有什么影响?
有了大量的数据在手,数据科学家可以使用机器学习来寻找被标记疾病的患者的各种属性和特征之间的相关性。这些相关性可以帮助医生了解疾病的潜在模式,并提出预防计划。
例如,社交媒体消息可以用来发现潜在的传染病。在数据预处理阶段,提取具有用户和时间信息的社交媒体消息。
接下来,提出了一个无监督的情感分析模型。在训练期间,该模型可以从社交媒体数据中提取关于症状、身体部位、疼痛持续时间、疼痛前的先前活动以及疼痛位置的关键信息和相关性。
最后,从个体的症状加权向量中检索潜在传染病相关信息。
一旦机器学习模型提取了信息,医生就可以推荐适当的医疗常规,不仅可以减少患者的经济支出,还可以减少患肿瘤等更严重疾病的几率。
不在早期治疗症状或疼痛不仅对患者的健康而且考虑到经济成本都是非常危险的。随着疾病的发展,治疗费用也在增加。从这个意义上说,数据科学可以在优化医疗支出方面发挥巨大作用。
机器学习如何帮助诊断
医疗诊断是医疗保健中非常具有挑战性的一部分。统计数据显示,如果患者在更短的时间内得到治疗,他们有更大的机会保持健康。但是治疗依赖于诊断报告,对医生来说,分析数百份报告可能是一项单调乏味的任务。
最近,医院已经开始使用机器学习来加快诊断和分析的过程。现在,医生可以在诊断中获得支持,以尽快达到治疗阶段。
随着机器学习被用于分析诊断报告或 CT 扫描,发现异常甚至恶性细胞可以以超人的完美水平完成。
由机器学习模型创建的报告和建议由专家医生进行审查,并支持他们为患者做出正确的决定。
通过这种方式,医生可以识别和优先考虑健康状况最严重的患者,并提高他们预防可避免疾病的成功率。
机器学习如何帮助 T2 治疗
有了更多关于个体患者特征及其症状的数据,就有可能提供精确的处方和高度个性化的护理。
机器学习系统被证明是医生和护士的一个很好的工具。有了精确的处方,患者出现药物副作用的可能性就更小了,因为治疗是根据患者的需求专门设计的。
国际基因组样本资源是一个庞大的人类变异和基因型数据数据库,这些数据与冠心病和糖尿病等常见疾病相关。像这样的数据使得提高个性化医疗保健的质量成为可能。
数据科学家也在帮助将其他研究领域与医学和健康科学相结合,以提供更好的治疗患者的方法。
例如,在查看运动员的医疗记录时,数据科学家可以发现患者要求的独特模式和相关性,例如运动员关节的承重能力远远好于正常人。
数据科学家可以使用这些模式和异常从材料科学的分支中找到合适的解决方案。这种情况的一个例子是发现金属材料,如 Ti 及其合金,具有高机械强度和断裂韧性,因此它们可以在临床上用于修复高负荷条件下的硬组织(骨骼和关节)。
有了这样的发现,数据科学家可以为医生提供新的治疗思路。
如何在预测分析中使用机器学习
这是健康分析中最受欢迎的话题之一。你可以向机器学习模型提供历史数据,训练它找出模式并从中生成准确的预测。它发现症状、习惯、疾病的相关性和关联性,并做出有意义的预测。
医生可以借此通过患者的生活方式、饮食习惯,通过各种活动来预测各种疾病。
预测分析在提高供应链和医药物流的效率方面发挥着重要作用。模型可以预测特定医院对药品物流的本地需求,以避免在紧急情况下出现药品短缺。
医生可以预测患者健康状况的恶化,并提供预防措施,如开始早期治疗,以降低患者病情恶化的风险。
像苹果或耐克这样的大公司在他们的可穿戴设备中使用预测分析,来测量心率、呼吸频率、睡眠周期等等。
这种测量让人们了解他们的身体正在发生什么,软件可以预测他们的训练是否是最佳的,以及他们需要多少卡路里和休息。
药物发现
根据研究和统计,一种药物上市需要花费高达 26 亿美元,耗时 12 年。自从大数据和机器学习出现以来,科学家们已经能够更快地模拟药物与身体蛋白质和不同类型的细胞和条件的反应。这使得药物开发时间更短,获得美国食品药品监督管理局批准的可能性更大。
科学家们正在利用这项技术开发疫苗,以解决冠状病毒引起的持续全球健康危机。
在最近一篇题为“与新冠肺炎相关的蛋白质结构的计算预测”的论文中,谷歌 DeepMind 团队使用一个名为 AlphaFold 的人工智能系统预测了几个正在研究中的与新型冠状病毒相关的蛋白质。
研究小组表明,这些结构为理解冠状病毒的功能提供了重要的资源。这只是数据科学家如何使用机器学习来预测各种蛋白质结构,并使用它来理解和开发疫苗的一个例子。
另一个例子来自葛兰素史克。他们使用机器学习进行临床试验,以加快药物发现过程。
初创公司正在筹集大量投资,以加快药物发现和测试过程。BenevolentAI 是一家总部位于伦敦的独角兽公司,已经筹集了 1 . 15 亿美元来启动 20 多个药物项目,并创建了一个“生物科学机器大脑,专门用于发现新药和疾病治疗方法
它今年在欧洲和美国的首次临床试验将解决帕金森病患者白天过度嗜睡的问题。
治疗后监测
在任何类型的手术或治疗后,都有并发症和复发疼痛的风险,有时甚至会有副作用。一旦病人离开医院,这可能很难处理。
远程家庭监护帮助医生与患者保持实时联系。对病人来说非常划算,还能腾出医院的空间。
英特尔的 Cloudera 软件根据 EMR 数据和医院所在地的社会经济状况,帮助医院预测患者在未来 30 天内再次入院的几率。
SeamlessMD 的多模式术后护理平台使新泽西州的圣彼得医疗保健系统将术后平均住院时间缩短了一天,为每位患者平均节省了 1,500 美元。
患者所要做的只是回答应用程序中的几个问题,机器学习软件可以指导他们做出适当的反应。
虚拟协助
借助疾病预测建模和自然语言处理(NLP)的进步,数据科学家可以构建一个全面的虚拟平台,为患者提供帮助。
在这些平台和机器学习算法的帮助下,患者可以输入他们的症状,并获得对各种可能疾病的见解,以及他们需要遵循的治疗的全面总结。
患有抑郁症或焦虑症等心理问题以及阿尔茨海默氏症或帕金森氏症等神经退行性疾病的患者,可以利用虚拟应用程序来帮助他们完成日常任务。
虚拟助理的一个流行例子是Ada——一家位于柏林的初创公司,它根据用户的症状预测疾病。还有 woe bot——斯坦福大学开发的聊天机器人,为抑郁症患者提供治疗。
自从 COVID 爆发以来,许多初创公司都在开发可以帮助你在日常生活中找到平衡的应用程序。 Balance 是帮助你冥想以消除焦虑和增加注意力的应用程序之一。
Zenia 是另一款提供指导瑜伽和健身的 app。该应用程序基本上通过网络摄像头跟踪你的位置和姿势,并预测一条线段来显示你的姿势有多正确。
推荐系统
推荐系统非常有用。它们不会取代人工干预,而是增强了人工干预,并为人类提供了做出更明智决策的工具。
放射科医生可以使用机器学习通过分割暴露恶性细胞,并用算法的建议支持他们的决定。
同样,机器学习算法可以使用 NLP 来推荐最适合患者的处方、治疗、医疗保健程序和饮食。医生和护士可以查看算法的建议,并做出更好的决策。
推荐系统也可以通过聊天机器人带到移动设备上。
患者可以输入他们的担忧,并回答聊天机器人提出的问题。一个算法可以根据患者的历史数据、医疗数据、先前的答案等等来评估答案,并推荐一套个性化的解决方案。
医疗保健和医学研究中的工具、库和框架
算法
- 变分自动编码器
- 通常在表示学习中使用,变分自动编码器(VAE)是相对较新的无监督神经网络,它学习特征空间上的分布。VAEs 用于寻找重要的特征或表示;数据中的递归模式。除此之外,它们还用于检测异常值、聚类、和数据重构。
- vae 还用于降维,将高维数据转换为低维数据。通过降维,理解和解释数据变得更加容易。
- 分割
- 分割算法用于突出地面真相或目标。这对于在 CT 扫描中检测和突出恶性细胞非常有用。
- 使聚集
- 当处理大量数据时,通常很难标记数据、理解数据和解释数据,因此我们尝试根据可能性将它们分开,即以相似的概率分布排列它们。有各种各样的聚类算法,其中一些是 tSNE 和 VAE。
- 图像分类
- 图像分类是一种监督学习算法。它用于对不同的数据组进行分类。一般来说,它识别模式并将它们分配给给定的组或类。
- 自然语言处理
- 自然语言处理(NLP)是分析文本数据,并根据分配的任务返回输出。NLP 主要用于完成句子、预测下一个单词或句子、文本摘要、文本翻译。
- 在医疗行业,它对生成处方、根据、诊断、自动生成报告使用图像到文本生成等非常有帮助。
- 文本摘要
- 如前所述,文本摘要是一项 NLP 任务。顾名思义,它接受文本数据并将其汇总到给定的长度。当患者从一个医生转移到另一个医生时,或者甚至当患者被转移到不同的医院或完全转移到不同的治疗时,浓缩患者的报告非常有用。
- 文本翻译
- 有时,专科医生可能接受过其他语言的培训,或者患者可能来自土著背景,他/她不能理解英语,在这种情况下,文本翻译可以帮助将报告从一种语言翻译成另一种语言。
面向医疗保健行业的 Python 库
- Tensorflow
- Tensorflow 或 tf 是 Google 开发的。它提供了来自 Google 机器学习社区的良好教育支持,并被广泛用于构建简单和复杂的神经网络。
👉检查海王星与 TensorFlow 的集成
- Tensorflow 或 tf 是 Google 开发的。它提供了来自 Google 机器学习社区的良好教育支持,并被广泛用于构建简单和复杂的神经网络。
- 张量流概率
- 张量流概率建立在最近开发的张量流的基础上。它过去常常在现代硬件(TPU、GPU)上结合概率模型和深度学习。主要用于数据科学家、统计学家、ML 研究人员以及希望对领域知识进行编码以理解数据并做出预测的从业者。
- PyTorch
- PyTorch 是一个科学计算框架,广泛支持机器学习算法。基于 Lua 的脚本语言为深度学习提供了广泛的算法,并使用脚本语言 LuaJIT 和底层 C 实现。
- 咖啡
- 与 TensorFlow 一样,Caffe 是另一个用于构建表达性深度学习项目的 python 库。
- Open3d
- Open3d 是一个用于处理 3d 数据的 python 库。这是非常有用的可视化和分析 CT 扫描。
- Matplotlib 和 Seaborn
- OpenCV
- OpenCV 用于图像处理和转换,如裁剪、调整大小、颜色转换、整形等。
- Numpy
- Numpy 是一个科学的 python 库,用来做复杂的数学,尤其是线性代数和矩阵。事实上,像 OpenCV 和 Open3d 这样的图像处理库,大部分都是建立在 NumPy 之上的。
- 十四行诗
- Sonnet 是 Deepmind 围绕 TensorFlow 打造的深度学习库。它提供了专门为他们的研究需求而设计的特性,并且已经被他们和研究团体广泛使用。
医疗保健行业使用的框架
- 脸书的《Pytorch》
- PyTorch 框架拥有构建任何灵活而强大的深度学习模型所需的所有基本库,如 Torch、PIL、NumPy 等,尽管它缺乏教程,但它在 Pytorch 论坛中得到了社区的积极支持。
- 该框架本身提供了许多扩展,如图像处理和建立深度神经网络所需的所有广泛的数学公式。
- 还值得注意的是,因为它是建立在 CUDA 之上的,所以它可以直接访问 NVIDIA GPUs(如果可用的话)。
- Keras
- 构建于 TensorFlow 之上,为初学者教程和大型活动社区提供了基础。像 Pytorch 一样,当与 Google Colab 一起工作时,它也提供了对带有额外 TPU 的 GPU 的访问。
- Deepmind 的极致
- Acme framework 在 Deepmind 中广泛使用,尽管在公共场合使用的不多。值得注意的是,它是一个专门基于 TensorFlow 构建的可定制框架。
在日常应用中使用数据科学和机器学习的公司
许多公司在他们的研究和产品中使用数据科学和机器学习。以下是在其医学研究和产品中使用机器学习的 10 家公司的列表:
- 谷歌/Deepmind
- Deepmind 是一家研究公司,2020 年 11 月 30 日,该公司通过名为 AlphaFold 的算法,在确定蛋白质链的 3D 形状方面取得了科学突破,从而转变了生物学。
- IBM 沃森医疗保健
- IBM Watson Healthcare 旨在为医疗工作者提供工具和服务,旨在帮助他们从数据中获得更多见解,并简化他们的操作。
- 他们使用人工智能驱动的解决方案来快速筛选数据,并做出快速而适当的决策。
- 斑马医疗视觉
- 对医学影像服务的需求不断增加,超过了合格放射科医生的供应,并使他们在不影响患者护理的情况下获得更多产出。Zebra-Med 旨在为放射科医生提供工具,帮助他们更有效地理解 CT 扫描。
- 肯西
- KenSci 面向数字健康和医疗保健解决方案的人工智能平台,为人工智能和商业智能应用提供数据管理系统。他们主张为实验模型开发以及测试和生产管理带来一套丰富的人工智能开发功能。
- 帕泰
- PathAI 正在开发技术,帮助病理学家在任何时候为每个患者做出快速准确的诊断。除此之外,他们还分析和预测新疗法对患者的益处,使可扩展的个性化医疗成为现实。
- PathAI 由 Gat es 基金会资助。
- 项目内眼
- 正如他们网站上所述,“InnerEye 项目的目标是使医学图像分析的人工智能民主化,并使研究人员、医院、生命科学组织和医疗保健提供商能够使用微软 Azure 构建医学成像人工智能模型”。
- Project InnerEye 是微软的一个项目,使用人工智能来诊断眼睛感染和疾病。在微软举办的一次会议上,微软首席执行官塞特亚·纳德拉说“……我们正在追求人工智能,以便我们能够赋予每个人和每个机构以人工智能工具,使他们能够继续解决我们社会和经济中最紧迫的问题。这就是追求。
- Insitro
- Insitro 提供:
- 对药物发现和开发的更好预测
- 大规模整合机器学习和生物学
- 跨学科合作,如生物学家、工程师和科学家。
- 重新想象药物发现和开发
- Insitro 提供:
- 音乐会
- ConcertAI 将其使命描述为“通过与领先的生物医学创新者、医疗保健提供商和医学协会合作,通过领先的真实世界数据、人工智能技术和科学专业知识,加速对患者的洞察和结果。
- 有序
- 有序是一个有趣的公司。它使用人工智能来纠正数据,使其在医疗使用中变得可靠。这使得诊断和治疗过程顺利。
- 启蒙
- Enlitic 是一家利用数据推进医疗诊断的公司。通过将放射科医生与数据科学家和工程师配对,他们收集并分析了世界上最全面的临床数据,开创了医疗软件,使医生能够更快地诊断,并享有盛誉。
结论
数据科学和机器学习正在将医学推进到一个新的领域。想想它能去哪里,就很兴奋。在未来几天,嵌入式机器学习专业知识将非常常见,它可以实时分析患者状态,在多个医疗保健系统中类似患者的情况,正在进行哪些适用的临床试验,以及新治疗方案的疗效和成本。
几年前仅仅是一个想法的机会和治疗现在正在成为现实。我们生活在机器学习的时代,算法可以通过分析我们的数据来支持我们预防和治疗疾病,并帮助医生做出更好的决策。
机器学习正在为越来越多的医生、护士和医疗保健工作者配备许多新工具,使他们能够更好地照顾病人。作为。弗朗西斯·皮博迪博士几年前说过,“护理病人的秘密在于护理病人”。当机器接管更多任务时,人类可以做他们最擅长的事情——照顾和提供帮助。
尼尔什·巴拉
我是最近一家初创公司 perceptronai.net 的创始人,该公司旨在通过我们的深度学习算法提供医疗和材料科学方面的解决方案。我也阅读和思考了很多。有时我把它们以绘画或音乐的形式表现出来。当我需要喘口气时,我会去跑步。
阅读下一篇
在 AILS 实验室建立可扩展的医学 ML 研究工作流程[案例研究]
8 分钟阅读| Ahmed Gad |发布于 2021 年 6 月 22 日
AILS Labs 是一个生物医学信息学研究小组,致力于使人类更加健康。这个任务就是建造模型,也许有一天可以拯救你的心脏病。它归结为应用机器学习来基于临床、成像和遗传学数据预测心血管疾病的发展。
四名全职和五名以上兼职团队成员。生物信息学家、内科医生、计算机科学家,许多人都有望获得博士学位。正经事。
虽然业务可能是一个错误的术语,因为面向用户的应用程序还没有在路线图上,但研究是主要的焦点。研究如此激烈,以至于需要一个定制的基础设施(花了大约一年时间建造)来从不同类型的数据中提取特征:
- 电子健康记录(EHR),
- 诊断和治疗信息(时间-事件回归方法),
- 图像(卷积神经网络),
- 结构化数据和心电图。
通过融合这些特征,精确的机器学习模型可以解决复杂的问题。在这种情况下,这是心血管一级预防的*风险分层。*本质上,它是关于预测哪些患者最有可能患心血管疾病。
AILS 实验室有一套完整的研究流程。每个目标都有七个阶段:
- 定义要解决的任务(例如,建立心血管疾病的风险模型)。
- 定义任务目标(例如,定义预期的实验结果)。
- 准备数据集。
- 使用 Jupyter 笔记本以交互模式处理数据集;快速试验,找出任务和数据集的最佳特性,用 R 或 Python 编码。
- 一旦项目规模扩大,使用像 Snakemake 或 Prefect 这样的工作流管理系统将工作转化为可管理的管道,并使其可重复。否则,复制工作流程或比较不同模型的成本会很高。
- 使用 Pytorch Lightning 与 Neptune 集成创建机器学习模型,其中应用了一些初始评估。记录实验数据。
- 最后,评估模型性能并检查使用不同特征和超参数集的效果。
扩大机器学习研究的 5 个问题
AILS Labs 最初是由一小群开发人员和研究人员组成的。一个人编写代码,另一个人审查代码。没有太多的实验。但是协作变得更具挑战性,随着新团队成员的到来,新问题开始出现:
- 数据隐私,
- 工作流程标准化,
- 特征和模型选择,
- 实验管理,
- 信息记录。
容器中的数据科学和机器学习
原文:https://web.archive.org/web/https://neptune.ai/blog/data-science-machine-learning-in-containers
当构建数据科学和机器学习驱动的产品时,研究-开发-生产工作流不像传统软件开发那样是线性的,在传统软件开发中,规格是已知的,问题(大部分)是预先了解的。
这涉及到大量的试验和错误,包括新算法的测试和使用,尝试新的数据版本(并管理它),为生产包装产品,最终用户的观点和看法,反馈循环,等等。这使得管理这些项目成为一项挑战。
如果您想确保您的应用程序能够实际工作,那么将开发环境与生产系统隔离开来是必须的。因此,将您的 ML 模型开发工作放在(docker)容器中确实有助于:
- 管理产品开发,
- 保持环境整洁(并使其易于重置),
- 最重要的是,从开发到生产变得更加容易。
在本文中,我们将讨论机器学习(ML)产品的开发,以及使用容器的最佳实践。我们将讨论以下内容:
- 机器学习迭代过程和依赖性
- 所有阶段的版本控制
- MLOps 与 DevOps
- 需要相同的开发和生产环境
- 容器要素(含义、范围、docker 文件和 docker-compose 等。)
- 容器中的 Jupyter 笔记本
- TensorFlow 在容器微服务中的应用开发
- GPU 和坞站
你需要知道的是
为了充分理解机器学习项目在容器中的实现,您应该:
对 Docker 软件开发有基本的了解,
- 能够用 Python 编程,
- 能够用 TensorFlow 或者 Keras 建立基本的机器学习和深度学习模型,
- 部署了至少一个机器学习模型。
- 如果您不了解 Docker、Python 或 TensorFlow,以下链接可能对您有所帮助:
机器学习迭代过程和依赖性
学习是一个反复的过程。当一个孩子学习走路时,他会经历一个重复的过程:走路、跌倒、站立、行走等等——直到他发出“咔嗒”声,他就可以自信地走路了。
同样的概念适用于机器学习,并且有必要确保 ML 模型从给定的数据中捕获正确的模式、特征和相互依赖性。
当你在构建一个 ML 驱动的产品或应用时,你需要为这种方法中的迭代过程做好准备,尤其是机器学习。
这种迭代过程不仅限于产品设计,而是涵盖了使用机器学习的产品开发的整个周期。
算法做出正确业务决策所需的正确模式总是隐藏在数据中。数据科学家和 MLOps 团队需要投入大量精力来构建能够执行这项任务的强大 ML 系统。
迭代过程可能会令人困惑。根据经验,典型的机器学习工作流应该至少包括以下阶段:
数据收集或数据工程
- 探索性数据分析
- 数据预处理
- 特征工程
- 模特培训
- 模型评估
- 模型调整和调试
- 部署
- 对于每个阶段,都直接或间接地依赖于其他阶段。
下面是我如何基于系统设计的层次来看待整个工作流程:
**模型级别(拟合参数):**假设已经收集了数据,完成了 EDA 和基本预处理,当您必须选择适合您试图解决的问题的模型时,迭代过程开始。没有捷径可走,你需要迭代一些模型,看看哪个模型最适合你的数据。
- **微观层面(调整超参数):**一旦您选择了一个模型(或一组模型),您就可以在微观层面开始另一个迭代过程,目的是获得最佳的模型超参数。
- **宏观层面(解决你的问题):**你为一个问题建立的第一个模型很少会是最好的,即使你通过交叉验证对它进行了完美的调整。这是因为拟合模型参数和调整超参数只是整个机器学习问题解决工作流程的两部分。在这个阶段,需要迭代一些技术来改进您正在解决的问题的模型。这些技术包括尝试其他模型,或集合。
- **元级别(改进您的数据):**在改进您的模型(或训练基线)时,您可能会发现您正在使用的数据质量很差(例如,贴错标签),或者您需要对某一类型进行更多的观察(例如,夜间拍摄的图像)。在这些情况下,改善数据集和/或获取更多数据变得非常重要。您应该始终保持数据集尽可能与您正在解决的问题相关。
- 这些迭代总是会导致系统中的大量变化,因此版本控制对于高效的工作流和可再现性变得非常重要。
所有阶段的版本控制
版本控制是一种系统,它记录一段时间内对一个文件或一组文件的更改,以便您可以在以后调用特定的版本。由于 ML-powered 产品开发中涉及的迭代过程,版本控制已经成为产品成功以及未来维护或优化的关键。
ML 工作流中的文件,以及笔记本、数据集、脚本文件等系统,它们都需要版本控制。
根据您的团队的偏好,有许多工具和最佳实践来对这些文件进行版本控制。我来分享一下最适合我的。
通常,您将使用版本控制系统,如 Git、Apache Subversion (SVC)或并发版本系统(CVS)。但是,由于 ML 工作流中使用的文件类型,只使用其中一个系统可能不是机器学习项目的最佳选择。最好添加其他有用的工具来有效地对每个文件进行版本控制。
**数据版本化:**大多数公司将数据存储在数据库或云存储/桶中,如亚马逊 S3 桶或谷歌云存储,在需要时可以提取数据。
提取样本以最好地代表您试图解决的问题可能是迭代的,并且对用于训练机器学习模型的数据进行版本化变得很重要。
您可以推送到版本控制平台的文件的容量和大小是有限制的,有时,您将处理的数据以千兆字节为单位,因此这不是最好的方法。
有了像 DVC 和海王星这样的工具,数据版本控制变得更加容易。以下是一些帮助您开始使用数据版本控制的有用链接:
笔记本版本: Jupyter、Colab 笔记本生成的文件可能包含元数据、源代码、格式化文本和富媒体。
不幸的是,这使得这些文件不适合传统的版本控制解决方案,传统的版本控制解决方案最适合纯文本。这些笔记本的问题在于它们是人类可读的 JSON。ipynb 文件。直接编辑 JSON 源代码并不常见,因为其格式非常冗长。很容易忘记所需的标点符号,像和[],并损坏文件。
更麻烦的是,Jupyter 源代码中经常散落着存储为二进制 blobs 的单元输出。笔记本中的小变化,比如用新数据重新运行,看起来像是版本控制提交日志中的重大变化。
一些有效跟踪文件的内置解决方案将笔记本转换为 HTML 或 Python 文件。你可以使用的外部工具有 nbdime、ReviewNB、Jupytext 和 Neptune 等等。
我的选择是 Neptune,因为它可以与 Jupyter 和 JupyterLab 集成作为扩展。版本控制只是 Neptune 的特性之一。团队、项目和用户管理特性使它不仅仅是一个版本控制工具,但是该软件的轻量级足迹可能使它成为一个引人注目的候选。
使用版本控制系统,你的整个项目都可以被版本化,使用容器,这变得更加容易,我们将很快讨论这一点。
MLOps 与 DevOps
在我们深入使用 TensorFlow 进行机器学习的容器之前,让我们快速浏览一下 MLOps 和 DevOps 之间的异同。
MLOps(机器学习运营)旨在管理大规模生产环境中所有类型的机器学习(深度学习、联邦学习等)的部署。
DevOps(开发和运营)是一套大规模结合软件开发和 IT 运营的实践。它旨在缩短开发周期,提高部署速度,并创建可靠的版本。
DevOps 原则也适用于 mlop,但机器学习工作负载的某些方面需要不同的关注点或实现。
记住我们之前讨论的基本 ML 工作流,我们可以指出 MLOps 和 DevOps 中的以下差异:
团队技能:一个 MLOps 团队有研究科学家、数据科学家和机器学习工程师,他们在 DevOps 团队中担任与软件工程师相同的角色。ML 工程师拥有软件工程师的基本技能,并结合了数据科学专业知识。
开发: DevOps 是线性的,MLOps 更多的是实验性质的。团队需要能够操作模型参数和数据特征,并随着数据的变化频繁地重新训练模型。这需要更复杂的反馈回路。此外,团队需要能够在不妨碍工作流可重用性的情况下跟踪操作的可重复性。
**测试:**在 MLOps 中,测试需要在 DevOps 中通常完成的方法之外的额外方法。例如,MLOps 需要测试数据验证、模型验证、模型质量测试、模型集成和差异测试。
- **部署:**ML ops 中的部署过程类似于 DevOps,但是它取决于您正在部署的 ML 系统的类型。如果设计的 ML 系统与整个产品周期分离,并作为软件的外部单元,这就变得容易了。
- **生产:**生产机器学习模型是连续的,在生产中可能比传统软件更具挑战性。随着用户数据的变化,智能会随着时间而降低。MLOps 需要模型监控和审计来避免意外。
- 需要相同的开发和生产环境
- 在软件工程中,产品开发通常有两个阶段——开发和生产。当开发和生产都选择云原生时,这可以减少到一个,但大多数 ML 应用程序在被推送到云之前都是在本地 PC 上开发的。
- 生产环境是开发环境的再现,主要关注产品性能的关键依赖因素。
在 MLOps 中重现环境或手动跟踪这些依赖关系可能会很有挑战性,因为工作流中涉及到迭代过程。
对于 Python 开发人员来说,Pip 和 Pipenv 等工具经常被用来弥合这一差距,但容器是保持事物整洁的更好方式。
MLOps 中的集装箱要素
容器是一个标准的软件单元,它封装了代码及其所有依赖项,因此应用程序可以快速可靠地从一个计算环境运行到另一个计算环境。
有了容器,就不需要为生产而选择云或任何计算环境配置,因为它们几乎可以在任何地方运行。
使用容器来分离项目环境使得 ML 团队可以灵活地测试运行新的包、模块和框架版本,而不需要破坏整个系统,也不需要在本地主机上安装每个工具。
把容器想象成一个虚拟机。它们有很多共同点,但功能不同,因为容器虚拟化的是操作系统,而不是硬件。集装箱更便携,效率更高。
容器是应用程序层的抽象,它将代码和依赖项打包在一起。多个容器可以在同一台机器上运行,并与其他容器共享操作系统内核,每个容器在用户空间中作为独立的进程运行。
容器比虚拟机占用更少的空间,因为虚拟机是物理硬件的抽象,将一台服务器变成许多台服务器。每个虚拟机包括操作系统、应用程序、必要的二进制文件和库的完整副本。
虽然有许多容器运行工具,但我们将重点放在 Docker 上。
容器是进行研究和实验的好方法,可以灵活地添加数据分析和机器学习工具(如 jupyter notebook 和 jupyter lab)。开发主机上的 Docker 容器是模型开发的一个很好的工具,因为经过训练的模型可以被保存并转换成自包含的图像,并被用作微服务。
这消除了删除整个虚拟环境的风险,或者在被不良软件包或框架破坏时重新安装操作系统的风险。有了容器,所有需要做的就是删除或重建图像。
值得注意的一件关键事情是,当映像被删除或停止时,容器文件系统也会消失。
如果您没有 Docker,请按照下面的指南在您的本地机器上安装它。根据您的主机操作系统,您可以通过以下链接下载它:
安装完成后,你可以在终端中输入“docker”来检查你的主机是否能识别这个命令。
输出应该类似于以下内容:
容器中的 Jupyter 笔记本
能够在 docker 上运行 jupyter 笔记本对数据科学家来说是非常好的,因为无论是否直接与主机接口,你都可以进行研究和实验。
Jupyter 被设计成可以通过一个网络浏览器界面访问,该界面由一个内置的网络服务器驱动。它最好与官方映像(包括 ipython 和 conda)、标准 python 库、所有必需的 jupyter 软件和模块以及附加的数据科学和机器学习库一起运行。只需拉一个官方映像就可以设置好开发环境。
首先,让我们来看一下官方的 Jupyter TensorFlow 图像,我们将使用它作为这个项目的开发环境。你可以在官方 Jupyter 网站上浏览图片列表及其内容。
当我们第一次运行这个命令时,图像在随后的运行中被提取和兑现。我们可以直接在终端上运行这个命令,但是我更喜欢通过 docker compose 运行它,因为我们将运行协同工作的多容器应用程序。有了这个就可以避免错别字了。
Compose 是一个定义和运行多容器 Docker 应用程序的工具。使用 Compose,您可以使用 YAML 文件来配置应用程序的服务。然后,只需一个命令,您就可以从您的配置中创建并启动所有服务。
项目合成文件如下图所示。
我们定义了两个服务(tensorflow 和 tf_model_serving)。重点关注突出显示的部分(tensorflow 服务使用 jupyter/tensorflow-notebook 图像),让我们解释每个标签:
Image :用于指定服务使用的 docker 图像。在我们的例子中,我们指定了正式的 tensorflow jupyter 笔记本。
Ports :我们用它将主机端口映射到容器端口。在这种情况下,由于 jupyter 默认运行在端口 8888 上,我们已经将它映射到本地主机上的端口 8888,但是如果 8888 已经被另一个服务使用,您可以随意更改本地主机端口。
Volumes: 这样,我们可以将本地主机目录绑定到容器中的工作目录。这对于保存中间文件(如模型工件)以绑定 localhost 目录非常有用,因为一旦停止运行,容器文件就会被删除。在这种情况下,我们将主机笔记本文件夹绑定到 projectDir(正在运行的容器笔记本上的项目目录)。
- 环境:jupyter 官方镜像可以作为 jupyter 笔记本或者 jupyter 实验室运行。使用环境标签,我们可以指定我们的首选。将“JUPYTER_ENABLE_LAB”设置为 yes 表示我们已经决定将 JUPYTER 作为实验室而不是笔记本来运行。
- 要使用 docker compose 运行服务,我们可以运行“docker-compose up
”。对于 TensorFlow jupyter 服务,我们运行“docker-compose up tensorflow”。该命令第一次从 docker hub 提取映像: - 该命令的后续运行将直接运行缓存的映像,无需再次拉取,如下所示。
- 我们可以通过上面突出显示的终端中显示的网址访问该笔记本,并显示中间日志。
既然笔记本已经启动并运行,我们就可以对我们正在开发的 ML 供电产品进行研究和实验了。任何默认不包含的包都可以使用**"安装!pip 将<包名>安装在任一代码单元中。要检查已安装的软件包,您可以运行"!皮普不许动”。**
TensorFlow 在容器中的应用开发
对于这个项目,我们将为南非研究人员拍摄的海洋无脊椎动物照片开发一个自动图像分类解决方案,并使用 Tensorflow 服务模型。你可以在 ZindiAfrica 上阅读更多关于这个问题和提供的数据集的信息。
我不会深入研究如何构建或优化模型,但我会指导您如何将它保存为 TensorFlow 服务格式,并作为微服务在容器中提供服务。
您可以通过本文末尾的 GitHub 链接阅读笔记本,了解如何使用 TensorFlow 构建模型。137 个类别中的一些图像如下所示:
一旦在这些图像上构建并训练了具有令人满意的评估的模型,我们可以加载在训练期间保存的. h5 keras 模型,并将其保存为 TensorFlow serving 要求的格式,如下所示:
这将创建一些服务所需的工件,如下图所示:
TensorFlow Serving 使得通过模型服务器公开一个经过训练的模型变得简单而高效。它提供了灵活的 API,可以很容易地与现有系统集成。
这类似于使用 Flask 或 Django 这样的框架来公开保存的模型,但 TensorFlow 服务更强大,是 MLOps 的更好选择,因为需要跟踪模型版本、代码分离和高效的模型服务。
import time
from tensorflow.keras.models import load_model
ts = int(time.time())
loadmodel = load_model('model.h5')
loadmodel.save(filepath=f'/home/jovyan/projectDir/classifier/my_model/{ts}', save_format='tf')
要了解更多关于我为什么选择使用它而不是其他传统框架的信息,请查看“构建加工流水线”一书。
模型服务架构
我们的目标是构建和部署一个微服务,使用容器作为一个 REST API,它可以被一个更大的服务使用,比如公司网站。借助 TensorFlow 服务,API 端点有两个选项 REST 和 gRPC。
REST: 表述性状态转移是一种架构风格,用于在 web 上的计算机系统之间提供标准,使系统之间更容易相互通信。它定义了客户端如何与 web 服务通信的通信方式。使用 REST 的客户机使用标准的 HTTP 方法(如 GET、POST 和 DELETE)与服务器通信。请求的有效负载大部分是用 JSON 编码的。
gRPC: 开源远程过程调用系统,最初于 2015 年在 Google 开发。当在推断过程中处理非常大的文件时,这是首选,因为它提供了低延迟的通信和比 REST 更小的负载。
模型服务架构
- 虽然有两个 API(REST 和 gRPC)可供使用,但重点是 REST API。
- 我在一个容器 jupyter 笔记本中使用客户机代码模拟了这一点。为了实现这一点,我们可以将保存的模型嵌入到基于官方 TensorFlow 服务图像构建的自定义 docker 图像中。
使用带有 docker swarm 或 kubernetes 的单个节点平衡器,可以在多个 TensorFlow 服务副本(我们的用例中有 4 个)之间平衡或均匀分布客户端请求。
我将使用 docker swarm 来编排我们的客户端笔记本和自定义图像,因为它是我安装的 docker 应用程序的一部分。
在 docker compose yml 文件中,我们需要添加 TensorFlow 服务,如下所示:
让我们快速浏览一下 tf_model_serving 服务的标签
**图像:**我们的定制服务 docker 图像 tf _ serving 将被构建并标记为 classifier_model。
**Build:**tensor flow _ model _ serving 服务的合成文件有一个构建选项,它定义了用于构建的 docker 文件的上下文和名称。在本例中,我们将其命名为 Dockerfile,其中包含以下 docker 命令:
docker 合成文件将使用该文件来构建自定义服务图像。
- FROM :用于指定要使用的基础图像。如果这是您第一次提取图像,这将从 docker hub 中提取。
复制:用来告诉 docker 从我们的主机复制什么到正在构建的镜像。在我们的例子中,我们将保存的模型复制到。/notebooks/classifier 到自定义 TensorFlow 服务图像的/models/目录中。
ENV:MODEL _ NAME = my _ MODEL 告诉 TensorFlow serving 根据请求在哪里查找保存的模型。 - Deploy: 使用这个标签,我们可以指定负载平衡的副本数量(在我们的例子中是 4 个)。将 endpoint_mode 设置为 vip 使得可以通过虚拟 ip 在服务发现中访问该容器。在 docker swarm 模式中提供的容器可以通过虚拟 IP (VIP)在服务发现中访问,并通过 docker swarm 入口覆盖网络或通过 DNS 循环(DNSRR)路由。
**要构建这个定制的服务映像,在您的终端中运行命令“docker-compose build
定制映像构建完成后,我们可以使用 docker swarm 启动 docker compose 文件中列出的服务,使用以下命令:
- “dock swarm init”
【docker stack deploy-c】<docker 合成文件> < stack name >。以我们为例,
为“码头栈部署-c 码头-组合. yml tf”
这样,docker 将创建一个虚拟网络,允许所有容器通过名称相互通信。
要检查每个容器的日志,我们可以运行下面的命令
“docker 服务日志
运行“docker 服务日志 tf_tf_model_serving”将显示日志:
现在服务器已经启动,我们可以使用运行 jupyter 笔记本中的客户端代码笔记本来模拟如何将它作为微服务使用,如模型架构所示。
要访问笔记本网址,我们可以在上面运行服务日志:
" docker 服务日志 tf _ tensorflow "
在浏览器中运行应该会得到类似的结果:
我将数据集中的 10 张随机图片保存在一个文件夹中,以测试笔记本中的 API。这些图像如下所示:
每个都被改造成 224*224 的尺寸,就像我在训练模型时做的那样。在向 api 发送请求之前,让我们快速构建 API 端点,如下面的代码片段所示:
你会注意到这是通用的,通用格式可能看起来像:http://:/v1/models/:
**主机:**您的模型服务器的域名和 IP 地址或服务名。在我们的例子中,我们将它声明为“tf_service_host ”,它可以作为我们的主机。
PORT: 这是 url 的服务器端口,对于 REST API,端口默认为 8501,如上面的架构所示。
tf_service_host = 'tf_model_serving'
model_name = 'my_model'
REST_API_port = '8501'
model_predict_url = 'http://'+tf_service_host+':'+REST_API_port+'/v1/models/'+model_name+':predict'
**型号名称:**这是我们正在服务的型号的名称。我们在配置时设置了这个“我的模型”。
- **动词:**这可以是:基于模型签名的分类、回归或预测。在我们的例子中,我们使用“预测”。
- 我们可以有一个预测功能,在将来自客户端的输入图像发送到 API 之前,我们可以用它将图像预处理成所需的格式(“JSON”)。
- 在上面的代码片段中,第一行“json.dump”用于声明 json 数据有效负载,这是 API 所需的格式。
- 实例参数被设置为我们想要分类的图像。在第 3 行,我们向服务器发送一个 post 请求,传递 url、json 文件和头。
然后,我们用关键字“prediction”从返回的 json 信息中获得预测。由于数据集中有 137 个类,我们可以使用 numpy argmax 函数获得准确的预测类,还可以获得模型预测置信度。这两个是作为 Python 元组返回的。
def model_predict(url,image):
request_json = json.dumps({"signature_name": "serving_default", "instances": image.tolist()})
request_headers = {"content-type": "application/json"}
response_json = requests.post(url, data=request_json, headers=request_headers)
prediction = json.loads(response_json.text)['predictions']
pred_class = np.argmax(prediction)
confidence_level = prediction[0][pred_class]
return (pred_class,confidence_level)
使用 for 循环对 10 个测试数据调用此函数,如下所示:
我们可以将结果构造如下:
GPU 和 Docker
Docker 是一个很好的工具,可以为研究和实验创建容器化的机器学习和数据科学环境,但如果我们能够利用 GPU 加速(如果在主机上可用)来加速事情,尤其是深度学习,那就更好了。
predicted_classes = []
for img in test_data:
predicted_classes.append(model_predict(url = model_predict_url, image=np.expand_dims(img,0)))
This will return [(0, 0.75897634),
(85, 0.798368514),
(77, 0.995417),
(120, 0.997971237),
(125, 0.906099916),
(66, 0.996572495),
(79, 0.977153897),
(106, 0.864411),
(57, 0.952410817),
(90, 0.99959296)]
GPU 加速计算的工作原理是将应用程序的计算密集型部分分配给 GPU,从而提供超级计算级别的并行性,绕过主流分析系统所采用的成本高昂的低级操作。
for pred_class,confidence_level in predicted_classes:
print(f'predicted class= {Class_Name[pred_class]} with confidence level of {confidence_level}')
With the output
predicted class= Actiniaria with confidence level of 0.75897634
predicted class= Ophiothrix_fragilis with confidence level of 0.798368514
predicted class= Nassarius speciosus with confidence level of 0.995417
predicted class= Salpa_spp_ with confidence level of 0.997971237
predicted class= Solenocera_africana with confidence level of 0.906099916
predicted class= Lithodes_ferox with confidence level of 0.996572495
predicted class= Neolithodes_asperrimus with confidence level of 0.977153897
predicted class= Prawns with confidence level of 0.864411
predicted class= Hippasteria_phrygiana with confidence level of 0.952410817
predicted class= Parapagurus_bouvieri with confidence level of 0.99959296
在主机上使用 GPU 进行数据科学项目取决于两个因素:
GPU 支持主机
GPU 支持包和软件
由于 docker 在很大程度上将容器与主机隔离开来,因此让容器访问 GPU 加速卡是一件轻而易举的事情。
在撰写本文时,docker 社区正式支持在 Linux 主机上运行的容器的 GPU 加速。虽然 windows 和 mac OS 主机有变通办法,但实现这一点可能是一项非常困难的任务。
- 了解您正在运行的 Tensoflow jupyter 容器是否可以访问 GPU 的一种方法是使用下面的代码片段:
- 尽管我的主机有 GPU 支持,但我无法利用这一点,因为我是在 macOS 上运行的。
尽管如此,docker 是在 GPU 支持下运行 TensorFlow 最简单的方法。点击此处在 Linux 主机上设置一个支持 GPU 的 TensorFlow docker 映像。
结论
这是我向我们合作的项目承诺的 Github 链接。看看吧!
tf.config.experimental.list_physical_devices('GPU')
print("Num GPUs Available: ", len(tf.config.experimental.list_physical_devices('GPU')))
感谢您阅读本教程,希望对您有所帮助。
Nevertheless, docker is the easiest way to run TensorFlow with GPU support. Click here to set up a TensorFlow docker image with GPU support on a Linux host.
Conclusion
Here is the Github link I promised to the project we worked on. Check it out!
Thank you for reading this tutorial, I hope it was helpful.**
使用 Kedro 构建和管理数据科学管道
原文:https://web.archive.org/web/https://neptune.ai/blog/data-science-pipelines-with-kedro
通过机器学习的强大功能,数据科学有望在所有行业产生巨大的商业价值。然而, Gartner 最近的一份报告显示,尽管有足够的数据和意图,但大多数数据科学项目都无法超越实验。
为了释放数据科学的全部潜力,机器学习模型需要作为可扩展的端到端系统部署在现实世界中,并自动管理。最大化数据科学影响的愿望导致了机器学习操作( MLOps )的兴起,这是一套用于构建、维护和监控机器学习生产系统的最佳实践。
作为 MLOps 的一部分,数据科学管道形成了有效部署和使用机器学习模型的基础。本文探讨了数据科学管道(专注于机器学习)背后的概念,以及如何利用开源框架 Kedro 来创建一个**。**
什么是数据科学管道?
顾名思义,数据科学管道包括各种组件的无缝链接,以促进数据按预期顺利移动。
如果我们在网上搜索数据科学管道,我们会看到令人眼花缭乱的管道设计。好消息是,我们可以将这些管道归结为六个核心要素:
- 1 数据检索和摄取
- 2 数据准备
- 3 模特培训
- 4 模型评估和调整
- 5 模型部署
- 6 监控
上图说明了这六个组件是如何连接起来形成一个管道的,在这个管道中,机器学习模型可以在生产环境中提供最佳结果。
Data science pipeline | Source: Author
让我们仔细看看这些组件:
(1)数据检索和摄取
数据是所有数据科学项目的生命线,因此第一步是从各种数据源中识别相关的原始数据。
- 这一步比听起来更具挑战性,因为数据通常以不同的格式存储在不同的孤岛中(例如,第三方来源、内部数据库)。
- 一旦所需的数据集被正确识别,它们就被提取并整合到一个中心位置,以供下游处理。
- (2)数据准备
来自数据的洞察力的质量取决于数据质量本身。因此,数据准备花费最多的时间和精力也就不足为奇了。
现在,我们已经准备好使用准备好的数据在训练数据集上运行机器学习。
模型训练是模型在数据中潜行,学习潜在的模式。经过训练的模型将被表示为从数据中捕获模式信息的统计函数。
- 要实现的机器学习模型的选择取决于实际任务、数据的性质和业务需求。
- (4)模型评估和调整
一旦模型训练完成,评估其表现是至关重要的。评估是通过让模型对它以前从未见过的数据集运行预测来完成的。它代表了它在现实世界中的表现。
- 评估指标有助于指导优化模型性能所需的更改(例如,选择不同的模型、调整超参数配置等)。).
- 机器学习开发周期是高度迭代的,因为有许多方法可以基于度量和错误分析来调整模型。
- (5)部署
一旦我们确信我们的模型可以提供出色的预测,我们就通过将它部署到生产环境中来将模型暴露给实际的操作。
Example of a model management system using Neptune.ai | Source
模型部署(又名服务)是将模型集成到生产环境中的关键步骤,在生产环境中,模型接收实际数据并为数据驱动的业务决策生成输出。
- (6)监测
- 虽然看起来我们已经成功地完成了模型部署,但是我们离完成还有一段距离。
为了保持一个强大且持续运行的数据科学管道,最重要的是我们要监控它在部署后的表现。
除了模型性能和数据质量,监控指标还可以包括操作方面,如资源利用率和模型延迟。
- 在成熟的 MLOps 设置中,我们可以根据预测性能或新数据的可用性触发新的模型训练迭代。
- Beyond model performance and data quality, the monitoring metrics can also include operational aspects such as resource utilization and model latency.
- 需要强调的重要一点是,数据科学管道是动态的,需要迭代改进,以确保持续的稳健性和准确性。
在前面的六个核心管道组件的图表中,我们看到了几个虚线箭头连接到管道的前面的元素。这些箭头反映了我们更新组件以响应监控指标变化时所需的各种迭代。
Example drift monitor in Arize | Source
例如,假设输入客户数据的年龄分布在最近几周越来越不均匀。在这种情况下,团队应该考虑检查数据准备步骤,或者根据新数据重新训练模型。
数据科学管道的重要性
首先理解数据科学管道的重要性和好处至关重要,因为它们需要努力构建。
这些管道的目标是创建一个系统化的工作流程,将原始数据以自动化和可重复的方式转化为可操作的业务洞察。
它的重要性来自于自动化数据科学开发周期中的手动步骤,这些步骤是重复的、劳动密集型的、容易出错的和耗时的。
这种简化的数据移动允许数据科学家专注于他们最擅长的事情,即改进数据和模型,而不用担心数据流、算法更新和模型部署的工程方面。
以下是数据科学管道可以带来的商业优势:
加快数据驱动的决策制定,以响应不断变化的业务需求和客户偏好。
通过将数据从孤岛整合到单个目的地,释放新的机会和全面的洞察力。
- 确保数据洞察力的一致性、可再现性和质量。
- 简化了向机器学习系统中引入新的商业想法和需求。
- 数据科学管道用例
- 数据科学管道是行业不可知的,因此我们可以预计它们可能会在不同的领域带来巨大的好处。
以下是行业中实施的数据科学管道的一些真实示例:
软件行业 — Dropbox 建立了一个现代光学字符识别管道,以创建移动文档扫描功能。
运输行业 — Lyft 利用内部管道框架来加速机器学习和数据协调,以实现定价、位置和到达时间估计等核心乘车功能。
- 保险行业 — USAA 利用机器学习管道,通过创建一项服务来绘制应该修理或更换的受损车辆零件的照片,从而改善汽车索赔处理。
Creating a modern OCR pipeline using computer vision and deep learning | Source
- 医疗保健行业 —英国国家卫生系统(NHS) 开发并部署了一套机器学习管道,作为新冠肺炎国家医院容量规划系统的一部分。
- 凯卓是什么?
- 看到数据科学管道可以带来的巨大价值后,让我们探索如何实现它们,并将这些理论优势转化为系统现实。
对管道重要性的认识促进了一些有效建设和管理管道的框架的发展。Kedro 就是这样一个框架,这是本文的重点。
Kedro 是一个开源的 Python 框架,用于创建可复制、可维护和模块化的数据科学代码。该框架有助于加速数据流水线,增强数据科学原型,并促进流水线的可再现性。
Kedro 将软件工程概念应用于开发生产就绪的机器学习代码,以减少成功部署模型所需的时间和精力。
它的影响是通过消除低质量代码的重新设计工作和无缝协作的项目模板的标准化来实现的。
让我们看看 Kedro 中的应用概念:
再现性:准确一致地跨不同管道运行和环境重新创建工作流程步骤的能力。
模块化:将大的代码块分解成更小的、独立的、易于理解的单元,这些单元易于测试和修改。
可维护性:使用标准代码模板,允许团队成员容易理解和维护任何项目的设置,从而促进协作开发的标准化方法
版本控制:精确跟踪每个项目的每个管道运行中使用的数据、配置和机器学习模型。
文档:清晰结构化的代码信息,便于阅读和理解。
无缝打包:允许数据科学项目被记录并有效地运送到生产中(使用诸如 Airflow 或 Docker 之类的工具)。
为什么是凯卓?
将数据科学项目从试点开发带入生产的过程充满了挑战。
一些重大困难包括:
需要为生产环境重写代码,导致项目严重延迟。
项目结构可能是杂乱无章和不连贯的,这给协作带来了挑战。
- 难以追踪的数据流。
- 过于冗长且难以测试或重用的功能。
- 难以理解的函数之间的关系。
- QuantumBlack 团队开发了 Kedro 来应对上述挑战。它诞生于一个共同的信念,即数据科学代码应该从一开始就为生产做好准备,因为它是成功管道部署的严格起点。
- 真实世界中的凯卓
和所有项目一样,证据就在布丁里。以下是 Kedro 在现实应用中成功使用的一些例子:
美国宇航局利用 Kedro 作为其基于云的预测引擎的一部分,预测空域内受阻和无障碍滑行的持续时间。
在 Kedro 的帮助下,JungleScout 加快了 18 次销售估算模型的培训和评审。
Telkomsel 使用 Kedro 运行数百个功能工程任务,并在其生产环境中服务数十个机器学习模型。
elemental通过在他们的调度软件中利用 Kedro 来测量历史性能和创建回放场景,提高了他们的工作效率。
为异常检测构建数据科学管道
现在我们已经了解了 Kedro,让我们进入激动人心的部分,通过一个实际动手的例子来工作。
该项目用例围绕财务欺诈检测展开。我们将使用隔离森林作为我们的机器学习模型,构建一个异常检测管道,来识别信用卡交易中的异常。
信用卡交易数据从 Worldline 和机器学习小组的合作中获得。这是对真实世界信用卡交易的真实模拟,旨在包括复杂的欺诈检测问题。
下面的可视化展示了我们最终的异常检测管道将会是什么样子,并作为我们将在以下部分构建的蓝图。
The credit card transaction data is obtained from the collaboration between Worldline and Machine Learning Group. It is a realistic simulation of real-world credit card transactions and has been designed to include complicated fraud detection issues.
随意查看这个项目的 GitHub repo 来跟随这个演练。
Kedro 管道
Anomaly detection pipeline | Source: Author
步骤 1:安装 Kedro 和 Kedro-Viz
建议创建一个虚拟环境,以便每个项目都有其独立的环境和相关的依赖项。
要使用 Kedro,Kedro 官方文档建议用户下载并安装 Anaconda 。
因为我的 Python 版本是 3.10 以上,Anaconda 使得在兼容 Kedro 需求的版本(即,在撰写本文时 Python 3.6-3.8)上创建环境(使用 conda 而不是 venv )变得很容易。
特别是,这是生成我们的 Kedro 环境的命令(在 Anaconda Powershell 提示符中):
一旦建立了虚拟环境并用 conda activate kedro-env 激活,我们就可以使用 pip 来安装 kedro 和 Kedro-Viz 插件:
我们可以通过将目录更改到我们的项目文件夹,然后输入 kedro info 来检查 Kedro 是否正确安装。如果安装正确,我们应该会看到以下输出:
conda create --name kedro-env python=3.7 -y
此时,我们可以安装项目所需的其他包:
pip install kedro kedro-viz
如果我们希望将这个项目初始化为 Git 存储库,我们可以使用:
步骤 2:项目设置
pip install scikit-learn matplotlib
Kedro 的一个关键特性是创建标准的、可修改的和易于使用的项目模板。我们可以很容易地初始化一个新的 Kedro 项目:
git init
在为一系列提示提供相关名称之后,我们将得到一个高度组织化的项目目录,我们可以在这个目录上进行构建:
项目结构可以分为六个主文件夹:
kedro new
/ conf : 包含指定重要细节的配置文件,如数据源(即数据目录)、模型参数、凭证和日志信息。
/ 数据 : 包含输入、中间和输出数据。它被组织成一个八层的数据工程约定,以清楚地分类和组织数据的处理方式。
- /****:包含与项目文档相关的文件。
- / logs : 包含管道运行时生成的日志文件。
- / 笔记本 : 包含项目中使用的 Jupyter 笔记本,例如用于实验或初步探索性数据分析。
- / src : 包含项目的源代码,例如用于流水线步骤、数据处理和模型训练的 Python 脚本。
- 步骤 3:数据设置
- 数据先于科学,所以让我们从数据设置开始。在这个项目中,原始数据(每日信用卡交易的 70 个 CSV 文件)首先放在 data/01_raw 文件夹中。
**#### 根据前面描述的项目蓝图,我们已经知道在整个过程中将会生成和利用哪些数据。因此,我们可以将这些信息翻译成 数据目录 ,这是一个项目可用的数据源注册表。
数据目录提供了一种定义如何存储和解析数据的一致方式,使得从管道中的任何位置加载和保存数据集变得容易。
我们可以在中找到数据目录。yml 文件—conf/base/catalog . yml*。*
上图是数据目录中定义的数据源的一个片段。例如,我们首先期望我们的原始 CSV 文件被读取并合并到一个名为 merged_data.csv 的中间 CSV 数据集。
Kedro 自带众多内置数据连接器(比如熊猫。CSVDataSet,matplotlib。MatplotlibWriter)来适应不同的数据类型。
步骤 4:创建管道
一旦我们的数据目录被适当地定义,我们就可以构建我们的管道。首先要理解两个关键概念: 节点 和 管道 。
节点是管道的构建块。它们本质上是 Python 函数,表示要执行的数据转换,例如数据预处理、建模。
管道是被连接以交付工作流的节点序列。它组织节点的依赖关系和执行顺序,连接输入和输出,同时保持代码模块化。
- 用于异常检测的完整管线可分为**三个较小的模块化管线,**我们将最终连接它们:
- Pipelines are sequences of nodes that are connected to deliver a workflow. It organizes the nodes’ dependencies and execution order and connects inputs and outputs while keeping the code modular.
1 数据工程管道
2 数据科学管道
- 3 模型评估管道
- 我们可以根据指定的名称,使用以下命令实例化这些模块化管道:
- 虽然管道在这个阶段是空的,但是它们的结构已经在 /src 文件夹中很好地生成了:
每个管道文件夹都有相同的文件,包括 nodes.py (节点代码)和 pipeline.py (管道代码)。
kedro pipeline create data_engineering
kedro pipeline create data_science
kedro pipeline create model_evaluation
步骤 5:构建数据工程管道
我们先来看看数据工程管道,在这里我们对数据进行处理,使其适合下游的机器学习。更具体地说,有三个预处理任务要执行:
Step 5: Build a data engineering pipeline
1 将原始数据集合并成一个中间合并数据集。
2 通过仅保留预测值列并为后续训练测试分割创建新的日期列来处理合并的数据集。
- 3 按时间顺序执行 80:20 列车测试,拆分并删除不必要的列。
- 我们首先将任务脚本化为三个独立的 节点函数在**节点. py、**中,如下所示:
- 然后,我们将这些节点函数导入到 pipeline.py 中,以正确的顺序将它们链接起来。
注意,在每个节点包装器的 节点(..) 上面,我们指定了一个节点名,函数(从 node.py 导入),以及在数据目录中定义的输入输出数据集。
from typing import Any, Callable, Dict
import pandas as pd
from datetime import timedelta, datetime as dt
def merge_data(partitioned_input: Dict[str, Callable[[], Any]]) -> pd.DataFrame:
merged_df = pd.DataFrame()
for partition_id, partition_load_func in sorted(partitioned_input.items()):
partition_data = partition_load_func()
merged_df = pd.concat([merged_df, partition_data], ignore_index=True, sort=True)
return merged_df
def process_data(merged_df: pd.DataFrame, predictor_cols: list) -> pd.DataFrame:
merged_df['TX_DATETIME'] = pd.to_datetime(merged_df['TX_DATETIME'], infer_datetime_format=True)
merged_df['TX_DATE'] = merged_df['TX_DATETIME'].dt.date
processed_df = merged_df[predictor_cols]
return processed_df
def train_test_split(processed_df: pd.DataFrame) -> pd.DataFrame:
processed_df['TX_DATE'] = pd.to_datetime(processed_df['TX_DATE'], infer_datetime_format=True)
split_date = processed_df['TX_DATE'].min() + timedelta(days=(8*7))
train_df = processed_df.loc[processed_df['TX_DATE'] <= split_date]
test_df = processed_df.loc[processed_df['TX_DATE'] > split_date]
train_df.drop(columns=['TX_DATE'], inplace=True)
test_df.drop(columns=['TX_DATE'], inplace=True)
if 'TX_FRAUD' in train_df.columns:
train_df = train_df.drop(columns=['TX_FRAUD'])
if 'TX_FRAUD' in test_df.columns:
test_labels = test_df[['TX_FRAUD']]
test_df = test_df.drop(columns=['TX_FRAUD'])
else:
test_labels = pd.DataFrame()
return train_df, test_df, test_labels
节点包装器中的参数应该与数据目录中的数据集名称和节点函数的参数相匹配。
from kedro.pipeline import Pipeline, node, pipeline
from .nodes import merge_data, process_data, train_test_split
def create_pipeline(**kwargs) -> Pipeline:
return pipeline([
node(
func=merge_data,
inputs="raw_daily_data",
outputs="merged_data",
name="node_merge_raw_daily_data"
),
node(
func=process_data,
inputs=["merged_data", "params:predictor_cols"],
outputs="processed_data",
name="node_process_data"
),
node(
func=train_test_split,
inputs="processed_data",
outputs=["train_data", "test_data", "test_labels"],
name="node_train_test_split"
),
])
对于节点 node_process_data,预测器列的列表存储在位于conf/base/parameters . yml中的参数文件中。
我们的数据工程管道设置已经完成,但是它还没有准备好,因为它还没有在 T2 注册。我们将在稍后的步骤 8 中探讨这个问题,所以让我们继续构建剩下的两条管道。
步骤 6:构建数据科学管道
我们的数据科学管道的异常检测模型是一个隔离林。隔离森林是一种使用决策树构建的无监督算法。
它通过随机选择一个特征,然后在其最大值和最小值之间选择一个分割值来“隔离”观察值。由于异常现象很少且不同,因此预计它们比正常观察更容易分离。
我们将使用 scikit-learn 隔离林实现进行建模。有两个任务(和节点)要被创建——**(I)**模型训练和 (ii) 模型预测(又名推理)。
隔离森林模型的污染值被设置为 0.009 ,反映了在原始数据集中观察到的欺诈案例的比例(即 0.9%)。
像以前一样,我们在 pipeline.py 中的管道函数内将节点链接在一起。
正如前面在数据目录中看到的,我们将把我们训练的隔离森林模型作为 pickle 文件保存在 data/06_models 中。
import numpy as np
import pandas as pd
from sklearn.ensemble import IsolationForest
def train_model(train_df: pd.DataFrame, contamination_value: float):
clf = IsolationForest(random_state=42, bootstrap=True, contamination=contamination_value)
clf.fit(train_df.values)
return clf
def predict(ml_model, test_df: pd.DataFrame):
preds = ml_model.predict(test_df.values)
preds_mod = np.array(list(map(lambda x: 1*(x==-1), preds)))
anomaly_scores = ml_model.score_samples(test_df)
anomaly_scores_mod = np.array([-x for x in anomaly_scores])
test_df['ANOMALY_SCORE'] = anomaly_scores_mod
test_df['ANOMALY'] = preds_mod
return test_df
步骤 7:构建模型评估管道
from kedro.pipeline import Pipeline, node, pipeline
from .nodes import train_model, predict
def create_pipeline(**kwargs) -> Pipeline:
return pipeline([
node(
func=train_model,
inputs=["train_data", "params:contamination_value"],
outputs="ml_model",
name="node_train_model"
),
node(
func=predict,
inputs=["ml_model", "test_data"],
outputs="predictions",
name="node_predict"
),
])
虽然隔离森林是一个无监督的模型,但如果我们有地面真实标签,我们仍然可以评估它的性能。
在原始数据集中,有一个用作欺诈交易指示器的 TX_FRAUD 变量。
利用模型预测的基本事实标签和异常分数,我们可以很容易地获得评估指标,这些指标将表示为 AUC 和 AUCPR 图。
下面是运行模型评估节点的 pipeline.py 脚本。
这个模型评估步骤与步骤 6 中的数据科学管道是分开的。这种分离是因为我们正在使用一种无监督的异常检测算法,并且我们并不期望总是得到真实的数据。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.metrics import roc_curve, precision_recall_curve, auc
def evaluate_model(predictions: pd.DataFrame, test_labels: pd.DataFrame):
def get_auc(labels, scores):
fpr, tpr, thr = roc_curve(labels, scores)
auc_score = auc(fpr, tpr)
return fpr, tpr, auc_score
def get_aucpr(labels, scores):
precision, recall, th = precision_recall_curve(labels, scores)
aucpr_score = np.trapz(recall, precision)
return precision, recall, aucpr_score
def plot_metric(ax, x, y, x_label, y_label, plot_label, style="-"):
ax.plot(x, y, style, label=plot_label)
ax.legend()
ax.set_ylabel(x_label)
ax.set_xlabel(y_label)
def prediction_summary(labels, predicted_score, info, plot_baseline=True, axes=None):
if axes is None: axes = [plt.subplot(1, 2, 1), plt.subplot(1, 2, 2)]
fpr, tpr, auc_score = get_auc(labels, predicted_score)
plot_metric(axes[0], fpr, tpr, "False positive rate", "True positive rate", "{} AUC={:.4f}".format(info, auc_score))
if plot_baseline:
plot_metric(axes[0], [0, 1], [0, 1], "False positive rate", "True positive rate", "Baseline AUC=0.5", "r--")
precision, recall, aucpr_score = get_aucpr(labels, predicted_score)
plot_metric(axes[1], recall, precision, "Recall", "Precision", "{} AUCPR={:.4f}".format(info, aucpr_score))
if plot_baseline:
thr = sum(labels)/len(labels)
plot_metric(axes[1], [0, 1], [thr, thr], "Recall", "Precision", "Baseline AUCPR={:.4f}".format(thr), "r--")
plt.show()
return axes
fig = plt.figure()
fig.set_figheight(4.5)
fig.set_figwidth(4.5*2)
axes = prediction_summary(test_labels['TX_FRAUD'].values, predictions['ANOMALY_SCORE'].values, "Isolation Forest")
return fig
步骤 8:在管道注册表中注册所有管道
from kedro.pipeline import Pipeline, node, pipeline
from .nodes import evaluate_model
def create_pipeline(**kwargs) -> Pipeline:
return pipeline([
node(
func=evaluate_model,
inputs=["predictions", "test_labels"],
outputs="evaluation_plot",
name="node_model_evaluation"
)
])
至此,创建管道的所有艰苦工作都已完成。我们现在需要通过在管道注册表中导入和注册所有三个模块化管道来结束。
return 语句中的 default 行指示模块化管道的默认运行顺序,在我们的示例中,这是所有三个模块化管道——data _ engineering、data_science 和 model_evaluation。
Kedro 的美妙之处在于,它的模块化结构让我们能够灵活地构建我们的管道。例如,如果我们没有基础事实标签,我们可以从缺省管线运行中排除 model_evaluation。
from typing import Dict
from kedro.pipeline import Pipeline, pipeline
from anomaly_detection_pipeline_kedro.pipelines import (
data_engineering as de,
data_science as ds,
model_evaluation as me
)
def register_pipelines() -> Dict[str, Pipeline]:
data_engineering_pipeline = de.create_pipeline()
data_science_pipeline = ds.create_pipeline()
model_evaluation_pipeline = me.create_pipeline()
return {
"de": data_engineering_pipeline,
"ds": data_science_pipeline,
"me": model_evaluation_pipeline,
"__default__": data_engineering_pipeline + data_science_pipeline + model_evaluation_pipeline
}
步骤 9:可视化管道
在运行管道之前,检查一下我们到目前为止已经构建了什么是一个好主意。奇妙的 Kedro-Viz 插件让我们可以很容易地可视化整个管道结构和依赖关系。
鉴于其易用性、清晰度和美观的显示,许多 QuantumBlack 客户对这一功能表达了他们的喜悦也就不足为奇了。
我们可以使用以下命令轻松生成可视化效果:
我们的浏览器中将会打开一个新的选项卡,我们将会看到一个漂亮的可视化工具来探索我们的管道结构。这种可视化也可以很容易地导出为一个. png 图像文件。
步骤 10:运行管道
kedro viz
我们终于准备好运行我们的管道。下面的命令将执行我们之前注册的默认管道。
运行时,管道将使用生成的数据填充各自的目录,包括异常预测和模型评估图。
我们还可以运行已经在管道注册表中注册的特定管道。例如,如果我们只想运行数据工程模块化管道(de),我们可以在命令中添加*–管道<名称>* :
kedro run
步骤 11:评估管道输出
最后,是时候评估我们异常检测管道的输出了。特别是,让我们回顾一下 matplotlib 评估图(保存在 数据/08 _ 报告 )来看看该模型的性能如何。
kedro run --pipeline de
从图中,我们可以看到隔离森林模型 AUC 是 0.8486 ,这是一个相当好的基线机器学习模型性能。
附加功能
Evaluating pipeline output | Source: Author
恭喜你走到这一步,并成功地用 Kedro 创建了一个异常检测管道!
除了前面详细介绍的基本功能之外,Kedro 还提供了其他用于管理数据科学项目的有用特性。这里有几个值得一提的功能:
(1)实验跟踪
Kedro 使得设置实验跟踪和访问每个管道运行的记录指标变得容易。除了它的内部实验跟踪能力,Kedro 与其他 MLOps 服务整合得很好。
例如, Kedro-Neptune 插件 让用户享受到组织良好的管道以及为元数据管理而构建的强大 Neptune 用户界面的好处。
(2)管道切片
Kedro 的管道切片功能允许我们根据需要执行管道的特定部分。例如,我们可以在希望运行的管道切片中定义开始和结束节点:
Kedro pipeline metadata in a custom dashboard in the Neptune UI | Source
(3)项目文档、打包和部署
我们可以通过在项目的根目录下运行这个命令来生成特定于项目的文档(构建在 Sphinx 框架上)。
kedro run --from-nodes train-test-split --to-nodes train_model
接下来,为了将项目的打包为 Python 库,我们运行以下命令:
最后,我们可以通过第三方插件 Docker 和 Airflow 来部署这些打包的数据科学管道。
kedro build-docs
(4)通过 Jupyter 笔记本访问 Kedro
kedro package
我们还可以使用 Jupyter 笔记本来探索项目数据或试验代码,为管道创建新节点。这些任务可以通过使用以下命令启动 Kedro Jupyter 会话来完成:
结论
下面是我们在本文中经历的内容:
kedro jupyter notebook
数据科学管道的概念、优势和用例是什么。
什么是 Kedro,以及如何使用它来构建和管理数据科学管道。
- 如何使用隔离林模型和 Kedro 框架为信用卡交易数据创建异常检测管道。
- 还有许多其他有趣的特性和教程可用,所以请查看官方 Kedro 文档做进一步的探索。另外,可以随意探索包含这个项目所有代码的 GitHub repo 。
- 参考
梁振英
数据科学家、技术作家、开发人员、药剂师。热衷于学习和推动实干家,喜欢用技术和数据寻找和解决有意义的问题。
阅读下一篇
最佳 MLOps 工具以及如何评估它们
12 分钟阅读| Jakub Czakon |年 8 月 25 日更新
The Best MLOps Tools and How to Evaluate Them
在我们的一篇文章中——机器学习团队实际使用的最好的工具、库、框架和方法——我们从 41 家 ML 初创公司学到的东西——Acerta 的 CTO Jean-Christophe Petkovich 解释了他们的 ML 团队如何接近 MLOps。
据他所说,一个完整的 MLOps 系统有几个要素:
您需要能够构建包含预处理数据和生成结果所需的所有信息的模型工件。
一旦您能够构建模型工件,您必须能够跟踪构建它们的代码,以及它们被训练和测试的数据。
- 您需要跟踪所有这三样东西,模型、它们的代码和它们的数据,是如何关联的。
- 一旦您可以跟踪所有这些内容,您还可以将它们标记为准备就绪,进行生产,并通过 CI/CD 流程运行它们。
- 最后,为了在该过程的最后实际部署它们,您需要某种方法来基于该模型工件旋转服务。
- 这是对如何在公司中成功实施 MLOps 的高度概括。但是理解高层需要什么只是拼图的一部分。另一个是采用或创建适当的工具来完成工作。
- 这就是为什么我们编制了一份最佳 MLOps 工具的清单。我们将它们分为六类,以便您可以为您的团队和业务选择合适的工具。让我们开始吧!
It’s a great high-level summary of how to successfully implement MLOps in a company. But understanding what is needed in high-level is just a part of the puzzle. The other one is adopting or creating proper tooling that gets things done.
That’s why we’ve compiled a list of the best MLOps tools. We’ve divided them into six categories so you can choose the right tools for your team and for your business. Let’s dig in!
数据科学项目管理[ML 团队新指南]
原文:https://web.archive.org/web/https://neptune.ai/blog/data-science-project-management
数据科学是主流,在竞争最激烈的市场中,许多组织正在通过更加数据驱动来击败竞争对手。
越来越多的新软件项目涉及数据科学的各个方面。这就产生了一个问题。如果没有标准化的方法来管理数据科学项目,团队通常会依赖不可重复、不可持续和无组织的临时实践。
这样的团队苦于项目成熟度低,没有持续的改进,定义良好的过程和检查点,或者频繁的反馈(Saltz,2015)。
在软件工程中,我们有一种叫做 CMM(能力成熟度模型)的东西。这是一种改进的方法,你可以用它来开发和改进你的软件构建过程。
CMM 有 5 个过程成熟度等级:
- 最初的
- 管理
- 清晰的
- 量化管理
- 使最佳化
所以当我提到特别的实践时,它们处于 CMM 的底层——初始的。很多未知,控制不好,没有足够的计划,这往往会导致灾难。
何时在 DS 管理中使用临时流程?
松散的、特别的过程在数据科学中有着重要的地位。当你开始一个项目时,松散的流程让你可以自由决定如何解决出现的每个问题。这自然意味着有很多尝试和错误。
临时流程可能最适合由个人和小团队协调的一次性项目(Saltz & Shamshurin,2016)。
注意 : 我将交替使用术语“方法论”和“方法”。
使用这种松散的方法,您可以以最小的管理开销快速开始一个项目,并且不需要遵守多个特定的过程。
然而,数据科学不再是孤立的。它已经发展成为一项团队工作,涉及数据科学以外的具有不同技能的专业人员(Spoelstra,Zhang 和 Kumar,2016)。
这就需要标准化的项目管理。让我们看看如何将成熟的软件项目管理方法用于数据科学。我们来看看:
瀑布方法
由 Winston Royce 在 1970 年提出的瀑布是最古老的软件工程范例。瀑布是一个顺序模型,分为预定义的阶段。
每个阶段必须在下一个阶段开始之前完成。阶段之间没有重叠。这些阶段包括:范围、需求、设计、构建、测试、部署和维护。
Each phase must be completed before the next can begin. There’s no overlap between phases. These phases include: scope, requirements, design, build, test, deployment and maintenance.
瀑布从一个初始阶段开始,然后沿着一条直线向最终阶段连续泻下。你不能重温以前的阶段,如果你需要,这意味着你计划不周。
这种方法需要重要的项目治理,包括报告、风险管理、移交和文档。
尽管 W.Royce 最初提出的瀑布模型考虑到了“反馈循环”,但是绝大多数采用这种方法的组织都把它当作严格的线性来对待()
*> 何时使用瀑布模型?
只有当需求非常清晰和固定,产品定义稳定,您的团队完全了解技术栈,并且项目很短的时候,您才应该使用它。
当项目阶段,从沟通到部署,以线性方式进展时,瀑布功能最好。这通常发生在现有系统需要改进的情况下,比如适应面部识别系统已经变得必要。
瀑布方法对数据科学项目管理有用吗?
不,不是的。当技术被很好地理解,产品市场稳定,并且需求在项目过程中不太可能改变时,瀑布是最有效的(记者&马克西姆,2015) 。
这与数据科学项目正好相反。在数据科学中,有很多实验,需求总是在变化,技术仍然非常新颖。
然而,我们仍然可以从这种方法中获得一些东西。例如,瀑布结构良好的特性非常适合数据科学项目的某些阶段,如范围、规划、资源管理或验证。
范围/合同–典型的大规模数据科学项目仍然需要控制和风险管理,尤其是在涉及第三方的消费者数据权利、业务案例衡量、合同和支付管理方面。
组织规划和文化–大型组织有企业范围的项目管理方法,这在本质上倾向于瀑布。数据科学项目可能必须与这些方法相吻合。这些可以包括 RAID 管理(风险、假设、问题和依赖性)、计划治理报告和预算跟踪。
组织资源管理-强调依赖性和瓶颈是保持项目里程碑的关键。
当我们谈到混合方法时,我们会对此谈得更多。现在,让我们继续讨论敏捷方法。
敏捷方法
敏捷方法论建立在 4 个核心价值观和 12 个原则之上(敏捷宣言)。这种方法是关于软件开发生命周期中的迭代和测试。
开发和测试活动同时发生,这在瀑布模型中是永远不会发生的。
何时使用敏捷方法?
敏捷是为了应对快节奏、不断变化的 IT 行业而产生的。对软件的需求一直在变化,所以开发人员需要能够快速适应。
如果你现在正在做软件开发,你正在使用敏捷。这是标准,它已经超越了软件项目。许多组织中的业务、营销、设计和其他团队都使用敏捷项目管理。
我们应该将敏捷用于数据科学项目管理吗?
敏捷非常适合数据科学,以下是一些原因:
1.数据科学家和业务所有者在开发生命周期的早期就高级需求(项目积压)达成一致,并随着项目的发展不断审查它们。
业务所有者可以审查模型/解决方案,并在整个开发过程中做出决策和变更。
以有意义的方式收集和记录详细的需求通常是数据科学项目中最困难的部分。企业所有者可能对必要的数据质量、要建模的精确业务结果或模型输出如何与决策系统集成没有详细的了解。
2.由于业务所有者的频繁审查和指导,敏捷数据科学产生了不断发展的模型和非常以用户为中心的版本。
3.企业所有者通过在整个项目中直接与开发团队合作,获得了强烈的主人翁感。
既然我们已经看到了敏捷和数据科学的完美结合,让我们来看看不同的敏捷框架——它们的好处、工具、利弊&和最佳实践。
混乱
Scrum 是一个敏捷的协作框架,可以让你的团队更加灵活。通过为复杂的任务提供简单的解决方案,它使得构建复杂的软件应用程序变得更加容易。
Scrum 是关于使用一套“软件过程模式”,这些模式已经被证明对于时间紧迫、需求变化和业务关键的项目是有效的。这些过程模式中的每一个都定义了一组开发活动。
基本 Scrum 概念
Scrum 将较大的项目(产品 backlog)分成一系列的小项目,每个项目都有一致的固定长度,从一周到一个月不等。每个小型项目周期,称为 sprint,在一个称为 sprint planning 的会议上开始,在这个会议上,产品负责人定义并解释最重要的特性优先级。
开发团队估计他们可以在 sprint 结束时交付什么,然后制定一个 sprint 计划来开发这些可交付成果。在冲刺阶段,他们密切配合,在每日站立时制定每日计划(最长 15 分钟)。在 sprint 结束时,团队向涉众展示可交付成果,并在 sprint 评审期间获得反馈。
这些可交付成果应该是潜在可发布的,并且符合商定的完成定义。为了结束一个 sprint,有一个 sprint 回顾,团队成员计划如何改进他们的工作。
我们应该使用 Scrum 进行数据科学项目管理吗?
是啊!
Scrum 帮助你的团队协作并交付增值。但是这并不容易。一个挑战是,在数据科学背景下,定义固定长度的冲刺可能很困难。很难估计一项任务需要多长时间。
数据科学团队经常想要不同持续时间的冲刺,但是在使用 Scrum 时这是不可能的。
由于这些挑战,一些团队使用数据驱动的 Scrum(我们将在混合方法部分看到它)。DDS 拥有 Scrum 的一些关键概念,但也解决了在数据科学环境中使用 Scrum 的关键挑战。另一个好的选择是看板(有时和 Scrum 一起使用)。
最佳 Scrum 实践
**区分“峰值”的优先级:**为了允许研究和发现,团队可以创建峰值——为紧张的研究提供时间的待办事项。这些尖峰与产品增量想法一起被搁置在待办事项列表中。当进入冲刺阶段时,当特定的研究目标达到或时限到期时,它们被认为是“完成”的(Mezick,2017)。
将工作划分得“更小”并征服:数据科学家经常抱怨他们的工作太不明确,无法估计一项任务可能需要多少努力。一个可能的解决方案是将工作增量分成可定义和可估计的小块(Mezick,2017)。
- 缩短冲刺:丹尼尔·梅齐克说“事情越接近混乱,要想知道该怎么做就要经常检查。”他建议将 sprint 周期划分为更短的时间段,以强制进行更频繁的检查(Mezick,2017)。
- **偶尔放松“完成的定义”:**为了避免探索性工作和概念验证的全面测试,交付速度可能比“完成”更重要,团队可以同意放松某些特性的完成定义。然而,团队应该确保他们不会陷入接受核心可交付成果的低质量输出的滑坡。
- **在冲刺阶段重新协商工作:**与普遍的误解相反,在冲刺规划阶段,冲刺计划并不是一成不变的。相反,“随着了解的深入,产品负责人和开发团队可以澄清并重新协商范围”,如果它不“危及 Sprint 目标”(萨瑟兰& Schwaber,2017)。
- **构建“架构跑道”:**需要新的大规模架构的团队可能会发现,仔细的前期规划比通过紧急设计来开发架构更有效。与 Scrum 以客户为中心的关注点不同,数据科学团队可能会从 Scaled Agile Framework (SAFe)中获得一个概念,并投入一些初始冲刺来为自己开发一个架构(Scaled Agile,Inc,2017)。
- **首先做最不了解的工作:**为了降低风险,数据科学团队可以将早期开发周期集中在探索性工作和概念证明上,以熟悉数据。Akred 建议他的团队“预先装载你不理解的部分,然后当我们对自己的能力有信心时,我们开始围绕它构建一些东西,这些东西实际上将变成一个可用的系统”(Akred,2015)。如果团队无法在合理的周期数内证明可行性,它可以重新关注其他工作,避免不必要的损失。
- **与 CRISP-DM 集成:**为了处理数据科学流程,CRISP-DM 可以与 Scrum 集成来管理数据科学项目(在混合部分有更多相关信息)。
- 2020 年 Scrum 最流行的工具是:
- Monday.com
wrike
- 专案经理
- 琪拉
- Scrum 的优点
- 客户关注: Scrum 关注交付客户价值。
**规律性:**严格的时间界限让团队习惯了有规律的工作流程。
- 自治:通过给团队提供广泛的自治,他们变得更快乐、更有效率、更投入。
- **通过检查改进:**团队被要求不断地检查自己,尤其是在每个冲刺阶段结束时的回顾中。这可以帮助团队通过从以前的周期中学习和适应来加速他们在每个开发周期中的表现。
- 经验证据:和数据科学一样,Scrum 建立在基于已知的执行原则之上。“经验主义断言,知识来自经验,并基于已知做出决策。Scrum 采用迭代、增量的方法来优化可预测性和控制风险”。
- Scrum 的缺点
- **时间拳击挑战:**虽然它提供了许多好处,但 Scrum 的时间拳击特性是有争议的,尤其是对数据科学团队而言。实施大多数数据科学问题的解决方案所需的时间是不明确的。
**“潜在的可释放增量”挑战:**这一挑战对于数据科学团队来说尤其艰巨,甚至可能没有必要。许多数据科学过程,尤其是在早期探索阶段,可能不打算在数据科学团队之外发布。此外,测试需求可能会超出 sprint 中的合理范围,尤其是在需要高度准确性的情况下(Jennings,2017)。
- 会议开销 : Scrum 会议可能每周需要多达四个小时,外加额外的时间用于积压工作细化和管理(萨瑟兰& Schwaber,2017)。这些会议可能被视为应该避免的开销(Beverly,2017)。
- **难以掌握:**在一项受控实验中,在数据科学项目中使用 Scrum 的学生团队表现不佳,很大程度上是因为他们无法理解方法学,也无法建立清晰的冲刺(萨尔茨、沙姆舒林、&克罗斯顿,2017)。显然,Scrum 有一个相当陡峭的学习曲线。
- Crisp-DM
- 这是一个棘手的问题。它在列表中,但它不完全是项目管理方法。
CrOSS-IindustrySstandardPprocess forDATAMining 最初是为数据挖掘而设计的,是一种具有六个阶段的方法,自然地描述了数据科学的生命周期。它为任何人,从新手到专家,提供了进行数据科学/挖掘项目的完整蓝图。
**Crisp-DM:阶段和任务
**业务理解:**从业务角度探索项目目标和需求,将这些知识转化为数据科学问题定义,并设计实现目标的初步方案。
**数据理解:**初始数据收集,然后 EDA 以熟悉数据,识别数据质量问题,发现对数据的第一个见解或检测子集以形成快速实验的假设。
**资料准备:**我们都知道,这个阶段通常是最耗时最无聊的。通过手动编辑电子表格或编写自定义代码来清理和重新格式化数据并不好玩。但是这个阶段涵盖了从初始原始数据构建最终数据集的所有活动。干净的数据有助于识别离群值、异常和模式,这些数据可用于接下来的步骤。
建模:这是数据科学项目的核心活动,它需要编写、培训、测试和改进模型,以分析数据并从中获得有意义的商业见解。不同的 ML 技术被应用于数据,以识别最适合业务需求的 ML 模型。
**评测:**在前一阶段,我们用不同的算法进行了多次实验。现在,我们可以选择最适合业务需求并提供最佳精度性能比的产品。
**部署:**在这个阶段,我们通常将 ML 模型部署到预生产或测试环境中。然后,一旦我们对现场测试感到满意,我们就部署它并进入 MLOps(阅读这篇文章中关于 MLOps 的更多内容)。
我们应该使用 CRISP-DM 进行数据科学项目管理吗?
我们来看一些数据。根据 kdnuggets 在 2014 年进行的汇总,用于分析、数据挖掘或数据科学项目的两种主要方法是:
脆饼干-德国马克-43%
我自己的(混合)–27.5%
CRISP-DM 是 2014 年和之前所有年份的流行方法,可以追溯到 12 年前。
- 有趣的是,在 2020 年 8 月和 9 月由datascience-pm.com进行的另一场比赛中,CRISP-DM 是数据科学界的不败冠军。
- 数据到此为止,我也给你我作为数据科学家的看法。
我认为如果你正在组建一个新的数据科学部门/团队,CRISP 是一个很好的起点。不同的阶段自然地描述了数据科学过程,这使得它更容易被采用。
它还鼓励可互操作的工具。您可以通过利用许多不同的微服务为您的项目创建一个完全定制的解决方案,而不是使用端到端的整体工具——您可以避免 SPOF(单点故障),如果一个工具出现故障,您只需插入一个新工具。
尽管 CRISP-DM 设计良好,经受住了时间的考验,但它未能涵盖数据科学过程的现代部分,这可能会导致问题。但这没什么好担心的,因为我们可以使用下面的最佳实践来克服这些问题。
最佳 CRISP-DM 实践
以下是克服 CRISP-DM 缺点的五个技巧:
**快速迭代:**不要在项目的各个层面上彻底地工作,以免陷入瀑布陷阱。最好异步思考和工作。专注于迭代地提供更多价值。你的第一个成果可能不会太有用。没关系。迭代。
足够多的文档…但不要太多:如果你严格遵循 CRISP-DM,你可能会花更多的时间来做文档。做合理适当的事,但不要做过头。
不要忘记现代技术:在您的项目计划中,添加一些步骤来利用云架构和现代软件实践,如 git 版本控制和 CI/CD 管道。
- 设定期望: CRISP-DM 缺乏与利益相关者的沟通策略。所以一定要设定预期,经常和他们沟通。
- **与真正的项目管理方法相结合:**作为上一条的概括,CRISP-DM 并不是真正的项目管理方法。所以把它和数据科学协调框架结合起来。流行的敏捷方法包括:
- 看板法
- 混乱
- 数据驱动的 Scrum
- 正如我们前面所讨论的,这种方法鼓励在整个数据挖掘过程中使用可互操作的工具(对于数据科学也是如此),所以 CRISP-DM 是工具中立的。
- CRISP-DM 的优点
- 可概括:虽然是为数据挖掘而设计的,但 CRISP-DM 的创始人之一 William Vorhies 认为,由于所有的数据挖掘/科学项目都始于业务理解,拥有必须收集和清理的数据,并应用数据科学算法,“CRISP-DM 甚至为当今最先进的数据科学活动提供了强有力的指导”(Vorhies,2016)。
**常识:**在一项研究中,接受过培训并被明确告知实施 CRISP-DM 的团队比使用其他方法的团队表现更好(萨尔茨、沙姆舒林、&克罗斯顿,2017)。
**易于使用:**与看板一样,CRISP-DM 无需太多培训、组织角色变化或争议即可实施。
**正确的开始:**最初对业务理解的关注有助于将技术工作与业务需求结合起来,并引导数据科学家避免在没有正确理解业务目标的情况下就贸然解决问题。
**强有力的收尾:**它的最后一步,即部署,提出了结束项目的重要考虑事项,并简化了向维护和运营的过渡。
灵活:一个松散的 CRISP-DM 实现可以灵活地提供敏捷原则和实践的许多好处。通过接受一个项目从重要的未知开始,用户可以循环通过各个步骤,每次都获得对数据和问题的更深入的理解。从前一个周期学到的经验知识可以进入下一个周期**。**
CRISP-DM 的缺点
文档繁重:几乎每个任务都有一个文档步骤。
**不现代:**与 Vorheis 关于 CRISP-DM 持续相关性的论点相反,其他人认为 CRISP-DM 作为大数据之前的流程,“可能不适合大数据项目,因为它有四个 V——量、多样性、速度和准确性”(Saltz & Shamshurin,2016)。
**不是一种项目管理方法:**也许最重要的是,CRISP-DM 不是一种真正的项目管理方法,因为它隐含地假设其用户是一个人或小型、紧密的团队,并且忽略了大型项目所必需的团队协作(萨尔茨、沙姆舒林、&康纳斯,2017)。
看板法
看板(日语中的字面意思是“广告牌”)开始于 20 世纪 40 年代,是丰田制造的供应链和库存控制系统。它最大限度地减少了在制品,并使汽车零部件的供应与需求相匹配。包括软件在内的其他行业也因为看板的有用性而采用了它。
看板从潜在特性或任务的列表开始,类似于 Scrum 的 backlog 概念。它们被放在看板的初始待办事项栏中,看板是工作流的可视化表示。
Kanban
在一个简单的三栏(或三箱)看板中(如上图所示),当团队决定开始一项任务时,看板卡(便笺条)从待办事项栏移到正在进行栏。当团队完成其任务时,它会移动到“完成”列。
看板通常有额外的栏目。例如,数据科学团队可能会将数据分成 3 栏:数据收集;分析;转型/准备。
数据科学项目管理应该使用看板吗?
看板对于数据科学非常有效。如果你还记得上一节中 datascience-pm.com 做的 2020 池,看板是第三种最流行的方法。
Kanban boards often have additional columns. For example, data science teams might split data into 3 columns: data gathering; analysis; transformation/preparation.
看板的灵活流程为数据科学家提供了更大的灵活性来执行他们的工作,而不必达到固定的截止日期——在看板团队中,没有必需的时间框。
像其他敏捷方法一样,工作被分成小的增量,这允许快速迭代和连续交付。看板提供了一些结构,这比许多数据科学团队目前所拥有的要多(Saltz,Shamshurin & Crowston,2017)。
看板最佳实践
看板只是数据科学项目管理方法解决方案的一部分。使用看板的团队需要其他合适的流程,比如将看板与另一个鼓励有效客户互动的敏捷框架(即 Scrum 或 CRISP-DM )混合。
根据这篇关于 2020 年最佳看板工具的文章,以下是前 6 名:
看板的优点
**高度可视化:**看板的高度可视化和简单性使其能够非常有效地为团队成员和利益相关者快速传达正在进行的工作(Brechner,2015)。
**非常灵活:**与 Scrum 的批处理周期方法相反,看板通过一次引入一个工作项目,为团队提供了更大的灵活性来改变齿轮(里格比、萨瑟兰、&竹内,2016)。避免了不能在冲刺截止日期前完成项目的冲突。
**轻量级和适应性强:**通过不规定时间框、角色和会议(里格比、萨瑟兰、&竹内,2016),管理看板的开销需求明显少于瀑布和 Scrum。看板为团队提供了采用他们自己的额外流程的自由。
- **避免文化冲突:**作为一个不重新定义团队角色的非常简单的系统,看板遇到的文化和组织阻力比 Scrum 少(里格比、萨瑟兰、&竹内,2016)。看板不是一个侵入性的过程;相反,团队可以无缝地采用它,而不必笨拙地转换到一个完全不同的系统。
- 更好的协调:简单、直观、轻量级和灵活的结构,没有紧张的截止日期,可能使看板比其他方法更有利于团队合作。
- **尽量减少在制品:**在制品(在制品)限制可以增加总生产量,减少未完成工作的投资,因为它们可以防止在给定流程中堆积过多的在制品(Brechner,2015)。
- 看板的缺点
- **客户互动未定义:**作为一个面向内部的流程,看板并没有直接规定面向外部的流程,用于丰富而频繁的客户反馈循环。如果没有 sprint 评审的结构化步调,客户可能不会对流程有所承诺(Akred,2015)。
- 缺少截止日期:相对于 Scrum,如果没有动力去完成不断逼近的截止日期,团队可能会在某些任务上花费过多的时间。需要更高水平的团队纪律来确保任务不会比需要的时间拖得更长。
**看板列定义:**如何定义数据科学看板的列?似乎没有好的答案。要设置特定于数据科学的委员会,您要么需要使用通用委员会,要么尝试创建包含数据科学流程所有步骤的委员会。
- 为什么不是混动车型?
- 因为没有一个放之四海而皆准的模型,团队经常创建他们自己的混合模型。混合模型是两种或多种方法的组合,经过修改以适应独特的业务环境。
- 什么时候应该使用混合动力?
Hybrid 可用于小型、中型和大型项目。当产品交付依赖于硬件和软件操作时,这是一个有效的解决方案。但是选择混合动力还有另一个原因:
客户对未指定的时间表和预算以及缺乏规划不满意的情况并不少见。这种不确定性是敏捷的典型特征。在这种情况下,规划、需求规范和应用程序设计可以在瀑布中完成。敏捷适用于软件开发和测试。
现在,虽然创建一个混合模型可能很有挑战性,但是它可以提供很大的价值,因为您可以从现有的模型中挑选最好的质量,并混合和匹配它们。
我知道你在想什么,我能不能只挑最好的品质就这样?当然不是,这里面有蹊跷。我将在下一节揭示它。
现在我们来看一些例子。数据科学有两种常见的混合方法:
双峰:敏捷-瀑布
也称为瀑布式敏捷,结合了瀑布和 Scrum 的元素。这很有挑战性,但是在一些特殊的情况下,比如涉及医疗设备数据处理的项目,这种方法效果最好。
双峰是什么意思?开发和发布软件有两种模式。模式 1 是严格的和可预测的,但是安全的。模式 2 敏捷而快速,但是有风险。
模式 1 传统;因此,它在众所周知和可预测的领域中完美地工作。根据 Gartner 的说法,它侧重于利用已知的东西,同时将传统环境转变为适合数字世界的状态。
模式 2 涉及快速应用开发。它是探索性的、非线性的,并为解决新问题而优化。模式 2 对于需要尽快完成的项目尤其有用。
我们可以使用双峰进行数据科学项目管理吗?
人们对结合敏捷和非敏捷方法有一种复杂的感觉。但印第安纳大学高级执行副院长埃里克·斯托尔特曼认为这种结合是好的。他说像瀑布这样的结晶过程和像 Scrum 这样的液体过程应该同时共存。
KSM 咨询公司的高级 IT 项目经理 Mark Schiffman 对此表示赞同。他将一个理想的数据科学项目管理方法描述为“类似于用瀑布包装器包裹的 Scrum”。他建议瀑布视图更适合以客户为中心的方面,例如需求收集以“让他们领先开发一步”,并且 Scrum 视图更适合开发(Schiffman,2017)。
- 印第安纳大学信息和图书馆科学副主任 Carol Choksy 同样认为,数据项目需要更密集的前期规划,最好使用 PMI 项目管理知识体系中的传统规划原则来处理。一旦确定了初始需求的范围,敏捷就适用了(Choksy,2017)。
- 从各种模型中挑选最好的方面来形成自己的模型是很诱人的,但是这种混合方法被批评为不能提供瀑布的结构优势和敏捷的灵活性优势(Sutherland,2014)。敏捷的顽固分子(也称为敏捷论者)给这种方法贴上负面的标签,称之为“易变的”、“脆弱的”或“混乱的”,以此来质疑它们的使用。那么,您可以使用哪些最佳实践来让它发挥作用呢?
双模方法的最佳实践
Gartner 的行业分析师认为,在双峰项目中挣扎的组织应该采用一种更加以结果为中心的项目管理方法。这将帮助他们最有效地管理“慢”(模式 1)和“快”(模式 2) IT 的不同需求。
使用一种简单的方法来确定哪种模式有意义:
决定在一个项目中使用哪种模式通常与公司文化有更大的关系。
将预期的业务成果定义为成功的衡量标准:
当您使用模式 1 时,很容易确定业务结果,因为一切都是很好理解和可预测的。这对于模式 2 来说是不正确的,而这恰恰是数据科学项目的工作方式。因此,在开始项目之前,弄清楚成功应该是什么样子是很重要的。
明确分离投资组合和项目治理:
- 许多组织努力的最后一个领域是在项目开始后保持一致的项目治理方法。
为了更好地理解这一点,让我们分解项目组合治理和项目治理。
- 项目治理:
定义项目、方案或组合的建立、管理和控制的一套政策、法规、职能、流程、程序和责任。
- 投资组合治理:
旨在回答组织应该如何监督项目组合管理的问题,主要关注与项目组合活动相关的领域。有效的项目组合治理确保项目组合与组织的目标一致,是可持续的,并且可以有效地交付。
投资组合治理还指导投资分析:
识别威胁和机会,
评估变更、影响和依赖性,
实现绩效目标,
选择、安排和优先处理活动。
双模方法没有一套清晰的工具。通过实验,你需要创造一套适合你的。为此,您需要考虑这两种模式的工具。
- **模式 1 工具:**使用 BI(商业智能)工具,这些工具既不适合临时流程,也不适合可视化/数据发现。他们通常不够敏捷,数据捕获、元数据创建和内容交付的价值实现时间通常以月为单位。
- **模式 2 工具:**这些工具在单个桌面环境中或多或少包含了数据分析所需的一切。他们敏捷、灵活,专注于漂亮、直观的视觉呈现。
- 问题是模式 2 工具不能做所有的事情。像像素完美报告、复杂建模和爆炸这样的事情不是他们的专长,也不是他们的路线图。
- 这些不足给组织留下了难题,要么牺牲重要的功能,要么通过采用双模方法来取得平衡。
双峰的优点
- 结合两种 IT 模式有很多好处 :
- **速度。**通过定义和管理一个专注于交付新解决方案的 IT 领域,他们可以快速生产以满足业务需求。
**创新。**由于模式 2 的重点不是维护安全性和处理日常问题,他们可以专注于需要创新来解决的更广泛的问题。
**敏捷。**许多组织的目标是颠覆某个行业——通过定义 IT 的哪些部分专注于这些颠覆,他们可以更快地实现目标。那些处于模式 2 的 IT 人员变得擅长敏捷实践,因此风险和开销更少,并且随着时间的推移,工作会更加顺利。
**减少“影子 IT”。**当用户快速获得他们需要的解决方案时,他们使用未经授权或未经证实的应用程序和软件的可能性会大大降低,因为他们不会绕过 IT 部门。
双峰的缺点
- 别离可以散漫 。通过明确地将人们分为模式 1 和模式 2 组,团队可能会争夺注意力、资源、权力和影响力。这可能会在更大的 IT 领域内形成一种“我们对他们”的心态。
*** 分离可能过于整齐。以这种方式定义两种 IT 模式似乎表明这两种模式不会或不应该相互依赖。对于许多企业来说,现实是一个创新的、功能良好的应用程序或软件解决方案,即模式 2 的目标,通常依赖于模式 1 中固有的运行良好的遗留系统。 这种分离可能会令人困惑。仅仅为了“创新”而混淆团队通常会导致角色和流程的混淆。这种困惑可以表现为对变革的抵制,当员工被告知对他们没有意义的变革时,这种情况很常见。 分离并不能保证创新。简单地将一个团队定义为创新团队并不意味着它会自然而然地发生——如果发生了,每个人都会成为创新者。事实上,一些企业发现创新来自技能和工具的混合,而不是来自有意绘制的线条。
**### 微软 TDSP 公司
- 如果你把 Scrum 和 CRISP-DM 结合起来,你会得到类似微软团队数据科学过程的东西。TDSP 于 2016 年推出,是“一种敏捷、迭代的数据科学方法,可高效提供预测分析解决方案和智能应用。”(微软,2020 年)。
- The separation can be too neat. Defining two IT modes in this way can seem that the modes won’t, or shouldn’t, rely on each other. For many enterprises, the reality is that an innovative, well-functioning application or software solution, the goal of Mode 2, often relies on well-oiled legacy systems that are inherent in Mode 1.
- TDSP 的项目生命周期类似于 CRISP-DM,包括五个迭代阶段:
- **业务理解:**定义目标,确定数据来源
**数据获取和理解:**摄取数据并确定它是否能回答问题(有效地结合了 CRISP-DM 中的数据理解和数据清理)
**建模:**特征工程和模型训练(结合建模和评估)
Microsoft Team Data Science Lifecycle (Microsoft, 2020)
**部署:**部署到生产环境中
**客户验收:**客户验证系统是否满足业务需求(CRISP-DM 没有明确涵盖的阶段)
- 微软解释说,“TDSP 有助于改善团队协作和学习。”所以现在,只剩下一个问题了。
- 我们应该使用微软 TDSP 进行数据科学项目管理吗?
- 耶!通过将现代实践与数据科学生命周期相结合,TDSP 非常全面,由四个主要部分组成:
- 数据科学生命周期定义,
- 标准化的项目结构,
推荐的基础设施和资源,
推荐的工具和实用程序。
这种方法经常利用微软 Azure,这并不奇怪,但也不是必须的。你可以有不同的技术堆栈,但仍然使用 TDSP。
- A data science life cycle definition,
- TDSP 生命周期被建模为一系列迭代步骤,为使用预测模型所需的任务提供指导。
- 您在生产环境中部署预测模型,并计划用它来构建您的智能应用程序。这个流程生命周期的目标是继续将数据科学项目推向一个明确的项目终点。
- 数据科学是一项研究和发现的实践。如果您将它与一种为您提供一组定义良好的工件来简化沟通的方法结合起来,您可以避免许多误解。
对于 TDSP 的每个阶段,我们提供以下信息:
**目标:**具体目标。
**如何做:**具体任务的大纲,以及如何完成这些任务的指导。
**工件:**可交付物和生产它们的支持。
TDSP 最佳实践
研究 TDSP 的最佳实践,我没有发现太多。后来,我意识到 TDSP 包括来自微软和其他行业领导者的最佳实践和结构,这有助于团队成功实施他们的数据科学计划。目标是帮助公司充分认识到他们的分析计划的好处。
- 注 :关于 TDSP 最佳实践的详细描述,请查看本文末尾的参考资料部分,在“微软 TDSP”下您会找到我的所有资料来源。
- TDSP 是一种现代方法,因此它的工具包括最新和最棒的。我们来看看吧!
- TDSP 推荐利用现代基于云的系统和实践的基础设施、资源、工具和实用程序,例如:
GitHub: 增强协作,自动化您的代码到云工作流,并通过高级功能帮助保护您的代码。
Azure Pipelines: 实现 CI/CD 持续构建、测试和部署到任何平台和任何云。
Azure Boards: 使用看板、积压订单、团队仪表板和定制报告,跨团队计划、跟踪和讨论工作。
Azure Monitor: 全面观察您的应用、基础设施和网络。
Visual Studio: 使用集成开发环境(IDE)为 Azure 创建强大的、可伸缩的应用程序。
- Azure Kubernetes 服务(AKS): 使用完全托管的 Kubernetes 服务,更快地交付容器化的应用程序,并更轻松地操作它们。
- TDSP 的优点
- **全面:**不仅仅是一个流程,还包括 GitHub 上可重复使用的模板、角色定义等等。
- 可选地包含 Scrum: TDSP 可以可选地与 Scrum 结合使用(在 Scrum 中,sprint 会经历所有阶段)。
- **维护:**微软似乎每隔几个月就会更新一次它的指南和知识库。
- TDSP 的缺点
一些不一致:微软似乎有时会忘记将它的一些更新扩展到它的所有文档中。
- **陡峭的学习曲线:**一些团队发现全面的框架学习起来很复杂,并且有太多的结构(例如,详细的管理角色和特定的文档模板)。
- 微软特定方面:虽然框架的大部分独立于微软的技术堆栈,但框架的其他部分,尤其是基础设施,特别提到了微软的产品。
- Domino 生命周期
作为一种结合了 CRISP-DM 元素和敏捷方法的现代方法,Domino 的数据科学生命周期在概念上类似于微软的 TDSP。它有更广泛的流程,但支持资源较少。
- Domino 是一个项目框架,有六个阶段:
- **构思:**定义问题,确定项目范围,并有一个可行/不可行的决策点
- **数据获取和准备:**确定现有的数据集,探索获取新数据集的需求,并为建模准备数据集
**研发:**假设检验和建模
**验证:**业务和技术验证
**交付:**部署、A/B 测试、用户验收测试
**监控:**系统和模型监控
- 嗯,这种方法有正确的成分,它采用了 CRISP-DM 和一些类似于 TDSP 的概念,对吗?不,不是真的。在前面关于双峰方法的章节中,我们看到“从各种模型中挑选最好的方面来形成你自己的模型是很诱人的,但是这种混合方法被批评为不能提供瀑布的结构优势和敏捷的灵活性优势(Sutherland,2014)。”
- 这就是说,外表可能具有欺骗性,所以我们仍然需要回答下面的主要问题。
- 我们应该使用 Domino Lifecycle 进行数据科学项目管理吗?
- 幸运的是,这里的答案是肯定的!
- Domino 生命周期对于喜欢构建自己的常识性方法(特别是在定义项目阶段方面)并且不寻找复杂方法的大型团队来说是理想的。
- 采用并坚持单一的项目框架可以帮助解决数据科学工作失败的许多潜在原因,但是如果他们希望框架保持有用,经理们在扩展时必须小心。
Domino 生命周期的最佳实践
Domino 可以用来管理 100 多名数据科学家的团队和 300 多个同时进行的项目,下面是方法:
衡量一切,包括你自己。具有讽刺意味的是,数据科学家生活在测量的世界里,而我们却很少测量自己的工作。在聚合工作流中跟踪模式有助于创建模块化模板,传播来自高绩效团队的最佳实践,并引导对内部工具和人员的投资以缓解瓶颈。
例如,通过检查他们多年来的全部工作,一家大型科技公司意识到他们只有 15-20 个典型问题需要解决,然后计划只在适当的地方应用模板。另一个组织对数百个项目的聚合状态进行季度审查,并意识到它们在 ETL 中一直受阻,因此他们重新分配预算以增加数据工程人员。
专注于减少迭代的时间。许多组织认为模型部署是一件轻而易举的事,但实际上应该是绕跑道跑几圈。测试真实结果的最小障碍(不牺牲严格的验证)是数据科学成功的另一个重要预测因素。
例如,领先的科技公司在几分钟内部署新模型,而大型金融服务公司可能需要长达 18 个月。
社交化总体投资组合指标。即使不精确,将整个数据科学项目组合的影响社会化也是至关重要的。这样做可以解决数据科学家对影响的担忧,并有助于解决管理层对投资数据科学的担忧。
在与利益相关者交流时,他们可能会震惊地得知有多少项目实际上正在进行中。如果他们知道发生了什么会更好。
重要的是,许多成功的数据科学经理并不把功劳归于自己,而是所有利益相关者的集体成就。
像 CRISP-DM 一样,这种方法也鼓励可互操作的工具,所以它是工具中立的。
Domino 生命周期的优点
基于“什么有效”: Domino 基于 20 多个数据科学团队的经验建立了这个流程。
**广义的团队定义:**团队不仅仅是一个技术团队,还包括业务干系人和产品经理。每个相关的利益相关者(技术或业务)都参与项目前期构思。
**灵活:**实践可以与其他方法混合和匹配。
**没有固定的节奏:**正如 Domino 前产品总监 Mac Steele 所观察到的,数据科学不会“在两周内奇迹般地发生”
Domino 生命周期的缺点
**不够全面:**与它的堂兄 TDSP 相比,Domino 的流程没有可复制的模板和详细的定义。
- 未更新: Domino 在一个一次性指南中定义了这个过程,此后就没有更新过。
- **团队协作未定义:**虽然流程建议进行许多迭代(通过它们的阶段),但不清楚团队应该如何决定什么是“在”迭代中,以及如何构建与业务涉众的对话。
- 数据驱动 Scrum (DDS)
- Scrum 在数据科学家中往往不受欢迎。一个关键原因是 Scrum 定义了固定时间的冲刺,旨在交付潜在的可交付增量。不幸的是,这可能会短路数据科学的实验性质。
另一方面,DDS(数据驱动 Scrum)是在考虑数据科学的情况下设计的。具体来说,DDS 支持精益迭代探索性数据科学分析,同时承认迭代的长度会因项目的阶段而异(收集数据与创建机器学习分析)。
- DDS 结合了 Scrum 和看板的概念。你可能听说过另一种方法,它不在我的列表中,Scrumban。Scrumban 和 DDS 如果结合了相同的概念有什么区别?Scrumban 更像是 Scrum 框架中的看板。DDS 没有实现 Scrum 的固定长度 sprints,但是 Scrumban 实现了,这给数据科学带来了几个挑战。
- 我们应该使用 DDS 进行数据科学项目管理吗?
- Team Coordination not defined: While the process suggests to do many iterations (through their phases), it’s not clear how the team should decide what is “in” an iteration, and how to structure the dialog with the business stakeholder.
是啊!数据驱动的 Scrum (DDS)除了基于一个熟悉和众所周知的敏捷框架之外,还通过从 Scrum 中移除一些东西来解决固定时间冲刺的主要问题:
迭代是可变长度的,以容量为中心,并且它们可以重叠。
迭代不是交付潜在的可交付的待办事项,而是关注数据科学的本地概念(例如,实验、待回答的问题)。这些项目中的每一个都被分解成任务来创建、观察和分析。
待办事项选择以更连续的方式进行。
Should we use DDS for Data Science Project Management?
DDS 是非常简化的 Scrum,增加了看板和 WIP(工作进展)限制,提供了一种可视化的方式来交流工作流和识别瓶颈。
这是一种非常独特的方法,它最大的优点也是它最大的缺点。用让·瓦尼尔的名言来说:
- 当我们开始接受自己的弱点时,成长就开始了
- 没有什么是完美的,那么让 DDS 为我们工作的最佳实践是什么呢?
- 最佳 DDS 实践
如果您打算在组织中使用 DDS,以下是 3 个最佳实践:
允许基于能力的迭代–这里没有放之四海而皆准的方法,有时进行一天的迭代是有意义的,有时进行三周的迭代(由于获取/清理数据需要多长时间,或者进行探索性分析需要多长时间)。目标应该是允许以一致的方式发布工作的逻辑块。
从迭代中分离会议——这是一把双刃剑。如果做得好,它可以产生巨大的结果,但做得不好,它可能会破坏团队的表现。迭代结束时的会议是学习和计划改进的基础。但是由于迭代可能非常短(例如一天进行一个特定的探索性分析),DDS 会议(例如改进过程的回顾会)应该基于一个基于逻辑时间的窗口,而不是与每个迭代相联系。
仅需要高层次的项目评估–在许多情况下,为探索性分析定义明确的时间表是困难的,因此不需要生成精确的详细任务评估来使用该框架。但是,高层次的“t 恤”级别的工作评估有助于对要完成的潜在任务进行优先级排序。
DDS 的优点
**基于能力的迭代:**承认已定义迭代的好处,但是跳过了硬性截止日期的不灵活性,以交付潜在的可交付增量。
**适合 Scrum 组织:**与 Scrum 的相似之处不仅仅是过程名称,这使得 DDS 对 Scrum 友好的组织有吸引力。
- **灵活适应各种生命周期:**并非所有数据科学项目都遵循相同的 CRISP-DM 式生命周期。通过避免生命周期定义,DDS 可以适应不同类型的数据科学项目。
- **将迭代从回顾和回顾中分离:**将回顾和回顾从迭代的完成中分离出来,可以实现短时间的、频繁的迭代,同时仍然保持这些仪式的常规时间表。
- DDS 的缺点
**不全面:**缺乏生命周期可能是寻找定义步骤的团队的障碍,就像在 CRISP-DM、TDSP 或 Domino Data Science Lifecycle 中发现的那样。
- **从回顾和回顾中分离迭代(可选视图):**这可能会使回顾和回顾在发生时显得陈旧。
- 研究与开发
- 广义地说,研究和开发是调查、原型制作和生产创新产品的一整套方法。
- 一个数据科学项目可以被看作是一项研究,其成果会转化为一个工程项目。研发方法将整个项目分为两大块:
一个数据科学研究阶段,
- 随后是工程/开发阶段。
- 这些阶段中的每一个都将使用不同的方法进行管理,通常在数据科学阶段使用松散结构的甚至是临时的方法,在工程阶段使用敏捷方法。
什么是 R&D?
首先,我们必须了解研发方法的根本区别:
研究–在此阶段,许多方法和分析被快速尝试并丢弃。有些想法是部分探索,然后放弃。像 NeptuneAI 或 MLFlow 这样的实验跟踪工具,结合 Jupyter 或 Zeppelin 笔记本,被用作实验的历史。时间不会花在编写错误恢复代码或编写子例程上,因为这些代码可能永远不会被使用。
- 开发–在这个阶段,现在有了需求,这些需求是研究阶段的结果。但是,研究者笔记本中的代码一般不是生产质量。经常需要对研究人员的代码进行重新设计,以使这些代码非常适合生产环境。
- 我们应该使用 R&D 方法进行数据科学项目管理吗?
是啊!
数据科学和 ML 本质上是实验性的。很自然,最好的方法是 R&D,因为它向创新敞开大门,避免通过一系列标准化的步骤来扼杀创造力和创新。
就个人而言,我认为这一点需要多说:任何需要创造力的努力在高度标准化和规范化时都会受到影响,因为创造力是杂乱的!
研究和开发已经让数据科学走到了这一步,如果我们想继续推进可能性的边界,我们应该让 R&D 继续活着。
我有两个有趣的研究案例为这种方法带来了更多的权重:Google Brain 和 DemandJump。两者都在数据科学阶段使用一种非常特别的方法,在开发阶段使用一种敏捷的方法。
最佳 R&D 实践
以下方法在与 R&D 方法结合使用时显示出了前景:
鼓励您的数据科学家了解部署阶段,鼓励您的工程师了解研究阶段。开发端到端的理解是非常宝贵的。
鼓励您的数据科学家在研究阶段考虑模型设计时考虑生产要求和部署的技术复杂性。例如,如果需求是实时推理,那么模型是否足够轻量级来支持它?
将数据工程师与数据科学家结合在一起可能会取得成功。数据工程师的工作是提取和准备数据科学家所需的数据。这使数据科学家能够专注于他们的最高价值,同时确保数据工程师意识到与生产数据相比,在模型构建过程中所做的妥协。
工作轮换是鼓励这种理解的另一种方法。例如,一名数据科学家可能会成为一名数据工程师,为期约 3 个月。
功能测试必须由数据科学家设计,以执行相同的结果——或统计定义的相似结果——这意味着生产代码应该与相同数据上的开发代码相匹配。数据科学家选择一个代表性数据集进行测试。对于测试确定性函数,如特征工程,生产结果必须等于数据科学家编写的函数。然后,生产团队将在生产环境中实施测试,并将测试包含在任何生产 QA 中。
顾名思义,这种方法本质上是实验性的,因此它也鼓励使用可互操作的工具,并且不局限于特定的工具集。但是行业中运行和跟踪实验的一些常用工具有:
Jupyter 笔记本——用来跑实验,
齐柏林笔记本——用来跑实验,
Github–代码版本化和存储库,
Neptune ai–跟踪不同的实验,并易于与其他工具和框架耦合,
ml flow–跟踪不同的实验,管理模型和数据,
Pytorch 等等。
- R&D 的优点
- **符合数据科学生命周期:**与部署/工程工作相比,数据科学工作需要更松散的结构。因此,相应地管理每个阶段。
- **符合研究背景:**许多数据科学家来自研究背景,会发现这种方法很自然。
- R&D 的缺点
- **阶段转换:**项目经常在艰难的生命周期转换点失败。在项目开始时,需要与工程、IT 和业务部门进行协调,而不是事后才想到。
- **临时数据科学:**最初的数据科学阶段可能会成为临时流程缺点的牺牲品。
对照表
- 我最喜欢的方法
- 写这篇文章对我来说非常有趣,因为我使用 Scrum-ban 为我的客户创建定制软件和数据科学解决方案,trello、github、pytorch 和 aws cloud 是我的首选工具,但我想调查和探索还有哪些其他方法。挑战很有趣,因为我学到了很多东西。
我非常喜欢可互操作的工具,因为它们可以让您灵活地即插即用任何新工具或替换现有工具。因此,由于这个事实以及前面提到的许多其他原因,我爱上了不止一种而是三种方法,即:
- 结论
- 谢谢你陪我踏上这段旅程!以下是我最后的想法:
我认为这一切都归结于什么最适合你的组织,基于文化和人。最流行的方法可能不太适合您的组织,而非常适合另一个组织。
因此,从一个朋友、工程师、极客和数据科学家的角度来看,我认为您应该使用这里提供的关于不同方法的数据,进行自己的研究,并尝试各种方法,以便找到最适合您组织的方法。不要试图让你的公司适应最流行的方法,而是根据你的需要调整方法。
也就是说,我在下面组织了一个巨大的参考链接列表,供你更深入地挖掘我们讨论过的任何主题。谢谢,祝你的项目好运!
参考
临时的
通信(communication 的简写)
生命周期
瀑布 vs 敏捷
敏捷
混乱
脆的
看板法
混合物
双峰的
微软 TDSP 公司
多米诺骨牌
研究与开发
Scrum
Crisp
Kanban
Hybrid
Bimodal
Microsoft TDSP
Domino
Research & Development*****
如何在 ML 中对各种数据源的数据进行版本控制
原文:https://web.archive.org/web/https://neptune.ai/blog/data-versioning-control-for-various-data-sources
数据版本控制是机器学习中的一个重要概念,因为它允许跟踪和管理数据随时间的变化。由于数据是任何机器学习项目的基础,因此有必要建立一个系统来跟踪和管理数据随时间的变化。然而,数据版本控制经常很少被关注,导致诸如数据不一致和无法再现结果之类的问题。
在本文中,我们将讨论数据版本控制在机器学习中的重要性,并探索用不同类型的数据源实现它的各种方法和工具。
什么是机器学习中的数据版本化?
在机器学习中,数据是建立和训练模型的基础。因此,建立一个系统来跟踪和管理数据随时间的变化是至关重要的。这就是数据版本控制的用武之地。
机器学习与传统软件工程中的数据版本控制
机器学习和常规软件工程中的数据版本控制有一些相似之处,但也有一些关键差异需要考虑。
在这两种情况下,数据版本控制系统的主要目标是跟踪和管理数据随时间的变化。这允许在必要时恢复到以前的版本,以及了解所做更改的历史。
但是,我们需要考虑一些关键差异:
数据的大小和复杂性
在机器学习中,我们经常处理大量的数据。基本上每个机器学习项目都需要数据。但是,数据工程师和数据库管理员在与机器学习无关的项目中处理、控制和存储万亿字节的数据并不罕见。
当谈到数据复杂性时,可以肯定的是,在机器学习中,我们正在处理更复杂的数据。首先,机器学习工程师和数据科学家经常使用不同数据供应商的数据。一些数据集正由数据输入专家和人工检查员进行校正。来自不同格式、数据库和来源的数据被组合在一起进行建模。数据科学家通常应用不同的数据插补和转换技术来创建具有特征的数据集。有时甚至元学习模型被用来产生元特征。
多种工具和技术
机器学习通常包括使用许多不同的工具和技术。这些工具可能有自己的版本控制系统,很难与更广泛的数据版本控制系统集成。
例如,我们的数据湖可能包含各种关系和非关系数据库、不同格式的文件以及使用不同云提供商存储的数据。数据科学家也可以为特征或特征存储建立单独的文件,并使用各种工具进行模型版本控制和实验跟踪。
考虑到工具和数据类型的范围,单独的数据版本逻辑将是必要的。不同的团队角色也可能在不同的阶段负责版本化数据。例如,数据工程师和数据库管理员可能处理数据湖中原始数据的版本控制,而数据科学家可能负责与实验跟踪相关的特征和数据的版本控制文件。
Different data sources and states in an MLOps project | Source
为什么数据版本化在机器学习中很重要?
数据版本化在机器学习中很重要,原因有几个:
- 数据是不断发展的——在机器学习中,数据通常是在很长一段时间内收集和修改的。通过使用数据版本化系统,可以跟踪数据更改的历史,并在需要时轻松恢复到以前的版本。
- 再现性–数据版本化对于再现之前实验的结果至关重要。如果没有所用数据的清晰记录,可能很难或不可能重现相同的结果。
- 协作——在团队环境中,多人可能同时处理相同的数据。数据版本化允许团队成员看到其他人所做的更改,并确保每个人都在使用最新版本的数据。
- 可审计性–为了符合法规,可能有必要证明数据的来源。数据版本允许数据的可追溯性,并有助于检测篡改,确保数据的完整性。
选择数据版本控制工具的关键标准是什么?
为了确定适合我们工作流程的数据版本管理工具,我们应该考虑:
- 易用性–在工作流程中使用该工具有多简单?融入一个项目需要很多时间吗?
- 数据支持——它支持项目需要的所有数据类型吗?
- 协作选项——是否有多个团队成员可以共享和访问数据的选项?
- 多样化集成–它是否集成了流行的 MLOps 工具?它如何适应当前的基础架构、堆栈或模型培训工作流?
下面,我们将介绍一些值得探索的数据版本控制工具。
TL;速度三角形定位法(dead reckoning)
如果您想快速查看哪个工具提供了什么功能,这里有一个表格可供参考。
DVC
数据版本控制 DVC 是一个针对数据和机器学习团队的版本控制系统。它是一个免费的开源命令行工具,不需要数据库、服务器或任何特殊服务。它有助于跟踪和管理机器学习项目中使用的数据和模型,并允许复制结果的能力。
借助 DVC,我们可以使用 Git 提交来跟踪数据和模型的版本,并将它们存储在本地或云存储中。DVC 还使我们能够轻松地在不同版本的数据之间切换。
Data version control DVC | Source
DVC 应该和 Git 一起使用。事实上,Git 和 DVC 命令经常被依次使用。Git 用于存储和版本控制代码,DVC 对数据和模型文件做同样的事情。虽然 Git 可以在本地存储代码,也可以在 GitHub、GitLab 和 Bitbucket 等托管服务上存储代码,但 DVC 使用远程存储库来存储所有数据和模型。远程存储库可以在同一台计算机上,也可以在云上。它支持大多数主要的云提供商,如 AWS、GCP 和 Azure。
DVC 的数据版本控制非常简单明了。例如,我们需要做的第一件事是在我们的目录中初始化 Git 和 DVC:
接下来,我们使用以下命令向 DVC 跟踪添加一个数据文件:
之后,DVC 将指示我们添加在最后一个命令之后生成的两个新文件:
git add data/.gitignore data/data.csv.dvc
然后我们用 Git 提交这两个文件:
git commit -m "add raw data"
当我们在远程存储库中存储数据时,会创建一个. dvc 文件。它是一个带有 md5 哈希的小文本文件,指向远程存储中的实际数据文件。此外,这个文件应该与代码一起存储在 GitHub 中。当我们下载一个 Git 存储库时,我们也获得了。我们用来下载相关数据的 dvc 文件。
要添加远程存储,我们使用命令:
dvc remote add -d storage gdrive://google_drive_id
git commit .dvc/config -m "Configure remote storage"
最后,我们需要推动数据:
如果我们更新了数据集,我们需要再次添加、提交和推送更改:
dvc add data/data.xml
git add data/data.xml.dvc
git commit -m "Dataset update"
dvc push
在此之后,又有一个文件将被添加到我们的远程存储中。现在,如果我们想恢复到文件的先前版本,我们可以使用 Git 命令列出所有提交:
它将列出所有带有提交消息的提交散列。使用 checkout 命令,我们可以恢复到我们想要的任何提交版本:
git checkout b11343a
dvc checkout
正如我们所见,DVC 与 Git 非常相似,使用 DVC,我们可以对任何我们想要的文件进行数据版本控制。更多关于 DVC 的有用资源:
此时,一个问题出现了;为什么用 DVC 而不是 Git?
有几个原因可以解释为什么 Git 本身不是数据版本控制的最佳工具:
- 1 Git 是为文本文件版本化而设计的,并不是为处理大文件而优化的。这可能会降低大型数据集或模型的版本控制效率。
- Git 将所有文件版本存储在存储库中,随着时间的推移,这会导致存储库变得非常大。这使得对大型数据集或模型进行版本控制变得不切实际。
- 3 Git 不提供专门为数据版本化设计的特性,比如数据血统跟踪或支持不同版本数据之间的切换。
尽管如此,Git 还有一个扩展,叫做 Git LFS,它被设计用来更有效地处理大型二进制文件。
去吧,LFS
Git-LFS (Git 大文件存储)在 Git 内部用文本指针替换大文件,同时将文件内容存储在像 GitHub.com 或 GitHub Enterprise 这样的远程服务器上。有了 Git,LFS 可以使用相同的 Git 工作流来版本化大文件。
最初,这个工具是由游戏开发人员开发的,用于更有效地管理 Git 存储库中的大型二进制文件,如游戏资产。Git LFS 后来被机器学习和研究专业人员采用,他们也有大型文件,如模型和数据,以保持他们与相关代码的联系。
Versioning with Git LFS | Source
值得一提的是有一个文件存储限制。例如,在 GitHub.com,2GB 免费或 5GB 企业云选项。与 DVC 相反,这个工具不是专门为机器学习项目创建的,不提供数据沿袭跟踪,也不是 MLOps 工具。
Git LFS 的设置可能有点复杂,但是一旦完成,我们就像平常使用 Git 一样使用它。我们唯一需要做的事情是指定我们想要跟踪的文件类型。例如,如果我们想追踪。tsv 文件,我们使用命令:
只有以这种方式跟踪的文件类型存储在 Git LFS 中,而不是标准的 Git 存储中。
关于 Git LFS 的更多信息可以在这里找到:
neptune.ai
neptune.ai 是一个实验跟踪和模型注册工具,为从事许多实验的 ML 团队而构建。它提供了跟踪、组织和存储来自机器学习实验的元数据的选项。此外,使用 Neptune,可以可视化和比较结果,以及进行模型和数据版本控制。
Experiment tracking and data versioning with neptune.ai | See in the app
有了 Neptune 工件,就有可能从本地目录或任何 S3 兼容的存储中对数据集、模型和任何文件进行版本化。基本上,它会创建一个 MD5 哈希,该哈希取决于文件内容和元数据,如路径、大小和上次修改时间。对其中任何一项的更改都会导致不同的哈希。
除了哈希之外,还可以使用以下方法来对数据文件进行版本控制:
- 文件或文件夹的位置和名称
- 以 KBs 为单位的文件大小
- 上次修改的数据
一旦记录了元数据,就很容易选择实验的具体运行,并比较工件是如何变化的。
Neptune 中的工件跟踪可以用几行代码实现。例如,如果我们想跟踪一个文件,我们需要导入 neptune 包,初始化 run,并调用“track_files”方法:
import neptune.new as neptune
run = neptune.init_run()
run["train/dataset"].track_files("./datasets/train.csv")
或者如果我们需要跟踪一个文件夹:
run["train/images"].track_files("./datasets/images")
为了存储来自亚马逊 S3 的工件,我们需要配置一个具有“S3ReadAccessOnly”权限的 IAM 策略,并将我们的 AWS 凭证存储为环境变量。为此,我们在 Linux/macOS 上使用“导出”命令,在 Windows 上使用“设置”命令:
export AWS_SECRET_ACCESS_KEY='Your_AWS_key_here'
export AWS_ACCESS_KEY_ID='Your_AWS_ID_here'
为了从工件中获取元数据,我们使用“fetch_files_list”方法:
artifact_list = run["train/images"].fetch_files_list()
它返回具有以下属性的 ArtifactFileData 对象:
file_hash:文件的哈希。
- file_path:文件的路径,相对于虚拟工件目录的根目录。
- size:文件的大小,以千字节为单位。
- 元数据:包含关键字的字典:
- file_path:文件的 URL(本地或 S3 兼容存储中的绝对路径)。
- last_modified:上次修改文件的时间。
总之,Neptune 是一个简单快速的数据版本控制选项,但是它可能不像 DVC 那样提供所有的数据版本控制功能。
更多关于海王星:
傻瓜
Dolt 是一个 SQL 数据库,用于版本控制和数据共享。它有 Git 语义,包括克隆、分支、合并、推和拉的特性。Dolt 还提供了查询和分析数据的工具,以及从其他来源导入和导出数据的工具。
与 DVC 和 Neptune 不同,Dolt 是一个数据库管理系统,旨在对存储在表中的数据进行版本控制和共享。这意味着我们不能直接对 CSV 文件或任何非结构化数据(如图像)进行版本控制。相反,有一个选项可以导入几种不同的文件格式。
更准确地说,我们可以将以下格式加载到 Dolt 中:
CSV、JSON、检察官办公室
- MySQL 数据库
- Postgres
- 电子表格
- 例如,要转储一个 MySQL 数据库“test”并将其加载到 Dolt 中,命令如下:
或者,我们可以使用命令将 postgres 数据库加载到 dolt 中:
mysqldump --databases test -P 3306 -h 0.0.0.0 -u root -p > dump.sql
dolt sql < dump.sql
其中 pg2mysql 是他们的定制工具。
./pg2mysql.pl < file.pgdump > mysql.sql
dolt sql < mysql.sql
对于版本控制,Dolt 有多个分支,并将所有数据存储在一个提交图中,就像 Git 一样。它允许处理不同的分支,合并它们,解决冲突,查询历史等等。
例如,在导入数据库之后,为了进行初始提交,我们使用一个命令:
与 Git 一样,为了在新的分支上进行更改,我们使用 checkout 作为:
call dolt_commit('-m', 'Created initial schema')
除此之外,Dolt 还提供了一个内置备份和监控的云托管数据库服务器。该产品的价格根据实例的 CPU、RAM、网络速度和磁盘空间而有所不同。
call dolt_checkout('-b','modifications');
insert INTO employees (id, first_name, last_name) values (4,'Daylon', 'Wilkins');
call dolt_commit('-am', 'Modifications on a branch')
更多关于 Dolt:
莱克夫斯
LakeFS 是一个开源的数据湖的数据版本控制和管理平台。有了 lakeFS,就有可能在生产数据之上测试 ETL,不需要复制任何东西。此外,lakeFS 可以用于数据管理、ETL 测试、实验的可再现性,以及数据的 CI/CD,以防止未来的失败。LakeFS 完全兼容许多数据工程工具的生态系统,如 AWS、Azure、Spark、Databrick、MlFlow、Hadoop 等。
例如,使用 lakeFS,可以在带有默认分支的 S3 存储桶上创建一个存储库。然后,使用一个单独的分支,我们可以将文件导入到存储库中。如果文件已经在 S3 上,导入不会复制文件,而是复制这些文件位置的范围和元范围。类似地,我们可以将新的分支合并到主生产分支中,并使用其他 Git 特性,如分支、合并、区分等。
关于部署,lakeFS 是一个无状态数据版本化平台,具有无共享架构,可以使用 K8s 和 helm chart 部署在负载平衡器后面的多个实例上。或者,它可以用作托管云服务,用户将 lakeFS 作为服务使用,数据位于用户的存储桶之上。
关于 LakeFS 的更多信息:
lakeFS version control system | Source
三角洲湖
Delta lake 是一个开源存储层,设计用于处理数据湖。它允许在现有的数据湖(如亚马逊 S3、Azure 数据湖存储、谷歌云存储和 HDFS)上进行数据版本控制、ACID 事务和模式管理。Delta lake 通过在数据湖之上构建 Lakehouse 体系结构,为数据湖带来了可靠性。这使得构建强大的数据管道和进行更复杂的数据分析变得更加容易。
关于数据版本化,Delta lake 有一个叫做“时间旅行”的选项。它支持回滚、完整的历史审计跟踪和可重复的机器学习实验。通过时间旅行,可以查询增量表的旧快照,这有助于重新创建分析和报告,修复数据中的错误,并为快速变化的表的一组查询提供快照隔离。例如,要查询一个旧的快照,我们可以使用 SQL 语法:
其中时间戳表达式可以是:
SELECT * FROM table_name TIMESTAMP AS OF timestamp_expression
“2023-01-30”(日期字符串)
current _ timestamp()–间隔 12 小时
任何其他可以转换为时间戳的表达式
总之,Data lake 允许构建 Lakehouse 体系结构,这是一种结合了数据湖和数据仓库的最佳元素的体系结构,并且它具有数据版本控制的选项。
关于三角洲湖的更多信息:
迟钝的人
Pachyderm 是一个用于数据科学和机器学习的开源平台,使数据科学家和工程师能够轻松开发、版本化和部署他们的数据管道。它提供了一种可扩展的、安全的方式来管理、版本化和分析大型数据集,并建立在 Docker 和 Kubernetes 等技术之上。此外,该平台与代码和基础设施无关。这意味着通过 Pachyderm,我们可以使用任何语言、库,将其与标准数据处理和机器学习工具或主要的云提供商集成。
Pachyderm 在其数据驱动的管道中有一个内置的版本控制功能。该软件允许用户定义最小的数据单位,称为“数据”,然后用机器学习模型处理数据。这允许 Pachyderm 使用全局 ID 跟踪每个数据随时间的变化。这种版本控制和 ID 跟踪用于扩展数据处理,并仅在有新的或不同的数据要处理时触发数据管道,使其比其他只将数据集视为整体的管道工具更有效。
关于厚皮动物的更多信息:
Integration with some popular tools | Source
结论
在本文中,我们描述了一些数据版本控制工具以及如何使用它们进行数据版本控制。它们可用于对各种数据源进行数据版本控制。例如:
为了在实验跟踪环境中对数据集和模型进行版本化,我们可以使用 Neptune。
要用类似 Git 的体系结构对任何类型的数据文件进行版本控制,我们可以使用 DVC 或 Git LFS。
- 对于存储在表中的版本数据集, Dolt 可能会有用。
- 对于数据湖或数据湖屋,我们描述了湖和三角洲湖。****
- Pachyderm 是一个可以用来优化数据管道和管理数据版本控制的工具。
- 参考
- Pachyderm is a tool that can be used to optimize data pipelines and manage data version control.
References
模型注册的最佳数据机器人替代方案
原文:https://web.archive.org/web/https://neptune.ai/blog/datarobot-alternatives-for-model-registry
DataRobot 是一个企业人工智能平台,它为企业提供了构建、管理和部署大规模模型的工具,并实现了端到端 ML 生命周期的自动化。它包含不同类型的模型、数据、最新的开源算法,可以在内部使用,或者作为一种完全托管的人工智能服务,DataRobot 为您提供人工智能的力量,以推动更好的业务成果。DataRobot 中的一个重要组件是它的模型注册表。
DataRobot 模型注册中心是 DataRobot 平台上使用的各种模型的中央组织中心。它包含每个模型,并将它们注册为一个部署就绪的模型包。
DataRobot 模型注册表提供以下功能:
- 一个注册所有模型的中心,无论其来源或部署位置如何。
- 它以相同的方式处理每个包功能,而不管其模型的来源。
- 它为整个企业的机器学习模型提供了统一的部署体验。您还可以将 DataRobot 中的模型部署到外部源。
- DataRobot model registry 有一个定制模型工作室,在这里您可以创建和部署定制模型。
- 您还可以创建定制的模型推断,并添加外部模型包,以便在模型注册中心中使用。
- DataRobot 提供了一个排行榜,用于比较模型注册表中的所有模型。该排行榜还提供了模型训练过程中使用的功能和技术的说明,并允许了解更多关于它训练了多少数据的详细信息,以及它的整体准确性分数。
DataRobot 模型注册中心的主要目的是存储所有的模型元数据,这些元数据是在整个商业企业中再现和部署所需要的。反过来,这将允许数据科学团队在需要时轻松找到所有与模型相关的元数据。
DataRobot model registry | Source, image taken by author
然而,DataRobot 模型注册表可能不是您团队的最佳选择,原因如下:
- DataRobot 模型注册表是 DataRobot 平台的组件之一,因此要使用它,您的团队必须将整个机器学习基础架构迁移到 DataRobot 平台。
- DataRobot 与其他框架和库的 API 集成并不容易使用。
- DataRobot 仅存储部署就绪的模型,即不存储需要持续训练的实验模型。
- 谈到数据处理,DataRobot 只处理小数据,除非您使用的是企业版。如你所知,每一个模型都和它被训练的数据量一样好。
- 此外,不能在 DataRobot 中编辑数据。即没有数据清理或 ETL 功能。数据必须在系统外编辑,然后再次输入。
- 不能导出 DataRobot 中使用的基础代码。
- DataRobot 不太适合无监督学习和没有足够数据可用的场景。
- 在 DataRobot 上,可以同时运行多少个模型是有限制的。每次不超过两个。
因此,我们有必要为模型注册寻找一些替代工具。
1.海王星
Neptune 是 MLOps 的一个元数据存储库,为运行大量实验的研究和生产团队而构建。它提供了一个中央存储,用于记录、存储、显示、组织、比较和查询机器学习生命周期中生成的所有元数据。
- 它支持并存储许多与 ML 模型相关的元数据类型,您可以对模型构建过程中生成的大多数元数据进行版本化、显示和查询。
- Neptune model registry 帮助您存储和记录模型、数据集、环境配置版本、超参数和模型度量的元数据。
Neptune model registry | Source
特征
- 从 Neptune 仪表盘中,您可以:
- 基于度量和参数值的搜索,
- 查找带有用户定义标签的运行,
- 基于参数或标签值的组模型训练运行。
- Neptune versions,并将您的所有模型训练运行存储在其中央注册库。
- Neptune 版本和存储所有类型的模型元数据,如 pkl 文件、数据元数据、图像、数据、图表等。
- Neptune 允许您通过 UI 或客户端库记录模型信息。
- 结合其模型注册功能,Neptune 允许您跟踪模型元数据的变化。
- 你可以在模型训练跑步之间进行比较,并深入了解它们之间的差异。
- Neptune 已经集成了 ML 框架和库包括 PyTorch、TensorFlow、Keras、XGBoost 等。
- Neptune model registry 允许 ML 团队的协作,因为它允许团队从其中央存储中探索所有与模型相关的元数据。
定价
Neptune 为云和您的私有基础架构提供定价计划。有几个可用的计划:
- 个人:免费(超出免费配额的使用量)
- 学术界:免费
- 团队:付费
查看海王星的定价了解更多信息。
2.SageMaker 模型注册表
SageMaker 是一个完全托管的工具,可以用于 ML 开发的每个阶段,包括模型注册。它帮助用户在一个统一的可视化界面中构建、调试、部署以及充分监控 ML 模型所需的一切。
SageMaker 模型注册表提供以下内容:
- 一个可搜索的集中存储区,用于存储模型和与模型相关的元数据,以实现可再现性。
- 每次实验性训练运行的版本控制和跟踪。
- 将模型从模型注册中心部署到现有的 Sagemaker 端点。
Sagemaker Model Registry 允许您连接到 Amazon SageMaker Model Monitor,在部署后持续实时监控您的机器学习模型的质量。
Sagemaker model registry component | Source
特征
- Sagemaker 有一个系统,可以帮助为生产编制模型目录。根据模型类型和内容对它们进行分类和存储。
- 在 Sagemaker 模型注册表中,模型可以快速地转移到生产中。它通过 CI/CD 实现了自动化的模型部署。
- Sage maker 允许您从一种硬件配置切换到另一种配置,它能够提供和管理您的模型环境的硬件基础设施
- Jupyter 笔记本易于创建和共享。
- 它有超过 150 种预设模型可用于多种情况。
- 可以创建模型组来监视已经被训练来解决某些问题的模型。然后,这些模型可以被存储并制作成新的模型版本。
- SageMaker Studio 支持其他几个框架,如 Tensorflow、PyTorch、MXNet 等
定价
对于 Sagemaker,它是按使用付费的。有两种支付方式可供选择:
- 按需定价:按秒计费,没有最低费用或前期承诺。
- sage maker 节约计划:这提供了一个灵活的、基于使用量的定价模式,以换取对一致使用量的承诺。
AWS 定价计算器可用于管理您的账单。另外,查看定价页面了解详细信息。
3.MLflow 模型注册表
MLflow model registry 是一个自给自足的系统,包括一个 UI、一组 API 和一些概念,能够有效地管理 MLflow 模型的生命周期。包括阶段转换、模型版本控制和注释。MLflow model registry 存储模型工件、元数据、参数和度量。
MLflow model registry dashboard | Source
特征
- MLflow 模型注册表与 MLflow 跟踪组件协同工作。这允许您回溯到生成模型和数据工件的原始来源,包括其源代码版本,从而为所有模型和数据转换生成生命周期的完整谱系。
- MLflow Model Registry 包含 API 和智能 UI,可以轻松注册和共享新的模型版本。当然还要对现有模型进行生命周期管理。
- MLFlow 能够再现实验和报告/结果。
- 使用 MLFlow,您可以在数据湖中存储的数据存储到增量表或目录时立即对其进行版本控制。
- 每个型号版本都有一个分配的预设。例如,“生产”描述了模型的生命周期。
定价
它是免费的。
4.彗星
慧星是一个机器学习,基于云的实验管理平台。Comet model registry 提供了一个系统,用于通过 Python SDK 实验来记录、注册、版本化和部署机器学习模型,以及注册、版本化和部署它们。
Comet 简化了记录实验历史和模型版本的过程。
模型训练跑步通过以下方式在 Comet 中注册:
- Comet.ml 实验的资产选项卡用户界面
- 通过 Comet Python SDK 以编程方式
Card view of Comet model registry | Source
特征
- Comet 兼容大多数平台和机器学习库。
- Comet 通过将代码、超参数、指标和依赖项放在一个用户界面中,让您可以轻松地比较实验。
- 自动通知系统使用户能够持续监控模型的性能。从而提高项目的整体质量。
- 凭借其可视化和报告的内置特性,comet 允许个人开发人员和专业团队进行交流,并在实验发生时运行和跟踪实验。
定价
Comet 提供以下定价方案:
- 个人:免费(超出免费配额的使用量)
- 学术界:免费
- 团队:付费
你可以在这里阅读他们的详细定价。
五分钟
Verta 是一个 AI/ML 模型管理和操作工具,具有模型注册功能,您可以在中央空间管理和部署您的机器学习模型。
Verta 使您能够简化数据科学和 ML 工作流程。它还有助于更快地将模型部署到生产中,同时确保实时模型健康。
特征
- Verta model registry 为发布就绪模型提供了一个中心基础。
- Verta model registry 连接到实验组件,使得重用训练过的模型变得容易。
- Verta model registry 帮助您管理模型治理。
- Verta 在 Docker 和 Kubernetes 上运行良好。可以与 Tensorflow、PyTorch、Spark.ml 和 r 等 ML 工具集成。
- Verta 可以轻松地与 Jenkins、Chef 和 GitOps 等 CI/CD 管道集成。
- Verta 也因其类似 Git 的环境而闻名。让有经验的 g it 用户(和其他开发人员)非常方便和熟悉。
定价
Verta 提供以下定价方案:
- 开源:免费
- SaaS:付费
- 企业:付费
你可以在这里阅读他们的详细定价。
6.大太酷
Dataiku 为企业的 ML 模型的设计、部署和管理提供了一个中心解决方案。它为团队提供自助分析和协作,以提高工作效率。
当在 Dataiku DSS 上设计和训练模型时,它们被存储在 Lab 中,Lab 充当它的模型注册库。
Dataiku model registry 是 Dataiku 中模型的中央存储。它允许通过 MLflow 存储外部模型。Dataiku 模型注册表提供了一个中心点:
- 探索模型及其版本。
- 跟踪模型版本的状态
- 跟踪简单输入随时间的漂移。
- 存储模型参数和数据沿袭。
Dataiku model registry dashboard | Source
特征
- Dataiku 提供了一个仪表板,用于监控模型操作和培训。
- Dataiku 提供了模型和数据血统。
- Dataiku 为数据清理、分析和验证提供了一套交互式功能。
- 它为模型提供了从模型构建到部署的端到端管理。
- 数据 DSS 是数据不可知的。
- Dataiku 有一个健壮的部署 API,可以将模型交付给生产。
- 数据流非常容易可视化。数据模型可以用图片和表格的形式来表示,而不是到处都有不同的文件。
- 您可以自由选择您的数据库格式,可用选项包括 SQL、NoSQL 和 HADOOP。
- Dataiku 使用其 API 与 Tensorflow、Keras、XGboost 等框架和外部库(H2O、数据等)集成。
定价
Dataiku 提供在线或内部安装或在您的云堆栈上安装的服务。它提供 14 天的试用版,之后起价为每月 499 美元。点击阅读更多关于定价的信息。
模型注册的 DataRobot 替代方案的比较
结论
DataRobot model registry 是 DataRobot 平台中的一个很好的组件,它促进了团队内的可重复性和协作,但是如上所述,它可能并不总是最适合您的团队。
像 Neptune、Sagemaker Model registry、Dataiku、MLflow 这样的替代模型注册工具将允许 ML 团队执行更好的模型注册和治理。
还有像 Azure Model Registry 、 Tensorflow 、 Determined AI 这样的工具,他们的平台上都有模型注册表,你也可以去看看。
快乐实验!
小野寺次郎
机器学习工程师和研究员,对人工智能和人类福祉(医疗保健和教育)之间的交叉充满热情。在我的空闲时间,我喜欢尝试新的菜肴和看动漫。
阅读下一篇
Continuum Industries 案例研究:如何跟踪、监控和可视化 CI/CD 管道
7 分钟阅读| 2021 年 8 月 9 日更新
Continuum Industries 是一家基础设施行业的公司,希望自动化和优化线性基础设施资产的设计,如水管、架空传输线、海底电力线或电信电缆。
其核心产品 Optioneer 允许客户输入工程设计假设和地理空间数据,并且使用进化优化算法来寻找可能的解决方案,以在给定约束的情况下连接 A 点到 B 点。
首席科学家安德烈亚斯·马莱科斯(Andreas Malekos)致力于研究人工智能发动机,他解释道:
“建造像电力线这样的东西是一个巨大的项目,所以你必须在开始之前获得正确的设计。你看到的设计越合理,你就能做出更好的决定。Optioneer 可以在几分钟内为您提供设计资产,而成本只是传统设计方法的一小部分。”
但是,创建和操作 Optioneer 引擎比看起来更具挑战性:
- 目标函数不代表现实
- 有很多土木工程师事先不知道的假设
- 不同的客户给它提出完全不同的问题,算法需要足够健壮来处理这些问题
与其构建完美的解决方案,不如向他们展示一系列有趣的设计选项,以便他们做出明智的决策。
引擎团队利用来自机械工程、电子工程、计算物理、应用数学和软件工程的各种技能来实现这一目标。
问题
无论是否使用人工智能,构建一个成功的软件产品的一个副作用是,人们依赖它工作。当人们依赖您的优化引擎做出价值百万美元的基础设施设计决策时,您需要有一个强大的质量保证(QA)。
正如 Andreas 所指出的,他们必须能够说,他们返回给用户的解决方案是:
- 好,意思是这是一个土木工程师可以看到并同意的结果
- 更正,这意味着计算并返回给最终用户的所有不同工程数量都尽可能准确
除此之外,该团队还在不断改进优化引擎。但要做到这一点,您必须确保这些变化:
- 不要以这样或那样的方式破坏算法
- 实际上,它们不仅改善了一个基础设施问题的结果,还改善了所有问题的结果
基本上,您需要**建立适当的验证和测试,**但是团队试图解决的问题的性质带来了额外的挑战:
- 您无法自动判断算法输出是否正确。这不像在 ML 中,你已经标记了数据来计算你的评估集的准确度或召回率。
- 您需要一组示例问题,代表算法在生产中需要解决的那类问题的。此外,这些问题需要被版本化,以便尽可能容易地实现可重复性。
调试和可视化 TensorFlow/Keras 模型:实践指南
原文:https://web.archive.org/web/https://neptune.ai/blog/debug-and-visualize-tensorflow-keras-model
调试在机器学习开发周期中起着很大的作用。一般来说,调试是所有类型的软件开发中的一个关键阶段——通常也是痛苦和耗时的。
有一种方法可以减轻痛苦。您可以尽早开始实现调试策略,不断测试您的组件,这将有可能产生一个高生产率的环境。
模型创建始于数据探索。接下来,我们为我们的模型和基线算法选择特征。最后,我们使用各种算法和调整参数来提高基线性能…
…这就是调试发挥作用的地方,以确保我们的基线模型做它们应该做的事情。从技术上来说,基线模型满足充分的标准,使其适合生产发布。
这可能看起来有点让人不知所措,构建和维护调试框架和策略可能会很昂贵和困难。幸运的是,您可以使用一个平台来完成这项工作。跟踪元数据、记录不同的研究模型、比较性能以及改进模型的功能和特征。
在本文中,我们将讨论模型调试策略,并使用 Neptune 及其 API 进行实际实现。
模型调试基础
机器学习中模型性能差可能由多种因素造成。这使得调试非常耗时。如果模型没有预测能力或具有次优值,则它们的表现很差。因此,我们调试我们的模型来确定问题的根源。模型性能差的一些常见原因包括:
- 模型特征缺乏足够的预测能力;
- 超参数被设置为次优值;
- 训练数据集具有通过模型过滤的缺陷和异常;
- 特征工程代码有 bug。
要记住的一个关键思想是,ML 模型一直被部署在越来越大的任务和数据集上。规模越大,调试你的模型就越重要。要做到这一点,你需要一个计划和一系列的步骤。这是:
模型调试的一般步骤
以下是机器学习中最有影响力的人常用的调试模式。
1.检查模型是否正确预测标签
检查您的特征是否充分编码了预测信号。模型的准确性与单个特征对预测性的编码程度有很大关系。一种简单而有效的测量方法是使用相关矩阵来评估单个特征和标签之间的线性相关性。
另一方面,要素和标注之间的非线性相关性不会被相关矩阵检测到。相反,从数据集中选择一些模型可以轻松学习的示例。或者,使用容易学习的合成数据。
2.建立模型基线
对你的模型质量的一个快速测试是将它与一个基线进行比较。一个 模型基线 是一个简单的模型,它在一项任务中产生合理的结果,并不难建立。当创建一个新模型时,通过用你能想到的最简单的启发式模型预测标签来创建基线。如果你训练的模型超过了基线,你必须改进它。
*
*“Good” results can be misleading if we compare against a weak baseline | Image source: MLCMU *
基线模型的例子有:
- 使用仅在数据集的最具预测性特征上训练的线性模型版本;
- 只关注预测最常见标签的分类模型;
- 预测平均值的回归模型。
3.调整超参数值
通常,工程师首先调整的最有针对性的超参数是:
- 学习率 :学习率由 ML 库自动设定。例如,在 TensorFlow 中,大多数 TF 估计器都使用 AdagradOptimizer,它将学习速率设置为 0.05,然后在训练期间自适应地修改该速率。或者,如果您的模型不收敛,您可以手动设置这些值,并选择 0.0001 到 1.0 之间的值。
- 正则化惩罚 :如果你需要减少你的线性模型的大小,使用 L1 正则化。如果你想要更多的模型稳定性,使用 L2 正则化。增加模型的稳定性会使模型训练更具重现性。
- 批量 :一个小批量一般有 10 到 1000 个批量。SGD 的批量大小为一。最大批量由机器内存中可以容纳的数据量决定。批量限制由您的数据和算法决定。
- 网络层数深度 :一个神经网络的深度是指层数,而宽度是指每层的神经元数。随着相应问题的复杂性增加,深度和宽度也应该增加。常见的做法是将层的宽度设置为等于或小于前一层的宽度。稍后调整这些值有助于优化模型性能。
测试和调试您的 TensorFlow/Keras 模型
让我们解决事情的实际方面,并实际获得实施我们上面提到的要点的实践经验。我们将构建、训练和调试一个 TensorFlow 模型,执行简单的音频识别。我们将使用 Neptune,因为它是 Keras/TensorFlow 模型的完全可操作的扩展,我们将探索一些有趣的特性来管理和跟踪我们模型的开发。
从语音命令数据集开始
这个数据集包括超过 105,000 个 WAV 音频文件,内容是人们说的 30 个不同的单词。谷歌收集了这些信息,并通过许可在 CC 下提供。用谷歌的话说:
该数据集旨在帮助训练和评估关键词识别系统。它的主要目标是提供一种开发和测试小型模型的方法,这些模型可以检测何时从一组 10 个目标单词中说出一个单词,并尽可能减少由于背景噪声或无关语音造成的假阳性”。
链接到数据集的官方研究论文:语音命令:有限词汇语音识别的数据集。
我们将使用整个数据集的较小版本,并使用 TensorFlow.data API 下载它。
data_dir = pathlib.Path('Documents/SpeechRecognition/data/mini_speech_commands')
if not data_dir.exists():
tf.keras.utils.get_file(
'mini_speech_commands.zip',
origin="http://storage.googleapis.com/download.tensorflow.org/data/mini_speech_commands.zip",
extract=True,
cache_dir='.', cache_subdir='data')
开始你的海王星实验:
run = neptune.init(project='aymane.hachcham/Speech-Recognition-TF',
api_token='YOUR_API_TOKEN')
将所有相关元数据记录到您的 Neptune 仪表盘:
run['config/dataset/path'] = 'Documents/SpeechRecognition/data/mini_speech_commands'
run['config/dataset/size'] = 105000
run['config/dataset/total_examples'] = 8000
run['config/dataset/examples_per_label'] = 1000
run['config/dataset/list_commands'] = ['down', 'go', 'left', 'no', 'right', 'stop', 'up', 'yes']
您还可以将音频样本记录到您的 Neptune dashboard,以便将所有元数据放在一起。目前,Neptune 支持 MP3、MA4、OGA 和 WAVE 音频格式。
run['config/audio'] = neptune.types.File('/content/data/right_commad_Sample.wav')
在这里你可以检查数据集的一个音频样本:一个右命令样本。
现在我们需要将所有的音频文件提取到一个列表中,并对其进行洗牌。然后,我们将把数据分割和隔离成训练集、测试集和验证集。
train_samples = list_samples[:6400]
val_samples = list_samples[6400: 6400 + 800]
test_samples = list_samples[-800:]
print('Training set size', len(train_samples))
print('Validation set size', len(val_samples))
print('Test set size', len(test_samples))
调查数据
由于数据中的音频文件被格式化为二进制文件,您必须将其转换为数值张量。为此,我们将使用 TensorFlow Audio API,它包含许多方便的函数,如 decode_wav,可以根据采样率将 wav 文件解码为 Tensors。
采样率是指整个音频文件中每秒编码的样本数。每个样本代表特定时间音频信号的幅度。例如,16kHz 采样速率表示 16 位系统,其值范围为-32768 至 32767。
让我们解码音频文件,得到相应的标签和波形。
def decode_audio(audio_binary):
audio, _ = tf.audio.decode_wav(audio_binary)
return tf.squeeze(audio, axis=-1)
def get_label(file_path):
parts = tf.strings.split(file_path, os.path.sep)
return parts[-2]
def audio_waveform(file_path):
label = get_label(file_path)
audio_binary = tf.io.read_file(file_path)
waveform = decode_audio(audio_binary)
return waveform, label
一旦我们的函数设置好了,我们将使用它们来处理训练数据,以便获得所有样本的波形和相应的标签。
AUTOTUNE = tf.data.AUTOTUNE
files_ds = tf.data.Dataset.from_tensor_slices(train_samples)
waveform_data = files_ds.map(audio_waveform, num_parallel_calls=AUTOTUNE)
绘制 6 个音频命令样本的 waveform_data:
Waveforms and command labels from the training data
您会注意到,即使对于相同的命令,波形也可能大不相同。这与声音的音高、音调和其他相关特征有关,这些特征使每个声音都很特别,几乎不可复制。
检查声音频谱图
频谱图显示了每个波形的频率随时间的变化,它们可以表示为 2D 图像。这是通过使用短时傅立叶变换(STFT) 将音频转换到时间-频率域来完成的。
STFT 将信号划分为时间窗口,并在每个窗口上执行傅立叶变换,保留一些时间信息并返回可以在其上执行标准卷积的 2D 张量。
幸运的是,TF 为我们提供了一个完美处理这项工作的 stft 函数:tf.signal.stft
我们需要设置先验参数来使用该函数。首先,设置帧长度和帧步长参数,使生成的谱图“图像”接近正方形。此外,我们希望各个波形与频谱图具有相同的长度,这样当我们将波形转换为频谱图时,结果将有望具有相同的维度。
def get_spectrogram(waveform_sample):
zero_pad = tf.zeros([16000] - tf.shape(waveform_sample), dtype=tf.float32)
waveform = tf.cast(waveform_sample, tf.float32)
equal_length = tf.concat([waveform, zero_pad], 0)
spectrogram = tf.signal.stft(
equal_length, frame_length=255, frame_step=128)
spectrogram = tf.abs(spectrogram)
return spectrogram
并排绘制频谱图及其相应的波形:
for waveform, label in waveform_data.take(1):
label = label.numpy().decode('utf-8')
spectrogram = get_spectrogram(waveform)
fig, axes = plt.subplots(2, figsize=(12, 8))
timescale = np.arange(waveform.shape[0])
axes[0].plot(timescale, waveform.numpy())
axes[0].set_title('Waveform')
axes[0].set_xlim([0, 16000])
plot_spectrogram(spectrogram.numpy(), axes[1])
axes[1].set_title('Spectrogram')
plt.show()
Waveform and corresponding spectrogram side-by-side
我有一篇文章深入解释了 spectrograms 和 Mel spectrograms 背后的所有理论,以及如何应用它来训练一个用于 TTS 和 STT taks 的 对话式智能机器人:工具指南
基线分类器
在开始训练 CNN 网络之前,我们会尝试用简单的基线分类器来测试我们复杂模型的准确性和性能。这样,我们将确信我们的 CNN 确实抓住了它,并且完美地匹配了任务的复杂性。
我们应该记住基线的两个主要特征:
- 基线模型应该非常简单。简单模型不容易过度拟合。如果您的基线过拟合,这通常表明您在使用任何更复杂的分类器之前关注了您的数据。
- 基线模型是可以解释的。基线模型有助于您理解数据,为特征工程提供方向。
在我们的例子中,我们将使用 scikit learn 提供的 DummyClassifier 模块。这是相当简单的,并有所有的要求,以弥补一个完美的候选人。
train_audio = []
train_labels = []
for audio, label in train_ds:
train_audio.append(audio.numpy())
train_labels.append(label.numpy())
train_audio = np.array(train_audio)
train_labels = np.array(train_labels)
from sklearn.dummy import DummyClassifier
from sklearn.metrics import accuracy_score
dummy_clf = DummyClassifier(strategy="most_frequent")
dummy_clf.fit(train_audio, train_labels)
Then get predictions and assess the accuracy score of our dummy classifier:
dummy_pred = dummy_clf.predict(test_audio)
dummy_true = test_labels
accuracy_score(dummy_true, dummy_pred)
我们的虚拟分类器的准确度得分为 0.16 。这与神经网络所能达到的相比是非常低的。一旦我们训练了我们的模型,我们将认识到基线结果清楚地表明我们的模型表现得非常好,并且确实超过了简单的 ML 分类器的能力。
构建并训练您的模型
既然我们已经构建了基线模型,并且一旦我们的所有数据都准备好用于训练,我们就需要构建我们的架构。一个简单的 CNN 就可以了,因为该模型将在光谱图上进行训练。因此,模型将学习通过仅与声谱图相关来识别每个声音的特性。
我们将使用一批 64 个数据加载器。
batch_size = 64
train_samples = train_samples.batch(batch_size)
val_samples = val_samples.batch(batch_size)
建筑
该模型还有一些额外的处理层,如:
- 一个 调整大小层 对输入进行下采样,从而训练得更快。
- 一个 归一化层 ,用于在将每个输入图像馈送到模型之前对其应用均值和标准差归一化。
如果我们使用 Pytorch,我们通常会首先应用数据转换,通常包括调整大小、规范化、裁剪等。但是,在 TensorFlow 中,这可以通过专门设计的模块轻松实现。
normalization_layer = preprocessing.Normalization()
normalization_layer.adapt(spectrogram_ds.map(lambda x, _: x))
sound_model = models.Sequential([
layers.Input(shape=input_shape),
preprocessing.Resizing(32, 32),
norm_layer,
layers.Conv2D(32, 3, activation='relu'),
layers.Conv2D(64, 3, activation='relu'),
layers.MaxPooling2D(),
layers.Dropout(0.25),
layers.Flatten(),
layers.Dense(128, activation='relu'),
layers.Dropout(0.5),
layers.Dense(num_labels),
])
我们还可以在 Neptune 中记录架构,以保存它供以后运行。
from contextlib import redirect_stdout
with open(f'./{model_name}_arch.txt', 'w') as f:
with redirect_stdout(f):
model.summary()
run[f"io_files/artifacts/{model_name}_arch"].upload(f"./{model_name}_arch.txt")
建立架构后,我们来编译模型。我们最终将使用 Adam 优化器和稀疏分类交叉熵损失度量来严格评估模型随时间的准确性。
hparams = {
'batch_size': 64,
'image_size': 120,
'num_epochs': 10,
'learning_rate': 0.0001,
'beta_rate_optimizer': 0.5,
'loss_function': tf.keras.losses.SparseCategoricalCrossentropy,
'optimizer': tf.keras.optimizers.Adam
}
run["params"] = hparams
跟踪我们模型训练进度最好的方法就是 海王 TF/Keras 扩展 。它作为一个回调函数,同时实时记录我们三个集合的值:训练、测试和验证。
sound_model.compile(
optimizer=tf.keras.optimizers.Adam(),
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy'],
)
from neptune.new.integrations.tensorflow_keras import NeptuneCallback
neptune_callback = NeptuneCallback(run=run, base_namespace="Sound Recognition")
history = model.fit(
train_ds,
validation_data=val_ds,
epochs=hparams["num_epochs"],
callbacks=[neptune_callback],
)
下面是三组中每一组的损失和精确度的结果。
调试和断言我们的训练的效率的一种方法是多训练几次,并在损失和准确性方面比较结果。
调试模型
调整模型超参数(时期数和学习率)向我们展示了模型的进展,以及这些参数是否对性能有任何严重影响。
调整模型超参数(时期数和学习率)向我们展示了模型的进展,以及这些参数是否对性能有任何严重影响。
如你所见,差别很小。这意味着整个训练碰巧非常相似,模型参数的变化既不能被认为是模型改进的转折点,也不能被认为是模型性能的转折点。
我们还可以显示混淆矩阵,以检查模型在测试集的每个命令上的表现。它显示了模型在预测每个命令时的准确性,并显示了模型是否对每个命令之间的差异有大致的了解。
y_pred = np.argmax(model.predict(test_audio), axis=1)
y_true = test_labels
confusion_mtx = tf.math.confusion_matrix(y_true, y_pred)
plt.figure(figsize=(10, 8))
sns.heatmap(confusion_mtx, xticklabels=commands, yticklabels=commands,
annot=True, fmt='g')
plt.xlabel('Prediction')
plt.ylabel('Label')
plt.show()
Confusion matrix
你可以看到我们的模型做得很好。
模型细化
随着模型变得越来越复杂,对其进行迭代调试。需要进行误差分析来找出模型失效的地方。跟踪模型性能如何随着用于训练的数据量的增加而扩展。
在您成功地为您的问题建立了一个模型之后,您应该尝试从模型中获得最佳性能。始终遵循以下基本规则来跟踪大多数潜在错误:
- 避免任何不必要的偏见
- 记住总会有不可约的误差
- 永远不要混淆测试错误验证错误
要实现的有趣的调试策略
灵敏度分析
敏感性分析是一种统计技术,用于确定模型、参数或其他量对输入参数相对于其标称值的变化有多敏感。这种分析展示了模型如何对未知数据做出反应,以及它根据给定数据预测什么。这通常被开发人员称为“假设”分析。
请看这里的例子: TensorFlow 关于模型特异性和敏感性的教程
模型基准
基准模型实现起来很简单,不需要太多时间。使用任何标准算法找到合适的基准模型,然后简单地将结果与模型预测进行比较。如果标准算法和 ML 算法之间有许多相似之处,简单的回归可能已经揭示了算法的潜在问题。
在这里看一个例子:一种测试你的深度学习框架的方法
最后的想法
我们已经探索了调试机制和策略,这些机制和策略对于机器学习模型的实验非常有用,并且我们做了一个实际的例子来说明如何使用 Neptune 来分析和跟踪模型性能。
我给你留下一些额外的资源。不要忘记查看我的其他文章,如果有任何问题,请随时联系我。
别忘了在 Colab 笔记本上查看这篇文章的所有代码:简单的声音识别
资源:*
深度学习模型训练调试的 9 个步骤
原文:https://web.archive.org/web/https://neptune.ai/blog/debugging-deep-learning-model-training
第一个电脑 bug 实际上是一个 bug。1947 年,一只蛾子进入哈佛大学的一台计算机,导致计算中断。当工程师打开电脑机箱时,他们很快就发现了导致问题的错误。如今,一个 bug 爬进我们的计算机并扰乱计算流程是不太可能的。然而,原理是一样的。
软件 bug 是一个很小的、很难注意到的错误,它会潜入我们的软件项目并导致问题。不幸的是,与发现飞蛾不同,软件缺陷更加微妙,难以发现。在大多数情况下,软件开发人员通过在他们的代码中犯一些起初看起来无害的小错误来制造这些错误。这就是存在许多工具和方法来帮助程序员调试代码的原因。
在本文中,我将更深入地探讨调试深度学习模型的主题,并解释如何做到这一点。
Figure 1. The art of debugging | Source: Unsplash
什么是深度学习模型调试,为什么与软件调试不同?
在软件调试中,程序员遵循一组预定义的规则,这些规则允许他们找到问题的根源。在某种意义上,这类似于沿着汉瑟和葛丽特创造的白色鹅卵石小径。在软件调试中,艺术是在哪里准确地留下白色鹅卵石,以便可以容易地检测到错误。
然而,机器学习是不同的。我们不是简单地解决一个定义明确的任务,这个任务对于给定的输入有一个确定的输出。我们正在训练一个模型,该模型从给定的域中捕获数据结构,以便算法学习识别可用于预测未来示例行为的模式。该模型的实现可能没有任何软件缺陷,但是该模型可能有缺陷。例如,考虑一个使用不正确的预处理数据训练的模型。显然,这是一个严重的限制,模型需要重新训练。然而,从软件的角度来看,这个模型没有任何问题,它对于所提供的输入是正确的。
模型越强大,漏洞就越复杂。
以上对于深度学习来说尤其如此。人们可以认为,深度学习模型的主要优势是它们从数据中学习相关特征的能力。虽然这产生了强大的模型,但也是一个挑战。就像可解释性是深度学习的一个严重问题一样,调试可能特别具有挑战性。再次考虑预处理输入错误的例子。例如,我们通过使用有符号整数而不是无符号整数来转换输入图像的颜色。一个 CNN 模型将学习如何处理错误的输入,并且仍然可以获得很好的结果。但是当对新的、正确预处理的数据进行评估时,该算法将失败。
在本文中,我们专注于调试深度学习模型。可以说,神经网络产生了最先进的预测模型。同时,就设计、调试和维护而言,它们是最具挑战性的模型。我们将讨论这些挑战,并提出应对这些挑战的策略。
深度学习模型如何调试?
基于神经网络的模型的设计应该与其调试策略齐头并进。我们列出了在实施和评估深度学习模型时应该始终遵循的基本步骤。
1.调试实现
软件缺陷可能会被深度学习的力量隐藏起来。例如,我们在 Keras 中实现了以下卷积神经网络:
inp = Input(shape=(28, 28, 1))
x = Conv2D(32, kernel_size=(3, 3), activation="relu")(inp)
x = MaxPooling2D(pool_size=(2, 2))(x)
x = Conv2D(32, kernel_size=(3, 3), activation="relu")(x)
x = MaxPooling2D(pool_size=(2, 2))(x)
…
对于第二个卷积层,我们可能会复制我们用于第一个卷积层的代码,即 x = Conv2D(32,kernel_size=(3,3),activation="relu")(inp),并忘记更新 x 的输入。该模型仍将工作,只是比我们实际想要实现的模型更简单。
提示: 创建测试,断言神经网络架构看起来像它应该的样子,检查层数、可训练参数的总数、输出的值域等等。理想情况下,将网络架构可视化,如图 2 所示。
Figure 2. A neural network architecture | Source: Author
2.检查输入
简单的错误,比如由于错误的索引而为我们的模型提供了一个特征子集,可能很难被检测到。深度学习模型仍然可以工作,即使提供的功能更少。更普遍的是,如果我们在预处理输入数据时出现系统性错误,深度学习的力量可能会成为一种诅咒。该模型将使自己适应不正确的输入,然后一旦我们修复了预处理错误,它将无法正常工作。
提示: 实现断言输入特性的格式和值范围的测试。
3.仔细初始化网络参数
在开始训练之前,我们必须初始化模型的参数。最有可能的是,我们使用一个可用的平台 TensorFlow 或 PyTorch 来负责初始化。然而,由于参数是根据每个神经元的输入和输出的数量来选择的,因此在这个阶段仍然可能出现错误。以下是 Andrej Karpathy 关于初始化的建议。
寻找正确的随机性能损失。当你用小参数初始化时,确保你得到了你期望的损失。最好先单独检查数据丢失(所以把正则化强度设置为零)。例如,对于具有 Softmax 分类器的 CIFAR-10,我们预计初始损失为 2.302,因为我们预计每个类别的扩散概率为 0.1(因为有 10 个类别),Softmax 损失是正确类别的负对数概率,因此:-ln(0.1) = 2.302。
提示: 更一般地说,在训练产生预期结果之前,编写断言输入的测试。在上面的例子中,我们可以断言 k 个预测类的概率分布的熵接近于-k ln 1/k = k ln k
4.从简单开始,使用基线
请注意,可以使用神经网络实现几个基本模型。例如,我们可以将线性回归实现为浅网络,以均方误差作为损失函数。类似地,逻辑回归可以通过浅网络实现,该浅网络具有用于输出的 sigmoid 激活函数和作为损失函数的二进制交叉熵。图 3 显示了通过从图 2 中的网络中移除隐藏层的逻辑回归模型:
其中 w [1] 到 w [n] 是可学习的参数。
此外,我们可以使用具有线性激活功能的自动编码器来模拟 PCA。因此,将我们对基本算法的神经网络实现的结果与我们在 scikit-learn 等平台上公开实现的结果进行比较是一个好主意。这将允许我们在早期捕捉不同种类的错误,例如权重初始化错误、学习率问题、错误的输入预处理等。
Figure 3. Logistic regression can be seen as a basic neural network | Source: Author
提示: 编写测试,断言我们深度学习实现和一些现成算法的相同输入的结果是可比的。
5.检查中间输出
我们可以将深度学习模型视为(非线性)函数的串联。连续层计算越来越复杂的特征。因此,我们可以追踪这些新特征。这对于深度卷积神经网络模型是特别直观的,其中每一层计算的特征可以被可视化。
类似于标准软件调试,我们设置断点,允许我们跟踪分配给程序中变量的中间值,我们也可以跟踪深度学习模型的中间输出。
特别的,我们可以使用一个调试工具。
提示 : 编写测试来检查每一层之后的输出值。此外,使用显示模型不同层的可视化工具。
6.确保我们的模型设计合理
您应该特别注意:
- **特征归一化。**重要的是输入特征具有相同的量级,因此对于不同尺度的特征,使用适当的归一化技术非常重要。常见的选择是标准化和最小-最大标准化:
标准化
最小-最大归一化
在上面,x 是输入向量,x [i] 是单独的坐标。
- 防止渐变消失。对于某些损失函数,我们可能会遇到消失梯度的问题。每层的梯度乘以后续层的梯度。考虑 sigmoid 函数σ(z) = 1/(1+e ^(-z) )。对于大的或小的 z 值,梯度将接近于 0,因此当使用它作为激活函数时,我们应该小心。经验法则是仅对输出层使用 sigmoid,或者更一般的 softmax。
提示: 检查每层输出的测试,应该检查中间层接近 0 的输出。
**批量大小。**在训练神经网络时,标准做法是使用小批量方法。在这种情况下,我们使用数据的子样本来计算损失,并使用反向传播计算的梯度下降来更新网络参数。当然,小批量的确切大小取决于计算硬件约束和数据集大小。认为小批量会导致训练次数多,大批量会导致训练速度慢。
**批量归一化。**我们通过归一化每个输入特征来归一化每个层的输入。这里重要的是要记住,平均值和方差是为每个小批量计算的,但在推断过程中,它们是为整个训练数据集计算的。(我们可能想要评估单个示例的模型。)
提示: 编写测试来确保每一层的输入都被规范化。
- **在最优值附近振荡。**需要调整学习速率,以应对复杂函数的曲率变化。特别地,不同方向上的梯度可能具有很大不同的幅度,因此使用恒定的学习速率可能导致振荡。实践中一种流行的选择是 Adam 方法(自适应矩估计),其中在每次迭代之后通过使用过去梯度的指数递减平均值来调整学习速率。
Figure 4. Oscillation around the optimal value leads to slower convergens | Source: Deep Learning
7.防止过度拟合
另一个需要记住的要点是,模型应该能够推广到新数据。神经网络的能力可能很容易导致过度拟合,以至于我们在输入实例中学习噪声。这里我们列出了一些常用的正则化技术。
**节点权重正则化。**标准做法是使用权重正则化,防止某些权重变得过大,从而使输入过拟合。标准选择是 L1 和 L2 正则化:我们在损失函数中添加一项λ||W||p,其中 W 是模型的可学习权重,而> 0 是正则化的强度。
辍学。在训练期间,我们随机删除给定层中的一部分神经元。这可以防止神经元变得过度特定,并学习更可能是随机产物的非常特殊的模式。
**提前停止。**在设计模型时,我们在尚未用于训练的数据子集上评估其性能,即所谓的验证数据。一旦验证的性能在一定数量的时期内没有改善,我们就停止训练模型。
**数据扩充。**为了迫使模型只学习数据中的重要模式,我们可以通过扩充数据集来生成一些人工数据。对于计算机视觉应用,我们可以旋转或镜像输入图像,或者改变颜色,以使生成的新数据看起来仍然像自然图像,参见图 5 中的示例..请记住,数据扩充对于某些领域来说可能具有挑战性,我们在应用它时应该小心,以免在训练数据中产生偏差。
Figure 5. Changing the visual effect of the original image such that we create new images and ensure the model will generalize | Source: Unsplash (transformed by Luna)
8.记录和跟踪实验
神经网络使用不同种类的随机化来训练高质量的模型。根据不同的策略,内部层的权重由随机权重初始化,我们可以使用正则化的 dropout,或者在设计模型时使用交叉验证。
提示: 使用随机种子并存储随机选择。
以上将使神经训练过程可重复,并将简化缺陷的检测。特别是,某些问题可能是由底层硬件的差异引起的,这可以通过再现完整的训练流来检测。
9.要耐心
永远记住,深度学习模型训练是一个缓慢且往往痛苦的过程。有时,我们可能会获得并非真正预期的结果,但这并不一定意味着我们的模型有问题。例如,考虑一下这个 reddit 讨论已经获得了一些流行。安德烈·卡帕西报道:
"有一次,我在寒假期间不小心离开了模特培训,当我一月份回来时,这是最先进的技术
等待几个小时直到我们的模型性能开始改善可能看起来违反直觉,并且不经常发生,事实上早期停止是基于这样的前提,即这并不真正可行。但这不一定表明我们的模型有问题。在高层次上,深度学习模型搜索关于给定目标的最佳参数集。并且相对于该目标的优化不是明确定义的任务,而是基于反向传播概念的启发式方法,该方法保证为所讨论的损失函数找到局部最优。然而,一个具有数千个参数的非凸函数很可能会有许多局部极小值。
因此,存在搜索可能收敛到函数参数空间的穷举搜索并且看起来没有进展的情况。在最近的一篇论文中,研究人员设计了一组学习问题,在找到最佳解决方案之前,这些问题的学习肯定需要很长时间。事实上,为了找到最优解,对训练数据的过度拟合是必要的。当然,这是一个人工设置,真实生活中的数据不太可能表现出相同的行为。但是我们应该记住,检测复杂的模式可能需要比我们的直觉告诉我们的更长的时间,并花一些时间来检查我们的模型是否不是这样。
Figure 6. A sudden drop in validation loss | Source: Twitter
提示: 在计划模型开发工作时,要给模型留出足够的训练时间,以确保我们不会经历损失函数的突然下降。
结论
调试神经网络模型可能是一项具有挑战性的任务,可能需要对软件开发和机器学习技术的不同领域有深刻的理解和经验。因此,在设计神经网络解决方案之前,重要的是要有一个明确定义的策略来简化模型调试。制定如何处理潜在问题的计划不仅会增加模型的稳健性,还可能带来新的见解和更强大的模型。
资源
- 亚马逊 SageMaker 调试器——亚马逊 SageMaker 创建的模型调试器。
- 微软的可视化调试工具 TensorWatch
- tensor board–tensor flow 的可视化工具。
- 海王星进行实验跟踪
- deep kit——测试和调试 ML 模型的开源平台。
- TensorFlow 调试器–提供在运行时检查学习流程的功能。
- 调试机器学习模型—ICLR 2019 研讨会
深度卷积生成对抗网络的训练和调试
对抗网络(深度卷积生成对抗网络)最近已经成为深度学习实践者非常活跃的游乐场。对抗网络领域是由蒙特利尔大学的 Ian Goodfellow 和他的同事在他们的文章生成对抗网络中建立的。从那以后,原始模型的新变体不断被开发,研究也不断向前发展。
对抗网络的主要目标是估计对抗过程中的生成模型。这一过程包括以一种对另一种的方式同时训练两个模型:
- 生成型模型(通常表示为 G )被训练来捕捉数据分布并对数据模式进行归纳,以最终再现原始样本的完美副本;
- 鉴别器模型(表示为 D )试图识别来自生成模型的假样本。鉴别器估计数据是原始数据还是生成数据的概率。
培训过程针对两种模型的两个不同但互补的目标:
- 生成模型被训练成通过总是生成更好的假货来胜过鉴别器。
- 该鉴别器被训练来学习如何正确地将真实数据与假数据进行分类。
当生成器创建完美的赝品,并且鉴别器在猜测输出是真还是假时留有 50%的置信度时,达到总体平衡。
对抗网络的不同方法
自从 Ian Goodfellow 的论文为敌对网络的核心机制奠定了基础,其他几种实现生成模型的方法也被提出和测试。其中一些方法如下:
完全可见的信念网络
这些网络主要用于识别、聚类和生成图像、视频序列和动作捕捉。Geoff Hinton 在 2006 年推出了它们。
它们是一类显式密度模型。他们使用链式法则来分解向量的概率分布。其思想是将经典的向量分布分解成每个向量成员的乘积。
这个家族中最流行的模型是一个名为 PixelCNN 的自回归生成模型。
变分自动编码器
自动编码器将数据作为输入,并发现该数据的一些潜在状态表示。通常,输入向量被转换成编码向量,其中每个维度表示关于数据的一些学习属性。
变分自动编码器(VAE)提供了一种概率方法来描述潜在空间的具体观察。我们不是为数据的每个潜在状态属性建立一个专用的编码器,而是制定我们的编码器来描述所有潜在属性的概率分布。
下图显示了一个非常简单的示例,该示例说明了数据中潜在属性的单个离散值和概率分布之间的差异:
如您所见,最好用概率术语表示数据中的潜在属性,这样我们就可以评估整个范围的值。
亚历克·拉德福德使用一种可变自动编码器来生成虚构的名人面孔。
Variational Autoencoders to generate fake faces | Credit: Alec Radford
玻尔兹曼机器
玻尔兹曼机器是由对称连接的单元组成的网络,它们随机决定是否激活。他们有简单的学习算法,使他们能够在由二进制向量组成的数据集中发现有趣的特征。
它们也可以被看作是一个能量函数,调度特定状态的概率分布。
深度卷积 GANs
深度卷积对抗网络是一种特殊的 GANs 。生成器( G )和鉴别器( D )的网络架构中的主要层分别是卷积层和转置卷积层。
这些架构首次在论文中介绍,深度卷积生成对抗网络的无监督表示学习。作者拉德福德等人。艾尔。提出了一种特殊的实现,它需要一系列的步进卷积层、批量范数层和 LeakyReLU 激活。生成器主要由转置卷积层填充,相反,对于鉴别器,激活是简单的 ReLU 层。
鉴别器输入是一个 3x64x64 彩色图像,输出是一个标量概率,表示输入是来自真实数据分布还是完全由生成器编造的置信度。
另一方面,发生器的输入由从标准正态分布提取的潜在向量组成,相应的输出产生一个 3x64x64 图像。
让我们用一些数学符号来帮助澄清我们将在本文后面使用的术语。
鉴别器网络记为***【D(x)***,其输出 x 来自训练数据而非生成器的标量概率。
对于生成器, z 是从标准正态分布中采样的潜在空间向量。因此, G(z) 表示将潜在向量 z 映射到数据空间的函数。
如此, D(G(z)) 表示发生器 G 的输出为实图像的概率。与我们之前解释的涉及一个模型对另一个模型的竞争一致,***【D(x)试图最大化它正确分类真实和虚假的概率,这可以表示为【log(D(x)】和【G(z)***相反,试图最小化虚假输出被鉴别器发现的概率,因此
*官方文件中描述的整体 GAN 损失函数如下所示:
如前所述,当: P [g] =P 数据 以及鉴别器猜测输入是真还是假时,理论上的收敛导致了该函数的解。
现在您已经了解了一般概念,并且有了更好的基础,我们可以有目的地深入到更实际的问题中。
我们将建立一个基于名人头像训练的 DCGAN。我们将打破构建模型、初始化权重、训练和评估最终结果的步骤。接下来,开始你的海王星实验和连接你的 API 令牌到你的笔记本。
名人-人脸数据集
名人属性面孔是一个大规模的开源数据集,提供了各种各样的名人图像,用 40 种属性进行了注释。图像质量很好,数据集在实际图像上提出了各种各样的姿势变化和背景杂波,使其非常适合我们的任务。
下载链接:大规模名人面孔属性(CelebA)数据集
在笔记本根目录下创建一个目录,并将文件夹解压到其中。应该是这样的:
* CelebA Dataset after extracting the folder*
现在,我们需要开始预处理部分。转换我们的数据并初始化 Torch DataLoader 类,该类将在训练过程中负责数据批次的洗牌和加载。
import torchvision.datasets as datasets
def data_preprocessing(root_dir, batch_size=128, image-size=64, num_workers=2):
data = datasets.ImageFolder(root=root_dir,
transform=transforms.Compose([
transforms.Resize(image_size),
transforms.CenterCrop(image_size),
transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
]))
dataloader = torch.utils.data.DataLoader(dataset, batch_size, shuffle=True, num_workers)
return dataloader
将所有数据集细节记录到您的 Neptune 运行中,因此您可以跟踪您的数据集信息和相应的元数据。
按照这里的说明建立自己的 Neptune 账户来追踪这些跑步记录。
开始你的实验:
run = neptune.init(project='aymane.hachcham/DCGAN', api_token='ANONYMOUS')
run['config/dataset/path'] = 'Documents/DCGAN/dataset'
run['config/dataset/size'] = 202599
run['config/dataset/transforms'] = {
'train': transforms.Compose([
transforms.Resize(hparams['image_size']),
transforms.CenterCrop(hparams['image_size']),
transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
}
The dataset config in your Neptune dashboard
模型结构
一旦数据集准备好并被记录,我们就可以开始构建实际的模型了。正如我之前解释的那样,我们将尝试一步一步地解决这个问题。我们需要从权重初始化策略开始。
权重初始化是关于模型权重应该满足的特定标准。官方论文建议从均值=0、标准差=0.02 的正态分布中随机初始化权重。
我们将创建一个函数,将一个通用模型作为输入,并重新初始化 卷积 、 转置卷积 和 批量归一化 层,以完全满足这个标准。
注 :你可以跟着教程看完整的 colab 笔记本,这里- > Colab 笔记本
def weights_init(model):
model_classname = model.__class__.__name__
if classname.find('Conv') != -1:
nn.init.normal_(m.weight.data, 0.0, 0.02)
elif classname.find('BatchNorm') != -1:
nn.init.normal_(m.weight.data, 0.0, 0.02)
nn.init.constant_(m.bias.data, 0)
由于模型参数将被生成器或鉴别器取代,因此它们肯定会有 Conv 和 BatchNorm 层。因此,该函数为这些层中的每一层设置一个随机权重初始化,平均值=0.0,标准偏差=0.02。
发电机
生成器 G 的作用是将潜在向量 Z 映射到数据空间。在我们的例子中,这转化为最终创建与数据中的原始图像具有相同大小和尺寸的 RGB 图像。这是通过堆叠一系列卷积、转置卷积和批处理规范层来实现的,这些层协调工作以产生最终看起来像人脸的 3x64x64 输出。
值得注意的是,在转置卷积之后添加的批范数层在很大程度上有助于训练期间的梯度流,因此它们构成了整体训练性能的重要部分。
class Generator(nn.Module):
def __init__(self):
super(Generator, self).__init__()
self.main = nn.Sequential(
nn.ConvTranspose2d(hparams["size_latent_z_vector"],
hparams["size_feature_maps_generator"] * 8, 4, 1, 0, bias=False),
nn.BatchNorm2d(hparams["size_feature_maps_generator"] * 8),
nn.ReLU(True),
nn.ConvTranspose2d(hparams["size_feature_maps_generator"] * 8,
hparams["size_feature_maps_generator"] * 4, 4, 2, 1, bias=False),
nn.BatchNorm2d(hparams["size_feature_maps_generator"] * 4),
nn.ReLU(True),
nn.ConvTranspose2d( hparams["size_feature_maps_generator"] * 4,
hparams["size_feature_maps_generator"] * 2, 4, 2, 1, bias=False),
nn.BatchNorm2d(hparams["size_feature_maps_generator"] * 2),
nn.ReLU(True),
nn.ConvTranspose2d(hparams["size_feature_maps_generator"] * 2,
hparams["size_feature_maps_generator"], 4, 2, 1, bias=False),
nn.BatchNorm2d(hparams["size_feature_maps_generator"]),
nn.ReLU(True),
nn.ConvTranspose2d(hparams["size_feature_maps_generator"],
hparams["num_channels"], 4, 2, 1, bias=False),
nn.Tanh()
)
def forward(self, input):
return self.main(input)
生成器的特征映射会传播到所有层。在输入部分中设置潜在向量的大小和通道的数量,以影响整个架构。
让我们实例化生成器并应用权重初始化:
model_name = "Generator"
device = "cuda"
generator = Generator().to(device)
generator.apply(weights_init)
现在我们可以打印总体架构并将其保存到 Neptune artifacts 文件夹:
with open(f"./{model_name}_arch.txt", "w") as f:
f.write(str(generator))
run[f"io_files/artifacts/{model_name}_arch"].upload(f"./{model_name}_arch.txt")
鉴别器
鉴别器图像经过一系列 Conv2、BatchNorm 和 LeakyReLU 层处理,最终概率由 Sigmoid 评估。
官方论文声称,为了下采样,使用跨卷积比池化更好,因为它有助于网络学习自己的池化功能。此外,LeakyReLU 激活促进健康的梯度流。查看这篇文章,了解更多关于死亡 ReLU 问题的信息,以及泄漏的 ReLU 激活如何帮助解决这个问题。
class Discriminator(nn.Module):
def __init__(self):
super(Discriminator, self).__init__()
self.main = nn.Sequential(
nn.Conv2d(hparams["num_channels"],
hparams["size_feature_maps_discriminator"], 4, 2, 1, bias=False),
nn.LeakyReLU(0.2, inplace=True),
nn.Conv2d(hparams["size_feature_maps_discriminator"],
hparams["size_feature_maps_discriminator"] * 2, 4, 2, 1, bias=False),
nn.BatchNorm2d(hparams["size_feature_maps_discriminator"] * 2),
nn.LeakyReLU(0.2, inplace=True),
nn.Conv2d(hparams["size_feature_maps_discriminator"] * 2,
hparams["size_feature_maps_discriminator"] * 4, 4, 2, 1, bias=False),
nn.BatchNorm2d(hparams["size_feature_maps_discriminator"] * 4),
nn.LeakyReLU(0.2, inplace=True),
nn.Conv2d(hparams["size_feature_maps_discriminator"] * 4,
hparams["size_feature_maps_discriminator"] * 8, 4, 2, 1, bias=False),
nn.BatchNorm2d(hparams["size_feature_maps_discriminator"] * 8),
nn.LeakyReLU(0.2, inplace=True),
nn.Conv2d(hparams["size_feature_maps_discriminator"] * 8, 1, 4, 1, 0, bias=False),
nn.Sigmoid()
)
def forward(self, input):
return self.main(input)
接下来,让我们初始化鉴别器,应用权重初始化,并将架构记录到工件文件夹中:
disc_name = "Discriminator"
device = "cuda"
discriminator = Discriminator().to(device)
generator.apply(weights_init)
with open(f"./{disc_name}_arch.txt", "w") as f:
f.write(str(discriminator))
run[f"io_files/artifacts/{disc_name}_arch"].upload(f"./{disc_name}_arch.txt")
现在,我们已经将两种模型架构登录到我们的仪表板中:
模型训练和调试
在实际开始训练过程之前,我们将花一些时间来讨论我们将使用的损失函数和优化器。
正如该论文所推荐的,使用的优选损失函数是 Pytorch 中定义的二元交叉熵或损失。BCELoss 的方便之处在于它提供了目标函数中两个对数分量的计算,即 logD(x) 和 log(1-D(G(z))) 。
原纸中使用的另一个约定俗成的是真假标签。在计算 D 和 G 损失时使用。
最后,我们为 G 和 D 设置了两个不同的优化器。根据论文中的规范,两个优化器都是学习率为 0.0002 且β1 = 0.5 的 Adam,并且还生成从高斯分布导出的固定批次的潜在向量。
criterion = nn.BCELoss()
fixed_noise = torch.randn(64, nz, 1, 1, device=device)
real_label = 1.
fake_label = 0.
optimizerD = optim.Adam(netD.parameters(), lr=lr, betas=(beta1, 0.999))
optimizerG = optim.Adam(netG.parameters(), lr=lr, betas=(beta1, 0.999))
培训阶段
现在我们已经定义了所有的部分,我们可以开始训练了。为了进行训练,我们需要一丝不苟地遵循 Goodfellow 论文中提出的算法。具体来说,我们将为真实和虚假图像构建不同的小批量,同时调整生成器的目标函数以最大化 logD(G(z))。
训练循环由两个分段部分组成。第一部分处理鉴别器,第二部分处理发生器。
甄别训练
如官方文件所述,训练鉴别器的目标是“通过提升其随机梯度来更新鉴别器”。在实践中,我们想要实现的是最大化正确分类给定输入为真实或虚假的概率。因此,我们需要从数据集构建一批真实样本,向前传递通过 D ,计算损耗,然后向后传递计算梯度。然后,我们对这批假样本重复同样的模式。
发电机培训
我们想从生成器中得到什么非常清楚,我们的目标是训练它,让它学会生成更好的假货。在他的论文中,Goodfellow 坚持不提供足够的梯度,尤其是在学习过程的早期。为了实际完成以下内容,我们将对来自鉴别器训练部分的发生器输出进行分类,使用真实标签批次计算发生器损耗,计算反向传递中的梯度,最后用相应的优化器步骤更新***【G】***的参数。
创建数据加载器:
dataloader =数据预处理(数据目录)
建立训练循环:
- 鉴别器训练部分:
discriminator.zero_grad()
real_cpu = data[0].to(device)
b_size = real_cpu.size(0)
label = torch.full((b_size,), real_label, dtype=torch.float, device=device)
output = discriminator(real_cpu).view(-1)
errD_real = criterion(output, label)
errD_real.backward()
D_x = output.mean().item()
noise = torch.randn(b_size, hparams["size_latent_z_vector"], 1, 1, device=device)
fake = generator(noise)
label.fill_(fake_label)
output = discriminator(fake.detach()).view(-1)
errD_fake = criterion(output, label)
errD_fake.backward()
D_G_z1 = output.mean().item()
errD = errD_real + errD_fake
optimizerD.step()
generator.zero_grad()
label.fill_(real_label)
output = discriminator(fake).view(-1)
errG = criterion(output, label)
errG.backward()
D_G_z2 = output.mean().item()
optimizerG.step()
- 调用训练循环内的两部分:
img_list = []
G_losses = []
D_losses = []
iters = 0
for epoch in range(hparams["num_epochs"]):
for i, data in enumerate(dataloader, 0):
discriminator_training()
generator_training()
print('[%d/%d][%d/%d]tLoss_D: %.4ftLoss_G: %.4ftD(x): %.4ftD(G(z)): %.4f / %.4f'
% (epoch, hparams["num_epochs"], i, len(training_data),
errD.item(), errG.item(), D_x, D_G_z1, D_G_z2))
G_losses.append(errG.item())
D_losses.append(errD.item())
run["training/batch/Gloss"].log(errG.item())
run["training/batch/Dloss"].log(errD.item())
if (iters % 500 == 0) or ((epoch == hparams["num_epochs"]-1) and (i == len(training_data)-1)):
with torch.no_grad():
fake = generator(fixed_noise).detach().cpu()
img_list.append(vutils.make_grid(fake, padding=2, normalize=True))
iters += 1
检查 G 和 D 损耗:
我们可以清楚地观察到两个损失减少并最终稳定下来。我们可以通过改变纪元编号来进行多次训练,但变化仍然不大。当我们增加历元数时,我们可以注意到损耗略有改善,这可以从下面的比较中看出:
Left chart: D and G losses with 10 epochs, Right chart: D and G losses with 5 epochs | See in Neptune
我们还可以看到发生器和鉴频器损耗相互重叠:
D and G losses overlapping
生成器级数的最终结果
最后,我们可以看看生成器并排创建的一些真实和虚假的图像。
Fake images versus real images
总结想法
我们已经成功地从头开始构建了一个深度卷积 GAN,解释了所有不同的部件和组件,并在人脸数据集上进行训练。模型的质量总是可以通过增加训练数据和明智地调整超参数来提高。
生成对抗性神经网络是深度学习进化的下一步,尽管它们在几个应用领域都有很大的前景,但在硬件和框架上都存在重大挑战。然而,GANs 有着广阔的应用前景,如图像到图像的翻译、语义图像到照片的翻译、3D 对象生成、自动驾驶、人体姿态生成等等。
和往常一样,如果你想继续了解这个话题,这里有一些好的资源:
如有任何问题,请随时给我发电子邮件:hachcham.ayman@gmail.com。
不要犹豫去查一下谷歌 Colab 笔记本:带 DCGAN 的假脸*
深入研究机器学习(和深度学习)中的错误分析和模型调试
“赢得一场 Kaggle 比赛并不能让你为现实世界的数据科学做好准备!”这话我听得多了。当我还是个新手的时候,我想知道“什么?我在排行榜上有 99%的准确率。那简直太完美了!”但现在我明白了他们的意思。
获得良好的准确性就像在比赛前赢得掷硬币比赛一样。
很好,但是还有很多工作要做。
在竞赛和研究中,在你训练一个模型后,你做误差分析,找出模型的问题所在。然后,对您的模型进行一些更改,并在训练集上对其进行重新训练。但是,有时通过使用一个沉重而复杂的模型,你会得到一个很好的验证和测试分数。在比赛中,你会在这一点上停下来,因为你是在一个单一的指标上被评判的。在这个行业中,即使在你的测试数据集上获得了很高的分数,仍然有一些重要的步骤需要完成。
在这篇文章中,我们将深入探讨为什么你应该仔细检查你的模型,即使你得到了一个好的度量。
具体来说,我们将研究:
- 分析你的模型在你的测试数据上哪里出错了,以及如何基于这些见解对你的模型进行系统化的修改。
- 在三个层面上执行误差分析——预测、数据和特征。
- 如何在您的模型培训管道中查找并修复错误。
- 为生产中的模型寻找和解决 bug 的想法。
误差分析
对于您的 ML 项目,如果您获得了 85%的准确率,您应该问自己——为什么其他 15%的测试示例被错误分类?这通常是你错误分析的起点。
具有讽刺意味的是,如果您在测试集上获得了 100%的性能,您也应该有所怀疑。如果有数据泄露怎么办?
让我们来看看 3 个不同层次的误差分析——预测、数据和特征。
预言
一个简单的开始方法是将这 15%的误差分解成一些有洞察力的东西——一个混乱矩阵。它给你一种不准确的模式的感觉。大多数的类是否被错误地分类到一个特定的类中(在不平衡的情况下可能是大多数类)?
We can see that the misclassified Versicolor was predicted as Virginia. | Source
例如,如果您正在处理电子邮件数据集中的命名实体识别,您可能有五个类,其中两个是日期。说出邮件的发送日期和回复日期。
很有可能该模型在识别日期方面做得很好,但是很难将日期分成两类。在这种情况下,一个简单的解决方案是识别日期,并应用一些启发式方法来区分它们。
另一种全面评估你的模型的方法是**看看你的模型与你的基线相比表现如何。**你的基线是否比你的复杂模型更好地对一些类进行分类?整体改善边际吗?如果有,为什么?
另一种验证模型可信度的方法是亲自挑选预测。例如,分析一些低置信度的正确分类可以告诉您模型是否很难评估简单(从人类的角度来看)的示例。分类错误的例子容易预测吗?这些都是特征工程方面出了问题的迹象。
Original image
ML Operations 最近从软件开发中借鉴了一些想法来衡量一个模型的健壮性。在软件开发中,每一个新代码在发布前都必须通过测试。您也可以为 ML 模型创建一套测试。
例如,可以通过在几个明显的精选示例上测试模型来确保最低预期性能。如果模型在这些例子中的任何一个都失败了,那么它就不适合上线。
类似地,人们可以改变这些例子中的一些细节并看到效果。“德怀特是个好人”和“T2 是个好人”的情感得分应该差不多。在这种情况下,名称被更改。
Examples of adversarial attacks in NLP | Source
数据
我无法计算一个模型因为数据质量差而失败的次数。当您花费数周时间实施一些复杂的架构,然后发现数据有错误时,这是非常令人沮丧的。
在实施基线之前,始终确保数据是您期望的样子。因为后来,你不想知道你的糟糕指标是因为你的模型还是你的数据。
现在,我说的*数据不好是什么意思?*在我回答这个问题之前,你必须记住一条黄金法则——了解你的数据:
- 是如何产生的?
- 什么时候产生的?
- 谁生成的?
- 它是如何储存的?
- 所有的都储存起来了吗?
- 你应该知道一切。
现在,我们准备讨论高质量数据。
考虑从发票图像中识别命名实体的 NLP 任务。为此,您需要文本形式的图像内容。该文本是从第三方 OCR(光学字符识别)软件获得的。
如果你使用过像 tesseract 这样的开源软件,输出的文本可能会有很多拼写错误。这大大增加了你的词汇量。清理这些乱七八糟的东西变得很乏味。结果,你的 NER 任务变得不必要的困难。这里的数据质量很差。
考虑另一个例子,工厂机器上的传感器捕获关于机器的数据——温度、声级等。
OCR output can be erroneous. The word good is misread as goal. | Source
作为一名数据科学家,你的任务是开发一个模型来检测机器中的异常行为。原来传感器已经损坏好几个星期了,而且没有更换。因此,您丢失了大量数据。你的数据(有一个时间维度)有一个缺口。
数据的另一个潜在问题可能是注释的准确性。同样,您应该知道数据是如何被注释的。公开还是由专门的团队?注释者有足够的专业知识来标记数据吗?
一个小而重要的错误可能是训练和验证数据的不适当分割。不保持两个部分的分布,特别是在不平衡的数据会导致结果不准确。
该示例显示了对具有一维输入(X 轴)和一维连续预测变量(Y 轴)的数据拟合曲线。训练样本覆盖 X 中的某个范围,这不同于测试示例覆盖的 X 中的范围。因为训练数据不代表真实曲线,所以拟合曲线是不准确的。| 来源
一种常见的做法是对数据集应用扩充。如果您扩充了您的数据,您是否应用了有效的转换?例如,在汽车和自行车之间的图像分类中,垂直反转图像以创建合成示例几乎没有意义。模型不太可能看到颠倒的汽车或自行车。
特征
在你训练好你的模型之后,你如何检查你的特征是否良好?您 99%的验证准确性可能是由不良功能造成的,这些功能是利用数据泄漏设计的。
在这种情况下,模型将高度依赖于此功能。这可以用 SHAP 或莱姆框架(模型可解释性)来验证。另一个常见的漏洞是在整个数据集上安装一个缩放器或矢量器,然后进行分割。这应该避免,因为您在培训中间接使用了验证数据。
该图显示了像 LIME 这样的解释者如何为预测的每个特征分配贡献分数。| 来源
编者按
DALEX 是一个结合了很多模型解释和预测解释技术的可解释框架。你可以在这里阅读关于 Dalex。
不同的模型有不同的数据条件。基于距离的模型更适合缩放输入。确保你的特征服从这样的假设。此外,功能必须符合常识规则。比如特征之一是人类年龄,就不需要 200 年那么荒谬的数值。确保在过多修改数据之前编写这样的测试。
分析神经网络中的特征要困难得多,因为它们实际上无法解释。一个有用的小技巧是检查每一层的参数值的分布。训练较差的网络会有几个参数值或梯度接近于零的图层,这些图层永远不会流向网络中的某个区域。
调试模型训练管道
我们在三个核心组件中寻找错误,但还有更多空间。
深度学习系统中的模型训练管道更加复杂 s,主要是因为深度学习提供的灵活性。难的是神经网络无声无息地失效。通常,您能够成功运行训练代码,但是您不会得到想要的结果。有很多方法可以找出网络的问题。
调试深度学习模型
例如,损失曲线在诊断深层网络时非常方便。您可以通过绘制训练和验证损失曲线来检查您的模型是否过拟合。也可以检查一下自己的学习率是过高还是过低。如果损失曲线过早在一个高值处变平,则学习率可能较低。如果损失曲线遵循锯齿形模式,则学习率太高。
当训练 LSTM/RNN 时,损失曲线中的尖峰指向爆炸梯度。在这种情况下,剪切渐变会有所帮助。
现代深度学习模型中注意力是必须的。它显著提高了模型性能。然而,它也是一个很好的解释工具。考虑一个机器翻译任务。你需要建立一个编码器-解码器模型,将英语翻译成波兰语。注意力权重允许你直观地检查哪个英语单词对翻译的波兰语单词最重要。
训练深度学习模型的一些准则:
- 从一个简单的网络开始——没有批量规范,没有辍学,没有正规化或任何花哨的技巧。可能只是一个 CNN/RNN 和一个分类层。
- 溢出单批数据。
- 手动检查中间输出和最终输出的形状。即使你没有发现任何代码错误。神经网络无声无息地失败了。
- 尝试尽可能多的使用 DL 框架 APIs】避免自己写函数。例如,使用 PyTorch 的数据加载器或图像转换器,而不是自己编写。
- 调整模型时,不要一次更改多个超参数的值。一次调整一个超参数。
有关系的
你可能想看看这个关于神经网络故障诊断的伟大资源。
评估生产中的模型
到目前为止,我们已经讨论了模型训练中的错误分析。然而,在生产环境中有一些事情需要注意。大多数时候,你没有标签来检查你的预测是否正确。您必须依靠试探法来查看模型性能是否下降。
ML 模型是根据具有某种分布的数据来训练的。如果生产环境中的数据具有不同的分布,那么模型性能将是次优的。这个问题很常见,被称为模型漂移。
我们如何检测到这一点?由于我们在生产中没有标签,我们依靠一些替代措施。例如,如果特征的分布不同于训练集特征,则模型漂移是可能的。
在生产中评估模型是一个巨大的话题,我们有另外一篇文章专门讨论这个问题: 处理概念漂移的最佳实践 。
最后的想法
机器学习中的错误分析不仅仅是为了提高你的目标指标的性能,也是为了确保在静态训练和验证数据集上表现良好的模型在生产中也一样好。
它包括理解你的训练过程中的限制——数据、特征或模型,并试图使这些方面尽可能健壮。不幸的是,没有可以应用于任何 ML 问题的详细框架。计算机视觉问题可能需要不同于 NLP 问题的错误分析。但这正是这个过程的创意所在!
希望你学到了一些东西。欢迎在海王星博客上查看更多令人惊叹的人工智能/人工智能文章。
德鲁维尔·卡拉尼
i3systems India 的数据科学家
一位热爱数学和编程的数据科学家。他以前的经验使他能够处理大规模的自然语言处理问题,如聊天机器人和文档理解。他认为,教育大众了解技术及其影响与开发新技术同样重要。
阅读下一篇
ML 实验跟踪:它是什么,为什么重要,以及如何实施
10 分钟阅读|作者 Jakub Czakon |年 7 月 14 日更新
我来分享一个听了太多次的故事。
“…我们和我的团队正在开发一个 ML 模型,我们进行了大量的实验,并获得了有希望的结果…
…不幸的是,我们无法确切地说出哪种性能最好,因为我们忘记了保存一些模型参数和数据集版本…
…几周后,我们甚至不确定我们实际尝试了什么,我们需要重新运行几乎所有的东西"
不幸的 ML 研究员。
事实是,当你开发 ML 模型时,你会进行大量的实验。
这些实验可能:
- 使用不同的模型和模型超参数
- 使用不同的培训或评估数据,
- 运行不同的代码(包括您想要快速测试的这个小变化)
- 在不同的环境中运行相同的代码(不知道安装的是 PyTorch 还是 Tensorflow 版本)
因此,它们可以产生完全不同的评估指标。
跟踪所有这些信息会很快变得非常困难。特别是如果你想组织和比较这些实验,并且确信你知道哪个设置产生了最好的结果。
这就是 ML 实验跟踪的用武之地。
使用 TensorFlow Extended (TFX)和 Kubeflow 深入研究生产中的 ML 模型
如果整个行业的 Jupyter 笔记本电脑中每浪费一个机器学习模型,我就会成为百万富翁。—我
构建模型是一回事,将模型投入生产又是另一回事。机器学习最难的部分之一是有效地将模型投入生产。
这里强调的是有效地,因为虽然有很多方法可以将模型投入生产,但是很少有工具可以有效地部署、监控、跟踪和自动化这个过程。
在本教程中,我将向您介绍 **TensorFlow Extended,俗称 TFX。**你将使用 TFX、谷歌人工智能平台管道和 Kubeflow,将一个示例机器学习项目投入生产。
如果您是第一次学习这些工具,请不要担心,我将尽力正确地解释它们,同时也实际地实现它们。
要完成本教程或继续学习,你需要一个 GCP 账户。如果你还没有,请到这里注册,你会得到 300 美元的注册积分,可以用来进行实验。除此之外,您还需要:
- 对机器学习的基本理解
- 对张量流的基本理解
- 对云平台有一点熟悉
- 显然,你也需要 Python
TFX 和库伯弗洛简介
TFX 是一个基于 Tensorflow 的生产规模的机器学习平台。它由谷歌所有并积极维护,在谷歌内部使用。
TFX 提供了一系列框架、库和组件,用于定义、启动和监控生产中的机器学习模型。
TFX 提供的组件让您可以从一开始就构建专为扩展而设计的高效 ML 管道。这些组件包括:
- 建模,
- 培养
- 上菜(推断),
- 以及管理不同目标的部署,如 web、移动或物联网设备。
在下图中,您可以看到可用 TFX 库和可用管道组件之间的关系,您可以使用它们来实现这一点。
您会注意到,TFX 库和组件涵盖了一个典型的端到端机器学习管道,从数据摄取开始,到模型服务结束。
Python 中提供了用于实现上述不同任务的 TFX 库,这些库可以单独安装。但是建议只安装 TFX,它带有所有的组件。
随着本教程的进行,你将会使用不同的 TFX 组件,在向你展示如何使用它之前,我将首先解释它的功能。
幕后的 TFX 和指挥者
默认情况下,TFX 会为您的 ML 管道创建一个有向无环图(DAG)。它使用 Apache-Beam 来管理和实现管道,这可以在分布式处理后端上轻松执行,如 Apache Spark 、 Google Cloud Dataflow、 Apache Flink 等等。
值得一提的是,Beam 附带了一个直接通道,因此它可以用于测试或小型部署等场景。
虽然运行 Apache Beam 的 TFX 很酷,但是很难配置、监控和维护定义的管道和工作流。这就产生了我们称之为管弦乐队的工具。
像 Kubeflow 或 Apache Airflow 这样的编排器使得配置、操作、监控和维护 ML 管道变得很容易。它们大多带有你容易理解的图形用户界面。
以下是显示已定义任务的示例气流 GUI:
这里有一个给 Kubeflow:
在本教程中,您将使用 Kubeflow 作为 ML 管道的编排器,所以让我们简单地谈谈 Kubeflow。
Kubeflow 是一款开源kubernetes-专门为开发、编排、部署和运行可扩展 ML 工作负载而设计的原生平台。
它可以帮助您轻松管理端到端的 ML 管道流程编排,在内部或云等众多环境中运行工作流,并为工作流的可视化提供支持。
现在我们已经有了基本的介绍,让我们进入本教程的实践方面。在下一部分中,您将在 GCP 上设置您的项目。
建立一个新的谷歌云项目
如果您已经创建了一个 Google Cloud 帐户,那么您已经拥有了免费的 GC 积分。接下来,您将为本教程创建一个新项目。
如果你已经用完了你的免费积分,那么你的 GC 账户将会收费,所以记得在本教程结束时清理项目。
要设置新项目,请按照以下步骤操作:
为您的项目命名。我会把我的叫做 tfx-project。
点击创建新项目
创建完成后,再次单击项目下拉菜单,并选择您刚刚创建的新项目。
如果操作正确,您应该会看到您的项目仪表板。
配置 AI 平台管道并设置 Kubeflow
现在您已经创建了项目,您将设置 Kubeflow。按照以下步骤实现这一点:
点击汉堡菜单,显示 GCP 上可用的服务,滚动到你有 AI 平台的地方,选择管道。
在 pipelines 页面中,单击新实例按钮。这将打开 Kubeflow 管道页面。您可以在这里配置 Kubeflow 引擎。
您可以为您的群集选择一个区域,或者保留默认值。
确保选中允许访问框,因为这是您的集群访问其他云 API 所必需的。
点击创建集群按钮,等待几分钟直到集群创建完毕。
您可以选择一个名称空间,或者保留默认值。此外,如果您将为您的工件使用一个托管存储,那么您可以添加您的存储细节,或者留空。
最后点击部署,等待管道部署完成。
设置云人工智能平台笔记本
接下来,您将在 AI 平台中设置一个笔记本。这让我们可以在熟悉的 Jupyter 笔记本环境中进行实验。要实例化这个新笔记本,请执行以下步骤:
从 GC 汉堡菜单中选择 AI 平台选项,点击笔记本选项。
接下来,选择启用笔记本 API ,然后点击新建实例,在 AI 平台上创建一个新的笔记本实例。
根据您想要做的事情和您的预算,您可以选择一个自定义的启动库来添加到您的笔记本实例。对于本文,我将使用没有安装 GPU 的 Tensorflow 2.1 版本。
在弹出菜单中,点击底部的自定义。这将打开一个配置页面,如果向下滚动,您将看到一个减少计算实例的 CPU 和 RAM 数量的选项。为了降低成本,您将使用更小的产品。
如果你有足够的预算,并且需要非常快或大的东西,你可以跳过上面的步骤。
- 最后,滚动到最后,点击创建创建笔记本。
在云端体验笔记本电脑
现在您已经设置了笔记本,您将打开它。按照以下步骤实现这一点:
- 在 AI 平台仪表板中,再次单击管道。这一次您将看到刚刚创建的 Kubeflow 管道,在它旁边有一个 OPEN PIPELINES DASHBOARD 命令。点击它。
这将在 Kubeflow 中打开您的管道,从这里您可以执行许多特定于 Kubeflow 的功能。
接下来点击打开 TF 2.1 笔记本。这将打开笔记本页面,您可以在其中选择一个笔记本实例。单击您之前创建的笔记本实例,如下所示。
最后,点击 Create 来启动笔记本实例。这将打开一个熟悉的 Jupyter 笔记本,您将在其中进行实验。
在打开的 Jupyter 笔记本中,导入的文件夹中提供了一个模板文件,帮助您执行一些重要的配置和设置,以及一个用于处理 TFX 组件的模板。
稍后我们将利用这种配置,但是现在让我们开始构建我们的项目。
在笔记本中,为您的项目创建一个新文件夹( advert-pred )。在那个文件夹中,创建一个新的 Jupyter 笔记本(广告-实验)并打开它。
在这个 Jupyter 笔记本中,您将单独并交互地浏览每个 TFX 组件。这将帮助你理解每个组件在做什么,然后在最后,你将把你的实验变成一个完整的管道并部署它。
设置
在笔记本的第一个单元中,你将安装 TFX、库比弗洛(kfp)和一个名为 skaffold 的软件包:
# Install tfx and kfp Python packages.
import sys
!{sys.executable} -m pip install --user --upgrade -q tfx==0.22.0
!{sys.executable} -m pip install --user --upgrade -q kfp==1.0.0
# Download skaffold and set it
!curl ///skaffold//latest/ /home//.local//Import packages
Skaffold 是一个命令行工具,方便 Kubernetes 应用程序的持续开发。它帮助我们轻松管理和处理构建、推送和部署应用程序的工作流。以后你就会明白斯卡福德的用途了。
运行第一个单元后,您会得到一些警告——现在忽略它们。其中一个通知您您的安装不在您的 env 路径中。通过将它们添加到 PATH 中,您可以在下一个单元格中解决这个问题。
# Set `PATH` to ``
PATH=%env
%env /home//.local/
接下来,设置一些重要的环境变量,Kubeflow 稍后将使用这些变量来编排管道。将下面的代码复制到新的单元格中:
# Read GCP project id from env.
shell_output=!gcloud config list --format 'value(core.project)' 2>/dev/null
GOOGLE_CLOUD_PROJECT=shell_output[0]
%env GOOGLE_CLOUD_PROJECT={GOOGLE_CLOUD_PROJECT}
print("GCP project ID:" + GOOGLE_CLOUD_PROJECT)
第一个变量是您的 GCP 项目 ID 。这可以从你的环境中访问,因为你在人工智能平台上。接下来是 Kubeflow 管道集群端点。
在部署管道时,端点 URL 用于访问 KFP 集群。要获得您的 KFP 端点,请从 Kubeflow“入门”页面复制 URL。
将复制的 URL 分配给变量端点:
ENDPOINT='https://2adfdb83b477n893-dot-us-central2.pipelines.googleusercontent.com'
复制端点 URL 时,确保删除 URL 的最后一个路径,并在. com 结尾停止复制。
接下来,您将创建一个 Docker 名称,Skaffold 将使用它来捆绑您的管道。
CUSTOM_TFX_IMAGE='gcr.io/' + GOOGLE_CLOUD_PROJECT + '/advert-pred-pipeline'
最后,您将设置基本路径,并将当前工作目录设置为项目文件夹。
#set base
BASE_PATH
%cd
您完成了设置。
接下来,您将开始对每个 TFX 组件进行交互式探索。
交互式运行 TFX 组件
TFX 附带了一个内置的 orchestrator,允许您在 Jupyter 笔记本中交互式地运行每个组件。
这有助于您轻松探索每个组件,并可视化输出。在探索结束时,您可以将代码作为管道导出。
现在,让我们来看看实际情况。在新的代码单元格中,导入以下包:
import os
import pprint
import absl
import tensorflow as tf
import tensorflow_model_analysis as tfma
tf.get_logger().propagate = False
pp = pprint.PrettyPrinter()
import tfx
from tfx.components import CsvExampleGen
from tfx.components import Evaluator
from tfx.components import ExampleValidator
from tfx.components import Pusher
from tfx.components import ResolverNode
from tfx.components import SchemaGen
from tfx.components import StatisticsGen
from tfx.components import Trainer
from tfx.components import Transform
from tfx.components.base import executor_spec
from tfx.components.trainer.executor import GenericExecutor
from tfx.dsl.experimental import latest_blessed_model_resolver
from tfx.orchestration import metadata
from tfx.orchestration import pipeline
from tfx.orchestration.experimental.interactive.interactive_context import InteractiveContext
from tfx.proto import pusher_pb2
from tfx.proto import trainer_pb2
from tfx.types import Channel
from tfx.types.standard_artifacts import Model
from tfx.types.standard_artifacts import ModelBlessing
from tfx.utils.dsl_utils import external_input
%load_ext tfx.orchestration.experimental.interactive.notebook_extensions.skip
在导入的包中,您会注意到您从 tfx 组件包中导入了不同的模块。这些组件将在 ML 流程的不同阶段按顺序用于定义管道。
最后一行代码(% load_ext )加载一个 tfx notebook 扩展,该扩展可用于标记从 notebook 自动生成管道时应该跳过的代码单元。
是啊!您可以自动将笔记本导出为管道,在 Apache Beam 或 Airflow 上运行。
上传您的数据
在你的广告预测目录中,创建一个名为 data 的新文件夹。您将在此上传数据,供实验阶段使用。
在您继续之前,请从这里下载广告数据。
要将数据上传到您的笔记本实例,请打开您创建的数据文件夹,单击上传图标并选择您刚刚下载的数据文件。
上传完毕,让我们先来看一下最上面的几排。
data_root = 'data'
data_filepath = os.path.join(data_root, "advertising.csv")
!head {data_filepath}
//输出
Sample data output
数据集来自于本次挑战上的。任务是预测客户是否会点击广告。所以这是一个二元分类任务。
**
这是一个关于构建 ML 管道的教程,因此,我不会涉及广泛的特征工程或分析。
让我们从 TFX 组件开始。
在您继续进行之前,首先您将创建一个叫做 InteractiveContext 的东西。InteractiveContext 将允许您在笔记本中以交互方式运行 TFX 组件,以便您可以可视化其输出。这与生产环境不同,在生产环境中,您将使用 orchestrator 来运行您的组件。
在新单元格中,创建并运行 InteractiveContext,如下所示:
context = InteractiveContext()
范例生成
您将使用的第一个组件是 ExampleGen。ExampleGen 通常位于 ML 管道的开头,因为它用于接收数据,分成训练集和评估集,将数据转换为高效的 tf。示例 格式,并且还将数据复制到一个托管目录中,以便于管道中的其他组件访问。
在下面的代码单元格中,您将把数据源传递给 ExampleGen 输入参数,并使用上下文运行它:
example_gen = CsvExampleGen(input=external_input(_data_root))
context.run(example_gen)
上面,您可以查看 ExampleGen 输出的一个交互式小部件。这些输出被称为工件,ExampleGen 通常产生两个工件——训练示例和评估示例。
默认情况下,ExampleGen 将数据分成 2/3 的定型集,1/3 用于评估集。
您还可以查看存储工件和 URI 的位置:
artifact = example_gen.outputs['examples'].get()[0]
print(artifact.split_names, artifact.uri)
//输出
既然 ExampleGen 已经接收完数据,下一步就是数据分析。
StatisticsGen
StatisticsGen 组件用于计算数据集的统计数据。这些统计数据提供了数据的快速概览,包括形状、存在的要素以及值分布等详细信息。
为了计算数据的统计信息,您将把 ExampleGen 的输出作为输入传入。
statistics_gen = StatisticsGen(
examples=example_gen.outputs['examples'])
context.run(statistics_gen)
这些统计数据可以使用上下文的 show 方法可视化,如下所示:
context.show(statistics_gen.outputs['statistics'])
下面您将看到为数字特征生成的统计数据:
Statistics for numerical features
如果您向下滚动,在 statistics 小部件中,您还会找到分类变量的描述。
Statistics for categorical features
使用 StatisticGen,您可以快速了解您的数据概况。您可以检查缺失、零的存在以及分布情况。
这些统计数据将被下游组件使用,如 SchemaGen 和 ExampleValidator ,用于在生产中接收新数据时检测异常、偏差和漂移。
SchemaGen
SchemaGen 组件将从统计数据中为您的数据生成一个模式。模式只是数据的一个定义。它从数据特征中定义类型、期望的属性、界限等等。
在下面的代码单元格中,您将把 StatisticsGen 输出传递给 SchemaGen 输入,然后可视化输出。
schema_gen = SchemaGen(
statistics=statistics_gen.outputs['statistics'],
infer_feature_shape=False)
context.run(schema_gen)
context.show(schema_gen.outputs['schema'])
数据集中的每个要素都被表示,以及预期的类型、存在、化合价和域。
示例验证器
ML 管道中的下一个组件是 ExampleValidator。该组件根据定义的模式验证您的数据并检测异常。
这可用于在生产中验证进入管道的任何新数据。在新数据输入到您的模型之前,它对于检测新数据中的漂移、变化和偏差非常有用。
在下面的代码单元格中,我们将 StatisticsGen 和 SchemaGen 输出传递给 ExampleValidator:
example_validator = ExampleValidator(
statistics=statistics_gen.outputs['statistics'],
schema=schema_gen.outputs['schema'])
context.run(example_validator)
context.show(example_validator.outputs['anomalies'])
我们的数据目前没有异常。我们可以进入下一个部分。
变换
管道中的下一个组件是转换组件。该组件对训练和服务数据执行特征工程。
要对接收到的数据执行转换,需要从 ExampleGen 传入数据,从 SchemaGen 传入模式,最后传入包含转换代码的 Python 模块。
在您的项目目录(advert-pred)中,创建一个名为 model 的新文件夹。在这个文件夹中,您将定义您的转换代码以及模型代码。
在模型文件夹中,创建三个脚本— constants.py、advert-transform.py 和 init.py.
要在 Jupyter Lab 中创建一个 Python 脚本,打开相应的文件夹,点击 + 图标,创建一个文本文件,然后将扩展名改为 .py.
在 constants.py 中,您将定义一些变量,如分类特征、数字特征以及需要编码的特征的名称。在我们的例子中,您将使用如下所示的一些选定功能:
DENSE_FLOAT_FEATURE_KEYS = ['DailyTimeSpentOnSite', 'Age', 'AreaIncome', 'DailyInternetUsage' ]
VOCAB_FEATURE_KEYS = ['City', 'Male', 'Country' ]
VOCAB_SIZE = 1000
OOV_SIZE = 10
LABEL_KEY = 'ClickedOnAd'
def transformed_name(key):
return key + '_xf'
DENSE_FLOAT_FEATURE_KEYS 代表所有数字特征,而 VOCAB_FEATURE_KEYS 特征包含所有你想要编码的字符串特征。
此外,您还添加了一个小的助手函数,它将把 _xf 附加到每个特性名称上。这在变换模块中用于区分变换后的要素和原始要素。
在 advert-transform.py 中,您将导入您的联系人,然后定义转换步骤。这是所有处理、清理、填充缺失值的代码所在的位置。
import tensorflow as tf
import tensorflow_transform as tft
from model import constants
_DENSE_FLOAT_FEATURE_KEYS = constants.DENSE_FLOAT_FEATURE_KEYS
_LABEL_KEY = constants.LABEL_KEY
_VOCAB_FEATURE_KEYS = constants.VOCAB_FEATURE_KEYS
_VOCAB_SIZE = constants.VOCAB_SIZE
_OOV_SIZE = constants.OOV_SIZE
_transformed_name = constants.transformed_name
def preprocessing_fn(inputs):
"""tf.transform's callback function for preprocessing inputs.
Args:
inputs: map from feature keys to raw not-yet-transformed features.
Returns:
Map from string feature key to transformed feature operations.
"""
outputs = {}
for key in _DENSE_FLOAT_FEATURE_KEYS:
outputs[_transformed_name(key)] = tft.scale_to_z_score(
inputs[key])
for key in _VOCAB_FEATURE_KEYS:
outputs[_transformed_name(key)] = tft.compute_and_apply_vocabulary(
inputs[key],
top_k=_VOCAB_SIZE,
num_oov_buckets=_OOV_SIZE)
outputs[_transformed_name(_LABEL_KEY)] = inputs[_LABEL_KEY]
return outputs
在 advert-constants.py 脚本的顶部,您初始化了在 constants.py. 中定义的常数。接下来,您定义了预处理 _fn 函数。该函数由转换组件调用,名字(预处理 _fn ) 要保留。
在预处理 _fn 函数中,您将根据每个特征的类型对其进行处理,对其进行重命名,然后将其追加到输出字典中。变换组件期望预处理 _fn 返回一个变换特征的字典。
另外,注意我们的预处理代码是用纯 Tensorflow 编写的。建议这样做,以便您的操作能够以最佳方式分布并在集群中运行。如果您想使用纯 Python 代码,尽管不推荐,您可以使用“@ TF _ function”包装器将它们转换为 Tensorflow 的函数。
现在回到您的笔记本,在新的单元格中添加以下代码:
advert_transform = 'model/advert-transform.py'
transform = Transform(
examples=example_gen.outputs['examples'],
schema=schema_gen.outputs['schema'],
module_file=advert_transform)
context.run(transform)
首先,定义转换代码的路径,然后传递示例和模式。当您运行这个程序时,您应该会看到一个非常长的输出,显示了一些转换后的特性,最后,您可以看到如下所示的工件小部件:
转换组件将生成两个工件:一个 transform_graph 和 transformed_examples 。 transform_graph 将所有预处理步骤定义为一个有向无环图(DAG ),它可以用于任何摄取的新数据,而 transformed_examples 包含实际的预处理训练和评估数据。
您可以通过调用如下所示的转换输出来轻松查看这一点:
transform.outputs
//输出
Transform component output
现在您已经获取、分析和转换了您的数据,您将定义下一个组件,称为训练器。
教练
训练器组件用于训练 Tensorflow/Keras 中定义的模型。培训师将接受模式、转换后的数据和转换图、转换参数以及您的模型定义代码。
在您的 model 文件夹中,创建一个名为 **advert-trainer.py、**的新 Python 脚本,并添加以下代码。
上面的代码很长,所以我们将逐一介绍:
import os
import absl
import datetime
import tensorflow as tf
import tensorflow_transform as tft
from tfx.components.trainer.executor import TrainerFnArgs
from model import constants
_DENSE_FLOAT_FEATURE_KEYS = constants.DENSE_FLOAT_FEATURE_KEYS
_VOCAB_FEATURE_KEYS = constants.VOCAB_FEATURE_KEYS
_VOCAB_SIZE = constants.VOCAB_SIZE
_OOV_SIZE = constants.OOV_SIZE
_LABEL_KEY = constants.LABEL_KEY
_transformed_name = constants.transformed_name
def _transformed_names(keys):
return [_transformed_name(key) for key in keys]
def _gzip_reader_fn(filenames):
"""Small utility returning a record reader that can read gzip'ed files."""
return tf.data.TFRecordDataset(
filenames,
compression_type='GZIP')
def _get_serve_tf_examples_fn(model, tf_transform_output):
"""Returns a function that parses a serialized tf.Example and applies TFT."""
model.tft_layer = tf_transform_output.transform_features_layer()
@tf.function
def serve_tf_examples_fn(serialized_tf_examples):
"""Returns the output to be used in the serving signature."""
feature_spec = tf_transform_output.raw_feature_spec()
feature_spec.pop(_LABEL_KEY)
parsed_features = tf.io.parse_example(serialized_tf_examples, feature_spec)
transformed_features = model.tft_layer(parsed_features)
return model(transformed_features)
return serve_tf_examples_fn
def _input_fn(file_pattern, tf_transform_output,
batch_size=100):
"""Generates features and label for tuning/training.
Args:
file_pattern: List of paths or patterns of input tfrecord files.
tf_transform_output: A TFTransformOutput.
batch_size: representing the number of consecutive elements of returned
dataset to combine in a single batch
Returns:
A dataset that contains (features, indices) tuple where features is a
dictionary of Tensors, and indices is a single Tensor of label indices.
"""
transformed_feature_spec = (
tf_transform_output.transformed_feature_spec().copy())
dataset = tf.data.experimental.make_batched_features_dataset(
file_pattern=file_pattern,
batch_size=batch_size,
features=transformed_feature_spec,
reader=_gzip_reader_fn,
label_key=_transformed_name(_LABEL_KEY))
return dataset
def _build_keras_model(hidden_units):
"""Creates a DNN Keras model for classifying taxi data.
"""
real_valued_columns = [
tf.feature_column.numeric_column(key, shape=())
for key in _transformed_names(_DENSE_FLOAT_FEATURE_KEYS)
]
categorical_columns = [
tf.feature_column.categorical_column_with_identity(
key, num_buckets=_VOCAB_SIZE + _OOV_SIZE, default_value=0)
for key in _transformed_names(_VOCAB_FEATURE_KEYS)
]
indicator_column = [
tf.feature_column.indicator_column(categorical_column)
for categorical_column in categorical_columns
]
model = _wide_and_deep_classifier(
wide_columns=indicator_column,
deep_columns=real_valued_columns,
dnn_hidden_units=hidden_units or [100, 70, 60, 50])
return model
def _wide_and_deep_classifier(wide_columns, deep_columns, dnn_hidden_units):
"""returns a simple keras wide and deep model.
"""
input_layers = {
colname: tf.keras.layers.Input(name=colname, shape=(), dtype=tf.float32)
for colname in _transformed_names(_DENSE_FLOAT_FEATURE_KEYS)
}
input_layers.update({
colname: tf.keras.layers.Input(name=colname, shape=(), dtype='int32')
for colname in _transformed_names(_VOCAB_FEATURE_KEYS)
})
deep = tf.keras.layers.DenseFeatures(deep_columns)(input_layers)
for numnodes in dnn_hidden_units:
deep = tf.keras.layers.Dense(numnodes)(deep)
wide = tf.keras.layers.DenseFeatures(wide_columns)(input_layers)
output = tf.keras.layers.Dense(
1, activation='sigmoid')(
tf.keras.layers.concatenate([deep, wide]))
model = tf.keras.Model(input_layers, output)
model.compile(
loss='binary_crossentropy',
optimizer=tf.keras.optimizers.Adam(lr=0.01),
metrics=[tf.keras.metrics.BinaryAccuracy()])
model.summary(print_fn=absl.logging.info)
return model
def run_fn(fn_args: TrainerFnArgs):
"""Train the model based on given args.
Args:
fn_args: Holds args used to train the model as name/value pairs.
"""
first_dnn_layer_size = 150
num_dnn_layers = 4
dnn_decay_factor = 0.7
tf_transform_output = tft.TFTransformOutput(fn_args.transform_output)
train_dataset = _input_fn(fn_args.train_files, tf_transform_output, 40)
eval_dataset = _input_fn(fn_args.eval_files, tf_transform_output, 40)
model = _build_keras_model(
hidden_units=[
max(2, int(first_dnn_layer_size * dnn_decay_factor**i))
for i in range(num_dnn_layers)
])
log_dir = os.path.join(os.path.dirname(fn_args.serving_model_dir), 'logs')
tensorboard_callback = tf.keras.callbacks.TensorBoard(
log_dir=log_dir, update_freq='batch')
model.fit(
train_dataset,
steps_per_epoch=fn_args.train_steps,
validation_data=eval_dataset,
validation_steps=fn_args.eval_steps,
callbacks=[tensorboard_callback])
signatures = {
'serving_default':
_get_serve_tf_examples_fn(model,
tf_transform_output).get_concrete_function(
tf.TensorSpec(
shape=[None],
dtype=tf.string,
name='examples')),
}
model.save(fn_args.serving_model_dir, save_format='tf', signatures=signatures)
在导入部分,我们从常量模块导入一些您将使用的常量。
接下来,定义三个实用函数。第一个 _transformed_names 只是为每个特性返回一个修改后的名称。 _gzip_reader_fn 用于读取 TFRecordDataset 格式的文件。这就是我们的数据由 ExampleGen 表示的格式。最后是**_ get _ serve _ TF _ examples _ fn**,它解析每个 tf。示例并应用转换函数。
接下来,在 _input_fn 函数中,您只需生成一个 tf。来自变换要素的数据集文件。这是用于训练我们的模型的有效数据格式。
接下来的两个函数 _build_keras_model 和**_ wide _ and _ deep _ classifier**使用函数式 API 构建 keras 模型。这个函数式 API 在这里很有用,因为我们正在定义一个可以编排的静态图,因此,在编译模型之前,必须正确定义每个特性。
接下来,也是最重要的,您将定义 run_fn 。这个函数由训练器组件调用,因此名称不应该更改。在此函数中,您将从转换后的输出中初始化训练和评估数据集,初始化模型,为模型输出和张量板定义记录目录,最后拟合模型。
接下来,您定义服务签名,它被下一个组件推送器用于服务您的模型。
最后,您使用定义的签名将模型保存到服务目录中。
当您完成教练脚本的定义后,返回到您的笔记本并添加教练组件,如下所示:
培训师接受培训师模块、来自转换输出的转换示例、转换图、模式以及用于培训和评估步骤的培训师参数。
advert_trainer = 'model/advert-trainer.py'
trainer = Trainer(
module_file=advert_trainer,
custom_executor_spec=executor_spec.ExecutorClassSpec(GenericExecutor),
examples=transform.outputs['transformed_examples'],
transform_graph=transform.outputs['transform_graph'],
schema=schema_gen.outputs['schema'],
train_args=trainer_pb2.TrainArgs(num_steps=1000),
eval_args=trainer_pb2.EvalArgs(num_steps=500))
context.run(trainer)
现在您已经完成了培训,您将添加下一个组件——评估员。
求值程序
评估器组件计算评估集中的模型性能度量。它还可以用于验证任何新训练的模型。
当您在生产中改进和测试新型号时,这很有用。要设置评估器,您需要定义一个配置。
该配置只是指示评估者报告什么指标,在评估新模型时使用什么阈值,等等。更多关于这个的内容请看这里。
将以下配置代码添加到您的笔记本中:
接下来,您将把此配置以及示例和训练模型输出传递给评估者,如下所示:
eval_config = tfma.EvalConfig(
model_specs=[tfma.ModelSpec(label_key='ClickedOnAd')],
metrics_specs=[
tfma.MetricsSpec(
metrics=[
tfma.MetricConfig(class_name='ExampleCount'),
tfma.MetricConfig(class_name='BinaryAccuracy',
threshold=tfma.MetricThreshold(
value_threshold=tfma.GenericValueThreshold(
lower_bound={'value': 0.5}),
change_threshold=tfma.GenericChangeThreshold(
direction=tfma.MetricDirection.HIGHER_IS_BETTER,
absolute={'value': -1e-10})))
]
)
])
model_resolver = ResolverNode(
instance_name='latest_blessed_model_resolver',
resolver_class=latest_blessed_model_resolver.LatestBlessedModelResolver,
model=Channel(type=Model),
model_blessing=Channel(type=ModelBlessing))
context.run(model_resolver)
要可视化评估器的输出,请使用如下所示的 show 方法:
evaluator = Evaluator(
examples=example_gen.outputs['examples'],
model=trainer.outputs['model'],
baseline_model=model_resolver.outputs['model'],
eval_config=eval_config)
context.run(evaluator)
上面,您可以看到评估者报告的指标。如果你训练一个新的模型,性能将与基线模型进行比较,在我们的例子中,基线模型不存在,因为这是我们的第一个模型。
context.show(evaluator.outputs['evaluation'])
此外,评价者可以告诉我们一个模特是被祝福的还是没有被祝福的。一款加持的车型已经顺利通过所有评测标准,比现在的车型更好。然后这可以由推动器组件推动和服务,否则它抛出一个错误。这意味着您可以轻松地自动化模型部署。
要检查我们的当前模型是否得到了评估者的认可,请获取评估者的输出,如下所示:
//输出
blessing_uri = evaluator.outputs.blessing.get()[0].uri
!ls -l {blessing_uri}
我们的模型被自动地祝福,因为它是我们管道中的第一个模型。如果您训练另一个模型,并重新运行评估器管道,那么它将与当前模型进行比较,并变得有福气或没有福气。
既然您的模型已经被训练和认可,您可以使用 Pusher 组件轻松地将它导出到服务模型目录中。
推动器
在管道中总是排在最后的 Pusher 组件用于将一个受祝福的模型导出到服务目录。
要添加这个组件,您需要传入训练器输出、评估器输出以及服务目录。如下所示:
首先,您可以指定服务模型目录,您的训练模型将被推送到该目录。这可以是云存储或本地文件系统。
serving_model_dir = 'serving_model/advert-pred'
pusher = Pusher(
model=trainer.outputs['model'],
model_blessing=evaluator.outputs['blessing'],
push_destination=pusher_pb2.PushDestination(
filesystem=pusher_pb2.PushDestination.Filesystem(
base_directory=serving_model_dir)))
context.run(pusher)
就这样!您已经成功实现了所有的 TFX 组件,从获取数据到生成统计数据到生成模式,再到转换、模型训练、评估以及最终的模型保存。您可以轻松地导出笔记本,以便在 Apache Beam、Kubeflow 或 Apache Airflow 等流程编排中运行。
在下一节中,我将向您展示如何使用 Kubeflow 来编排您的管道。
设置您的 Kubeflow 管道
要使用 Kubeflow 运行或编排您的管道,您需要编写一些配置代码。这有助于设置 Kubeflow 以及定义要添加的 TFX 管道组件。按照以下步骤实现这一点:
首先,在项目目录中创建一个名为 pipeline.py. 的新 Python 脚本
- 在您的 pipeline.py 文件中,您将像我们在交互探索阶段所做的那样添加所有组件。
该文件定义了 TFX 管道和管道中的各种组件。
如果您注意到,上面的代码类似于您在交互式探索阶段编写的代码,这里您只需删除 InteractiveContext,并将每个组件添加到组件列表中。
from ml_metadata.proto import metadata_store_pb2
from tfx.components import CsvExampleGen
from tfx.components import Evaluator
from tfx.components import ExampleValidator
from tfx.components import Pusher
from tfx.components import ResolverNode
from tfx.components import SchemaGen
from tfx.components import StatisticsGen
from tfx.components import Trainer
from tfx.components import Transform
from tfx.components.base import executor_spec
from tfx.components.trainer import executor as trainer_executor
from tfx.dsl.experimental import latest_blessed_model_resolver
from tfx.extensions.google_cloud_ai_platform.pusher import executor as ai_platform_pusher_executor
from tfx.extensions.google_cloud_ai_platform.trainer import executor as ai_platform_trainer_executor
from tfx.extensions.google_cloud_big_query.example_gen import component as big_query_example_gen_component
from tfx.orchestration import pipeline
from tfx.proto import pusher_pb2
from tfx.proto import trainer_pb2
from tfx.types import Channel
from tfx.types.standard_artifacts import Model
from tfx.types.standard_artifacts import ModelBlessing
from tfx.utils.dsl_utils import external_input
import tensorflow_model_analysis as tfma
def create_pipeline(pipeline_name,
pipeline_root,
data_path,
preprocessing_fn,
run_fn,
train_args,
eval_args,
eval_accuracy_threshold,
serving_model_dir,
metadata_connection_config=None,
beam_pipeline_args=None,
ai_platform_training_args=None,
ai_platform_serving_args=None):
components = []
example_gen = CsvExampleGen(input=external_input(data_path))
components.append(example_gen)
statistics_gen = StatisticsGen(examples=example_gen.outputs['examples'])
components.append(statistics_gen)
schema_gen = SchemaGen(
statistics=statistics_gen.outputs['statistics'],
infer_feature_shape=True)
components.append(schema_gen)
example_validator = ExampleValidator(
statistics=statistics_gen.outputs['statistics'],
schema=schema_gen.outputs['schema'])
components.append(example_validator)
transform = Transform(
examples=example_gen.outputs['examples'],
schema=schema_gen.outputs['schema'],
preprocessing_fn=preprocessing_fn)
components.append(transform)
trainer_args = {
'run_fn': run_fn,
'transformed_examples': transform.outputs['transformed_examples'],
'schema': schema_gen.outputs['schema'],
'transform_graph': transform.outputs['transform_graph'],
'train_args': train_args,
'eval_args': eval_args,
'custom_executor_spec':
executor_spec.ExecutorClassSpec(trainer_executor.GenericExecutor),
}
if ai_platform_training_args is not None:
trainer_args.update({
'custom_executor_spec':
executor_spec.ExecutorClassSpec(
ai_platform_trainer_executor.GenericExecutor
),
'custom_config': {
ai_platform_trainer_executor.TRAINING_ARGS_KEY:
ai_platform_training_args,
}
})
trainer = Trainer(**trainer_args)
components.append(trainer)
model_resolver = ResolverNode(
instance_name='latest_blessed_model_resolver',
resolver_class=latest_blessed_model_resolver.LatestBlessedModelResolver,
model=Channel(type=Model),
model_blessing=Channel(type=ModelBlessing))
components.append(model_resolver)
eval_config = tfma.EvalConfig(
model_specs=[tfma.ModelSpec(label_key='ClickedOnAd')],
metrics_specs=[
tfma.MetricsSpec(
metrics=[
tfma.MetricConfig(class_name='ExampleCount'),
tfma.MetricConfig(class_name='BinaryAccuracy',
threshold=tfma.MetricThreshold(
value_threshold=tfma.GenericValueThreshold(
lower_bound={'value': 0.5}),
change_threshold=tfma.GenericChangeThreshold(
direction=tfma.MetricDirection.HIGHER_IS_BETTER,
absolute={'value': -1e-10})))
]
)
])
evaluator = Evaluator(
examples=example_gen.outputs['examples'],
model=trainer.outputs['model'],
baseline_model=model_resolver.outputs['model'],
eval_config=eval_config)
components.append(evaluator)
pusher_args = {
'model':
trainer.outputs['model'],
'model_blessing':
evaluator.outputs['blessing'],
'push_destination':
pusher_pb2.PushDestination(
filesystem=pusher_pb2.PushDestination.Filesystem(
base_directory=serving_model_dir)),
}
if ai_platform_serving_args is not None:
pusher_args.update({
'custom_executor_spec':
executor_spec.ExecutorClassSpec(ai_platform_pusher_executor.Executor
),
'custom_config': {
ai_platform_pusher_executor.SERVING_ARGS_KEY:
ai_platform_serving_args
},
})
pusher = Pusher(**pusher_args)
components.append(pusher)
return pipeline.Pipeline(
pipeline_name=pipeline_name,
pipeline_root=pipeline_root,
components=components,
metadata_connection_config=metadata_connection_config,
beam_pipeline_args=beam_pipeline_args,
)
为了创建管道,您从 tfx.orchestrator 导入管道,并传递所需的参数,这些参数只是管道名称、将存储所有输出的根目录、组件列表和元数据配置。
接下来,创建一个 Kubeflow runner 脚本( kubeflow_dag_runner.py )并粘贴下面的代码:
定义 KubeflowDagRunner 以使用 Kubeflow 运行管道。
这个脚本是特定于 Kubeflow 的,是通用的,所以你可以在你的项目中使用它。在这里,您可以定义所有变量,例如数据路径、输出的存储位置、管道名称以及训练和评估参数。
import os
from absl import logging
import pipeline
from tfx.orchestration.kubeflow import kubeflow_dag_runner
from tfx.proto import trainer_pb2
from tfx.utils import telemetry_utils
try:
import google.auth
try:
_, GOOGLE_CLOUD_PROJECT = google.auth.default()
except google.auth.exceptions.DefaultCredentialsError:
GOOGLE_CLOUD_PROJECT = ''
except ImportError:
GOOGLE_CLOUD_PROJECT = ''
PIPELINE_NAME = 'advert_pred_pipeline'
GCS_BUCKET_NAME = GOOGLE_CLOUD_PROJECT + '-kubeflowpipelines-default'
PREPROCESSING_FN = 'model.advert-transform.preprocessing_fn'
RUN_FN = 'model.advert-trainer.run_fn'
TRAIN_NUM_STEPS = 1000
EVAL_NUM_STEPS = 500
EVAL_ACCURACY_THRESHOLD = 0.5
OUTPUT_DIR = os.path.join('gs://', GCS_BUCKET_NAME)
PIPELINE_ROOT = os.path.join(OUTPUT_DIR, 'advert_pred_pipeline_output',
PIPELINE_NAME)
SERVING_MODEL_DIR = os.path.join(PIPELINE_ROOT, 'serving_model')
DATA_PATH = 'gs://{}/advert-pred/data/'.format(GCS_BUCKET_NAME)
def run():
"""Define a kubeflow pipeline."""
metadata_config = kubeflow_dag_runner.get_default_kubeflow_metadata_config()
tfx_image = os.environ.get('KUBEFLOW_TFX_IMAGE', None)
runner_config = kubeflow_dag_runner.KubeflowDagRunnerConfig(
kubeflow_metadata_config=metadata_config, tfx_image=tfx_image)
pod_labels = kubeflow_dag_runner.get_default_pod_labels()
pod_labels.update({telemetry_utils.LABEL_KFP_SDK_ENV: 'advert-pred'})
kubeflow_dag_runner.KubeflowDagRunner(
config=runner_config, pod_labels_to_attach=pod_labels
).run(
pipeline.create_pipeline(
pipeline_name=PIPELINE_NAME,
pipeline_root=PIPELINE_ROOT,
data_path=DATA_PATH,
preprocessing_fn=PREPROCESSING_FN,
run_fn=RUN_FN,
train_args=trainer_pb2.TrainArgs(num_steps=TRAIN_NUM_STEPS),
eval_args=trainer_pb2.EvalArgs(num_steps=EVAL_NUM_STEPS),
eval_accuracy_threshold=EVAL_ACCURACY_THRESHOLD,
serving_model_dir=SERVING_MODEL_DIR,
))
if __name__ == '__main__':
logging.set_verbosity(logging.INFO)
run()
这个脚本还包含一个叫做 run 的重要函数。****运行函数定义了成功执行 Kubeflow 管道的配置。它根据指定的参数实例化一个管道对象,然后执行它。
现在,再次回到您的笔记本实例。在你的互动探索后,在一个新的单元格中,将广告数据复制到你的谷歌云存储中。
如果您的数据已经在 GCS 中,请忽略这一点,只需在 pipeline.py 文件中指定路径。
默认情况下,当您实例化 Kubeflow 时,已经为您的管道创建了一个云桶。您将在复制数据集时指定此路径。
可以导航到云存储浏览器确认文件已经上传。
## copy data to cloud storage for easy access from Kubeflow
!gsutil cp data/advertising.csv gs://{GOOGLE_CLOUD_PROJECT}-kubeflowpipelines-default/advert-pred/data/data.csv
接下来,设置管道变量名。这与 Kubeflow_dag_runner.py 脚本中的相同:
管道名称= '广告预测管道'
接下来,在新单元中,您将使用 tfx pipeline create 命令创建管道,如下所示:
注意,您指定了 Kubeflow runner 脚本、Kubeflow 实例的端点以及 Docker 图像名称。
运行上面的命令需要几分钟才能完成。这是因为 TFX 使用我们之前安装的 skaffold 包来构建管道的 docker 映像。
!tfx pipeline create
--pipeline-path=kubeflow_dag_runner.py --endpoint={ENDPOINT} --build-target-image={CUSTOM_TFX_IMAGE}
成功构建后,您会发现两个新文件(Dockerfile 和 build.yaml)。接下来,您将使用 tfx run 命令向 Kubeflow 提交这个管道作业。如下所示:
您的 Kubeflow 管道已成功推出!要对此进行监控,请转到您的 Kubeflow 实例页面(从这里复制端点 URL),单击 Experiments,,然后选择您的管道名称。
!tfx run create --pipeline-name={PIPELINE_NAME} --endpoint={ENDPOINT}
在执行时,您应该会看到一个管道图。如果有任何错误,它显示一个红色的失败图标,管道停止,否则它显示绿色,所有组件都被执行。
**您还可以在 Kubeflow 中查看每个输出的可视化效果。**这是从每个组件的输出中自动生成的。
例如,下面我们检查 statisticsgen 的输出。点击 statisticsgen 节点,选择可视化。
要查看生成的输出和保存的模型,您可以导航到您的 GCS bucket。
如果您对您的管道进行更新,您可以使用下面的代码轻松地更新和运行它:
就这样!您已经使用 TFX 和 Kubeflow 成功地编排了一个端到端的 ML 管道。结合本教程中使用的工具,您可以轻松有效地构建整个 ML 工作流。
!tfx pipeline update
!tfx run create
摘要
在本教程中,您学习了如何使用 TFX 构建 ML 组件,如何在 AI 云平台上创建笔记本实例,如何交互式运行 TFX 组件,以及如何使用 Kubeflow 协调您的管道。
这是非常重要的知识,你可以开始在你的下一个公司或个人项目中使用。
希望对你有帮助。我等不及要看你造的东西了!
本教程完整课程代码的链接可在此处找到。
参考
本教程旨在介绍 TensorFlow Extended (TFX)和 Cloud AI 平台管道,帮助你学会|www.tensorflow.org
TFX 是一个基于 TensorFlow 的谷歌生产规模的机器学习(ML)平台。它提供了一个配置|www.tensorflow.org
从命令行。对于这个特定的管道,查找带有前缀 workflow1(它的前缀)的服务,并注意|cloud.google.com
Apache Beam 为运行批处理和流数据处理作业提供了一个框架,这些作业可以在各种|www.tensorflow.org上运行
TFX is a Google-production-scale machine learning (ML) platform based on TensorFlow. It provides a configuration | www.tensorflow.org
From the command line. For this particular pipeline, look for the services with prefix workflow1 (its prefix), and note | cloud.google.com
Apache Beam provides a framework for running batch and streaming data processing jobs that run on a variety of | www.tensorflow.org**
如何在生产中部署 NLP 模型
原文:https://web.archive.org/web/https://neptune.ai/blog/deploy-nlp-models-in-production
自然语言处理目前是最令人兴奋的领域之一,因为变形金刚和大型语言模型的出现,如 GPT 和伯特已经重新定义了该领域的可能性。然而,博客和大众媒体的大部分关注点是模型本身,而不是非常重要的实际细节,比如如何在生产中部署这些模型。本文试图弥合这一差距,并解释 NLP 模型部署的一些最佳实践。
我们将讨论模型部署过程的许多关键方面,例如:
- 选择模型框架,
- 决定一个 API 后端,
- 使用 Flask 创建微服务,
- 使用 Docker 等工具将模型容器化,
- 监控部署,
- 以及使用 Kubernetes 等工具和 AWS Lambda 等服务来扩展云基础设施。
这样,我们将从头到尾浏览一个部署文本分类模型的小例子,并提供一些关于模型部署最佳实践的想法。
模型培训框架与模型部署
您对 NLP 框架的选择将对模型的部署方式产生影响。Sklearn 是支持向量机、朴素贝叶斯或逻辑回归等简单分类模型的流行选择,它与 Python 后端集成得很好。Spacy 还因其一体化的语言处理功能而备受认可,如句子解析、词性标注和命名实体识别。它也是一个 Python 包。
基于深度学习的模型通常是在 Python 的 PyTorch 库中编写的,因为其通过运行定义的自动签名接口是构建模型的理想选择,这些模型可能会创建响应动态输入的计算图,如解析变长句子。许多流行的库也是建立在 PyTorch 之上的,比如 HuggingFace Transformers,这是一个受人尊敬的使用预先训练好的 transformer 模型的工具。显然,Python 生态系统对于 ML 和 NLP 来说是极其流行的;然而,还有其他选择。
预先训练的单词嵌入,如 FastText、GloVe 和 Word2Vec,可以简单地从文本文件中读取,并可以用于任何后端语言和框架。Tensorflow.js 是 Tensorflow 的扩展,允许直接用 Javascript 编写深度学习模型,并使用 Node.js 部署在后端,微软 CNTK 框架可以很容易地集成在。基于. NET 和 C#的后端。类似的机器学习包可以在许多其他语言和框架中找到,尽管它们的质量各不相同。尽管如此,Python 仍然是创建和部署机器学习和 NLP 模型的事实上的标准。
后端框架与模型部署
您对后端框架的选择对于成功的模型部署至关重要。虽然语言和框架的任何组合在技术上都可以工作,但是能够使用与您的模型相同的语言开发的后端通常是很好的。这使得将您的模型导入到您的后端系统变得很容易,而不必在不同的交互后端服务或不同系统之间的端口之间服务请求。它还减少了引入错误的机会,并保持后端代码干净,没有混乱和不必要的库。
Python 生态系统中的两个主要后端解决方案是 Django 和Flask。推荐使用 Flask 来快速原型化模型微服务,因为它可以很容易地用几行代码建立并运行一个简单的服务器。但是,如果您要构建一个生产系统,Django 的功能更加全面,并且集成了流行的 Django REST 框架,用于构建复杂的 API 驱动的后端。
流行的 NLP 库 HuggingFace ,也提供了一种通过推理 API 部署模型的简单方法。当您使用 HuggingFace 库构建模型时,您可以训练它并将其上传到他们的模型中心。从那里,他们提供一个可扩展的计算后端,服务于中心托管的模型。只需几行代码,每天花费几美元,任何人都可以部署用 HuggingFace 库构建的安全、可伸缩的 NLP 模型。
另一个伟大的 NLP 专用部署解决方案是 Novetta 的 AdaptNLP :
- 它们为快速原型化和部署 NLP 模型提供了各种易于使用的集成。例如,他们有一系列方法,使用 FastAI 回调和功能集成不同类型 HuggingFace NLP 模型的训练,从而加快部署中的训练和推理。
- 他们还提供现成的 REST API 微服务,打包为 Docker 容器,围绕各种 HuggingFace 模型类型,如问题回答、令牌标记和序列分类。这些 API 拥有成熟的 Swagger UIs,为测试模型提供了一个清晰的界面。
NLP 模型的实际部署
现在,让我们看看如何使用 Flask 部署逻辑回归文本分类器。我们将训练分类器来预测电子邮件是“垃圾邮件”还是“火腿”。
你可以访问这个 Kaggle 页面并下载数据集。然后,运行下面的命令创建一个 conda 环境来托管本教程的 Python 和库安装。
conda create -n model-deploy python=3.9.7
安装完成后,通过运行以下命令激活环境:
conda activate model-deploy
然后,通过运行以下命令安装我们需要的库:
pip install Flask scikit-learn
在您等待的时候,请继续查看您下载的 csv 数据集。它有一个标题,指定了两个字段,“类别”(这将是我们的标签)和“消息”(这将是我们的模型输入)。
现在,打开代码编辑器,开始输入。首先,我们将建立分类模型。因为这篇文章是关于部署的教程,我们不会遍历所有的模型细节,但是我们在下面提供了它的代码。
进行所需的进口。
import csv
from sklearn.linear_model import LogisticRegression
from sklearn.feature_extraction.text import TfidfVectorizer
创建所需的功能。
def load_data(fpath):
cat_map = {
"ham": 0,
"spam": 1
}
tfidf = TfidfVectorizer()
msgs, y = [], []
filein = open(fpath, "r")
reader = csv.reader(filein)
for i, line in enumerate(reader):
if i == 0:
continue
cat, msg = line
y.append(cat_map[cat])
msg = msg.strip()
msgs.append(msg)
X = tfidf.fit_transform(msgs)
return X, y, tfidf
def featurize(text, tfidf):
features = tfidf.transform(text)
return features
def train(X, y, model):
model.fit(X, y)
return model
def predict(X, model):
return model.predict(X)
clf = LogisticRegression()
X, y, tfidf = load_data('spamorham.csv')
train(X, y, clf)
现在,让我们设置 Flask,并为服务微服务的模型创建端点。我们首先要导入 Flask 并创建一个简单的应用程序。
import model
import json
from flask import (
Flask,
request
)
app = Flask(__name__)
app.config["DEBUG"] = True
@app.route('/predict', methods=['POST'])
def predict():
args = request.json
X = model.featurize([args['text']], model.tfidf)
labels = model.predict(X, model.clf).tolist()
return json.dumps({'predictions': labels})
app.run()
正如你所看到的,我们构建了一个 Flask 应用程序,并以“调试”模式运行,这样如果出现任何错误,它都会提醒我们。我们的应用程序有一条用端点“/predict”定义的“路线”。这是一个 POST 端点,它接收一个文本字符串,并将其分类为“垃圾邮件”或“垃圾邮件”。
我们以“request.json”的形式访问 post 参数。只有一个参数“text ”,它指定了我们想要分类的电子邮件消息的文本。为了提高效率,我们也可以重新编写这个程序,一次对多段文本进行分类。如果您愿意,可以尝试添加此功能:)。
预测函数很简单。它接收一封电子邮件,将其转换为 TF-IDF 特征向量,然后运行经过训练的逻辑回归分类器来预测它是垃圾邮件还是 ham。
现在让我们测试一下这个应用程序,以确保它能正常工作!为此,请在命令行中运行以下命令:
python deploy.py
这将启动位于 http://localhost:5000 上的 Flask 服务器。现在,打开一个单独的 Python 提示符并运行以下代码。
res = requests.post('http://127.0.0.1:5000/predict', json={"text": "You are a winner U have been specially selected 2 receive £1000 or a 4* holiday (flights inc) speak to a live operator 2 claim 0871277810910p/min (18+)"})
您可以看到,我们正在向/predict '端点发出一个 POST 请求,该请求带有一个 json 字段,该字段在参数“text”下指定了电子邮件消息。这显然是一条垃圾短信。让我们看看我们的模型返回什么。要从 API 获得响应,只需运行
res.json()`。您应该会看到以下结果:
{ '预测':[1]}
您也可以通过在 POSTMAN 中发送请求来测试您的请求,如下所示:
Testing request by sending it to POSTMAN
您需要做的就是输入您的 URL,将请求类型设置为 POST,并将您的请求的 JSON 放在请求的“Body”字段中。然后,您应该会看到您的预测返回在较低的窗口。
如您所见,该模型返回的预测值为 1,这意味着它将该邮件归类为垃圾邮件。万岁。这就是用 Flask 部署 NLP 模型的基础。
在接下来的小节中,我们将讨论更高级的概念,比如如何扩展部署来处理更大的请求负载。
模型部署环境中的容器化
任何模型部署的关键部分是集装箱化。像 Docker 这样的工具允许你将你的代码打包到一个容器中,这个容器基本上是一个虚拟的运行时,包含系统工具、程序安装、库以及运行你的代码所需的任何东西。
将您的服务容器化使它们更加模块化,并允许它们在任何安装了 Docker 的系统上运行。有了容器,你的代码应该总是不需要任何预配置或者混乱的安装步骤就可以工作。容器还使得使用编排工具(如 Docker-Compose 和 Kubernetes)在许多机器上处理服务的大规模部署变得容易,我们将在本教程的后面部分介绍这些工具。
在这里,我们为我们的文本分类微服务遍历一个 docker 文件。要让这个容器工作,您需要创建一个“requirements.txt”文件,指定运行我们的微服务所需的包。
您可以在终端的该目录下运行该命令来创建它。
pip freeze > requirements.txt
我们还需要对我们的 Flask 脚本做一个修改,让它在 Docker 中工作。只需将“app.run()”改为“app.run(host='0.0.0.0 ')”。
现在来看文档。
FROM python:3.9.7-slim
COPY requirements.txt /app/requirements.txt
RUN cd /app &&
pip install -r requirements.txt
ADD . /app
WORKDIR /app
ENTRYPOINT [“python”, “deploy.py”]
让我们试着理解这几行是什么意思。
第一行“来自 python:3.9.7-slim ”,指定了容器的基础映像。您可以想象我们的映像继承了库、系统配置和其他元素。我们使用的基本映像提供了 Python v3.9.7 的最小安装。
下一行将我们的“requirements.txt”文件复制到“/app”目录下的 Docker 映像中。
/app
将存放我们的应用程序文件和相关资源。在下面一行中,我们通过运行命令“pip install -r requirements.txt ”,进入/app 并安装我们需要的 python 库。
现在,我们使用“add”将当前构建目录的内容添加到/app 文件夹中。/app `。这将复制我们所有的烧瓶和模型脚本。
最后,我们通过运行“WORKDIR /app”将容器的工作目录设置为/app。然后我们指定入口点,这是容器启动时将运行的命令。我们将其设置为运行“python deploy.py ”,这将启动我们的 Flask 服务器。
要构建 docker 映像,请从包含 Docker 文件的目录中运行“Docker build-t spam-or-ham-deploy”。假设一切都正常工作,您应该得到一个构建过程的读数,如下所示:
我们现在还可以在 Docker 桌面中看到我们的容器图像:
接下来,要运行包含 Flask 部署脚本的 Docker 容器,请键入:
docker run -p 5000:5000 -t spam-or-ham-deploy
`-p 5000:5000 '标志将容器中的端口 5000 发布到主机中的端口 5000。这使得容器的服务可以从机器上的端口访问。现在容器正在运行,我们可以在 Docker 桌面中查看它的一些统计信息:
我们还可以像以前一样,在 POSTMAN 中再次尝试运行相同的请求:
Testing request by sending it to POSTMAN
云部署
到目前为止,我们的 API 只是被设计来处理适度的请求负载。如果您正在为数百万客户部署大规模服务,您将需要对如何部署模型进行许多调整。
库伯内特斯
Kubernetes 是一个跨大型部署编排容器的工具。使用 Kubernetes,您可以毫不费力地在许多机器上部署多个容器,并监控所有这些部署。学习使用 Kubernetes 是扩展到更大规模部署的一项基本技能。
要在本地运行 Kubernetes,你必须安装 minikube 。
完成后,在你的终端上运行“minikube start”。下载 Kubernetes 和基本映像需要几分钟时间。您将得到如下所示的读数:
接下来,我们希望通过运行以下命令来创建部署:
kubectl create deployment hello-minikube --image=spam-or-ham-deploy
然后,我们希望使用以下方式公开我们的部署:
kubectl expose deployment hello-minikube --type=NodePort --port=8080
如果我们运行“ku bectl get services hello-mini kube ”,它将显示一些关于我们服务的有用信息:
然后,我们可以通过运行“minikube service hello-minikube”在浏览器中启动该服务
您还可以通过运行“minikube dashboard”在仪表盘中查看您的服务。
欲了解更多信息,请查看 Kubernetes 入门文档。
自动气象站λ
如果你喜欢自动化程度更高的解决方案,像 AWS Lambda 这样的弹性推理服务会非常有用。这些是事件驱动的服务,这意味着它们将自动启动和管理计算资源,以响应它们所经历的请求负载。你所需要做的就是定义运行你的模型推理代码的 Lambda 函数,AWS Lambda 会为你处理部署和伸缩过程。
您可以在这里了解更多关于在 AWS 上部署模型的信息。
火炬服务
如果您正在使用深度学习 NLP 模型,如 Transformers,PyTorch 的 TorchServe 库是扩展和管理 PyTorch 部署的绝佳资源。它有一个 REST API 和一个 gRPC API 来定义远程过程调用。它还包括用于处理日志记录、跟踪指标和监控部署的有用工具。
NLP 模型部署中的挑战
1.NLP 模型部署的一个关键方面是确保适当的 MLOps 工作流。MLOps 工具允许您通过跟踪模型的训练和推理中涉及的步骤来确保模型的可重复性。这包括版本数据、代码、超参数和验证指标。
MLOps 工具如 Neptune.ai 、 MLFlow 等。为跟踪和记录参数(比如注意系数)和度量(比如 NLP 模型困惑)、代码版本(实际上,任何通过 Git 管理的东西)、模型工件和训练运行提供 API。使用此类工具监控 NLP 模型的训练和部署对于防止模型漂移和确保模型继续准确反映系统中的全部数据至关重要。
2.另一个挑战是 NLP 模型可能需要定期重新训练。例如,考虑在生产中部署的翻译模型的用例。随着企业在不同国家增加更多的客户,它可能希望向模型中添加更多的语言翻译对。在这种情况下,确保添加新的训练数据和重新训练不会降低现有模型的质量非常重要。因此,如上所述,对各种 NLP 指标的持续模型监控非常重要。
- NLP 模型可能还需要在生产中进行增量和在线训练。例如,如果从原始文本中部署一个情感检测模型,您可能会突然获得一些与“讽刺”情感相对应的新数据。
通常,在这种情况下,您不会想要从头重新训练整个模型,尤其是当模型很大的时候。幸运的是,有许多算法和库可以用来在生产中部署流式 NLP 模型。例如,scikit-multiflow 实现了分类算法,如 Hoeffding Trees ,这些算法被设计为在次线性时间内进行增量训练。
结论
在部署 NLP 模型时,必须考虑许多因素,如部署的规模、部署的 NLP 模型的类型、推理延迟和服务器负载等。
部署 NLP 模型的最佳实践包括使用 Django 或 Flask 等 Python 后端,使用 Docker 进行容器化,使用 MLFlow 或 Kubeflow 进行 MLOps 管理,以及使用 AWS Lambda 或 Kubernetes 等服务进行扩展。
对于那些不想自己处理大规模部署的人来说,有一些易于使用的付费服务,如 HuggingFace 的推理 API,可以为您处理部署。虽然需要一些时间来加快如何优化部署 NLP 模型,但这是一项非常值得的投资,因为它确保您可以将您的模型提供给世界其他地方!
参考
部署计算机视觉模型:工具和最佳实践
原文:https://web.archive.org/web/https://neptune.ai/blog/deploying-computer-vision-models
计算机视觉模型已经变得异常复杂,有各种各样的用例来提高业务效率、自动化关键决策系统等等。但是,如果一个有前途的模型在生产中表现不尽如人意,它可能会成为一个代价高昂的负担。话虽如此,我们如何开发和部署计算机视觉模型事关重大!
机器学习工程师正在他们的模型部署系统中慢慢接受 DevOps 实践,但这并没有结束!我们还需要考虑几个方面,比如代码版本、部署环境、持续培训/再培训、生产模型监控、数据漂移和质量、模型特性和超参数等等。但其中一些实践是特定于机器学习系统的。
在本文中,我们将了解如何在牢记上述方面的同时部署计算机视觉模型。
计算机视觉模型生命周期
考虑到只有少数开发的模型进入连续生产环境,部署计算机视觉模型或任何机器学习模型本身就是一个挑战。
CV 模型生命周期从收集质量数据开始,到准备数据、训练和评估模型、部署模型、监控和重新训练模型。可以通过下图直观地看到这一点:
Computer vision model lifecycle | Source: Author
在本文中,我们将关注计算机视觉模型的部署阶段。您将学习模型部署的关键方面,包括工具,最佳实践,以及部署计算机视觉模型时需要考虑的事项。
CV 模型部署模式、平台和 UI
在这一节中,我们将深入探讨部署和服务计算机视觉模型的不同方式。这里需要考虑的关键因素是:
- 部署模式(REST/RPC 端点、边缘、混合)
- 如何提供给最终用户
- 易于访问硬件和部署平台的可扩展性
部署模式(REST/RPC 端点、边缘、混合)
托管在内部/云平台上的机器学习模型通常通过 API 端点来部署或访问。像 REST / RPC 这样的 API 本质上为两个系统如何交互提供了语言和契约。
另一种模式是在边缘设备上部署模型,其中通过 CV/认知应用的数据消费发生在起始点。通常,部署也可以是混合的,即 API 端点和边缘设备的组合。
它们如何提供给最终用户
根据最终用户使用模型的方式,界面会有所不同。模型可以通过简单的 bash 命令行界面提供给一些用户,而其他用户可以通过基于 web 或基于应用程序的交互式 UI 来使用它。在大多数情况下,模型可以通过 API 提供,下游应用程序使用结果。
易于访问硬件和部署平台的可扩展性
就像在 UI/UX 方面可用的选项一样,我们可以在平台或硬件上部署生产模型的大量选项也是可用的。这包括开发人员经常进行代码开发的笔记本电脑、远程机器、远程虚拟机、托管 jupyter 笔记本电脑的远程服务器、部署在云环境中的带有编排器的容器,等等。
以上提到的每一点都将在下面的章节中详细阐述。
通过 API (REST/RPC)端点的 CV 部署
REST 代表“代表性状态转移”(作者罗伊·菲尔丁)。简而言之,REST 是一种客户机-服务器关系,其中数据通过简单的格式可用/传输,比如 JSON/XML。“RPC”部分代表“远程过程调用”,它通常类似于在 JavaScript、Python 等中调用函数。请阅读这篇文章以获得对 REST/RPC 协议的详细理解。
当 ML 部署 API 与另一个系统交互时,这种通信的接触点是通过 REST/RPC 端点发生的。对于 API,端点通常由服务器或服务的 URL 组成。它就像一个软件中介,允许两个应用程序相互交换数据。它也是一组用于构建软件应用程序的例程、协议和工具。一些流行的预训练 CV 云服务完全在 API 端点上提供服务,例如,Google Vision API。
REST 只是决定了 API 架构的外观。简单地说,这是开发人员在创建 API 时遵循的一组规则。
通常,每个 URL 被称为一个请求(API 请求),而发送回您的数据(主要作为 JSON)被称为一个响应。
一个 API 请求主要由四个部分组成:
端点:端点有一个叫做 URL 的东西,它决定了你请求的资源或数据。在 API 的上下文中,这些 URL 或路径被称为端点。
**方法:**方法是你发送给服务器的请求,比如 GET、POST PUT、DELETE 等。
**头:**头携带请求和响应体、授权、缓存 cookies 等信息。
**数据:**通常以 JSON 字符串和数据 URL 的形式出现。
下面提到了一些我们可以用来创建 Pythonic REST APIs 的工具(假设我们使用 Python 作为 ML 后端代码)。本文的范围不是深入研究这些框架,而是给出它们的一个高层次的概述。
Flask 是用于构建 web 应用和 REST APIs 的 Python 微框架。Flask 的主要工作是处理 HTTP 请求,并将它们路由到后端应用程序中的适当函数。
构建 REST APIs 的另一个流行选项是 Django REST 框架。构建 API 的模式通常被添加到 Django web UI 项目之上。
FastAPI 是一个 Python web 框架,专门用于构建高效的 API。它使用 Python 类型的提示,并内置了对异步操作的支持。FastAPI 框架由于其易用性和多功能性,最近变得越来越流行。
通过 python APIs 部署计算机视觉应用就像部署任何机器学习模型一样。对于面向计算机视觉部署的 API,重要的是您需要传递图像/视频进行处理,并作为后端部署的响应。可以通过下面讨论的一些方法发送图像/视频或其他数据文件
分析器
REST 框架通常有内置的解析器,用来检测请求中的数据类型。其中有 JSONParser、FormParser、MultiPartParser、FileUploadParser 等等。在计算机视觉部署中,FileUploadParsers 将在处理从后端到前端的数据传输中发挥主要作用。
下面显示了一个带有 Flask 框架的文件上传解析器(在我们的例子中,是一个图像/视频等)的样本片段。当然,代码结构随着 Django 和 FastAPI 框架的不同而不同。
from flask import Flask, render_template, request, redirect, url_for
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
@app.route('/', methods=['POST'])
def upload_file():
uploaded_file = request.files['file']
if uploaded_file.filename != '':
uploaded_file.save(uploaded_file.filename)
return redirect(url_for('index'))
代码片段| 来源
对于 python API 创建的详细指南,这将是一篇很好的文章来通读。
在已部署的机器学习模型的上下文中,用户可以利用 API 端点和相关联的 URL 路径来与底层推理引擎传输数据、流程和事务,这意味着它可以来回传输图像、视频数据和命令。随着时间的推移,使用 API 端点来消费计算机视觉模型的情况必然会增加。
计算机视觉 API 提供者
有许多服务提供商提供可以直接与您的应用程序集成的计算机视觉 API。下面将详细讨论其中的一些。有趣的是,您可以选择构建自己的用户界面,或者在这些 API 上使用默认的服务提供商用户界面。
妮克丝
Nyckel 正在提供计算机视觉 API 以及其他可以通过 RESTful HTTPS 请求访问的 API。它们提供了许多预训练的 CV 专用用例,如无条形码扫描仪、质量检测系统、人类情感分析等。
Nyckel 认知解决方案| 来源
Nyckel 通过 https 请求支持三种输入数据类型:文本、图像和表格。
1。Text :传递文本数据的请求和响应将作为 JSON 字符串处理。
2。Image :可以通过以下方式提供传递图像数据的请求:
- Raw image bytes
- 作为 JSON 请求中的数据 URI
传递图像数据的响应将以 JSON 字符串的形式提供,如下所示:
- 指向图像的 url
- 包含图像的数据 URI。
3。表格:它们作为 JSON 键值对来处理。即请求和响应。它允许用户构建自定义 ui,或者作为更大的应用程序管道中的中间 API。
关于访问 Nyckel API 的完整文档可以通过 web 文档共享这里阅读。
aws 识别
它是更广泛的 AWS 云解决方案套件的一部分。该工具提供了预先训练和可定制的计算机视觉功能,可以从图片、视频等中提取信息。“Rekognition”非常适合初学者,因为它不需要深入了解与计算机视觉相关的理论。Rekognition 的现成解决方案包括内容审核、面部识别、视频分析、文本识别、等。
Amazon Rekognition 提供了两个 API 集。亚马逊 Rekognition Image 用于分析图片,亚马逊 Rekognition Video 用于分析视频。需要分析的数据将被上传到 S3 桶中,可以通过AWS CLI&SDK调用。
这两种 API 都可以分析图像和视频,为您的应用提供洞察。或者如前所述,您可以将其用作内部 API,通过 REST/RPC 端点进行访问。
谷歌云视觉 API
Vision API 通过 REST/RPC API 提供强大的预训练机器学习模型。与亚马逊的 Rekognition 类似,它可以为图像分配标签,并快速将其归类到预定义的类别中。它可以检测物体和人脸,阅读印刷和手写文本。
下面显示的部署架构是针对利用 Google Cloud Vision API 的 OCR 应用程序的。
使用 Vision API 的 OCR(光学字符识别)应用程序中的数据流包括以下步骤:
Google Cloud Vision API | Source
The flow of data in the OCR (optical character recognition) application using Vision API involves steps shown below:
1 上传了包含任何语言文本的图像
- 2 触发视觉 API 提取文本并检测源语言
- 如果目标语言与源语言不同,翻译会排队等候
- 4 翻译 API 被触发,翻译翻译队列中的文本
- 5 将翻译后的文本从结果队列保存到云存储中,供以后访问
- 更多信息,请浏览谷歌云 OCR 教程。
Kairos 人脸识别 API
Kairos 人脸识别 API 使用计算机视觉算法来分析在图像和视频中发现的类似人类的人脸,并返回有关检测到的人脸的数据。这些数据可用于图像搜索、匹配和比较人脸,或者检测性别或年龄等特征。
Kairos 是一个相当容易实现的计算机视觉 API,为定制业务用例提供基于云的面部识别服务。
Kairos face recognition API | Source
CV 模型的边缘部署
在深入了解边缘部署的概念之前,了解什么是边缘计算非常重要。
简而言之,边缘计算是一个在相同位置或靠近数据来源的位置进行计算的过程。
如今,企业被大量数据淹没,他们真的不知道如何处理这些数据。传统的分析方法是通过互联网传输生成的数据,用于其他地方的计算工作。但是,由于生成的数据量巨大,并且存在相关的延迟,这种模型已经变得不够用了。这些问题现在通过边缘计算系统来解决。下图显示了云与边缘云与边缘计算的直接对比。
在 CV edge 部署的上下文中,它指的是在云或内部基础架构中创建和训练并部署在边缘设备上的计算机视觉模型。最先进的基于计算机视觉的系统,如自主车辆、制造业中使用的工业机器人、自主无人机等。利用高级别的边缘计算/部署功能。
Compare edge cloud vs cloud computing vs edge computing | Source
让我们来看看计算机视觉算法在边缘部署的一些经典用例。下面的示例简要介绍了边缘计算机视觉系统如何帮助零售商(如杂货店)监控现场活动,并及时采取措施优化销量。
现场安装的摄像机可以捕捉顾客在收银台排队、在特定区域拥挤、识别空货架、一段时间内顾客的购买模式、自助收银台发生的盗窃/欺诈等活动的实时视频。
下图显示了在超市环境中被识别和跟踪的对象。完整的论文可以通过这个链接访问。
CV 模型的另一个应用领域是工业自动化。下图显示了一个在工业环境中对焊缝进行实时质量检测的例子。所示的机器人臂安装有照相机,该照相机识别焊接池中哪里出现问题,以便可以采取纠正措施。捕获的输入流被摄取到基于英特尔 Edge AI 处理器的系统中。该解决方案建立在基于计算机视觉的人工智能推理引擎上,可以检测焊接缺陷,并发送命令立即暂停机械臂,以便及时采取纠正措施。
Object detection in a supermarket setting | Source
Object tracking in a supermarket setting | Source
几乎所有流行的云服务提供商都提供边缘部署服务。下面讨论了其中的一些问题。
Weld porosity detection system | Source
IBM Edge 应用管理器***(IEAM)***是一个模型管理系统,可以在边缘设备上创建、部署和更新机器学习模型。这种特定的解决方案可以管理元数据,并跨多个边缘设备同步部署。在高层次上,该应用程序将有两个组件,一个在云中,另一个托管在边缘设备上,它们将在 HTTPS 连接的帮助下同步。 IEAM 模型管理系统的代表图像如下图所示。
Azure 的边缘部署解决方案
使用 Azure stack edge ,可以将所有 Azure 功能(如计算、存储、网络和 GPU 加速的机器学习)带入任何边缘位置。
边缘设备上的视频分析器的部署架构可能使用以下 Azure 服务:(仅列出了相关的少数服务,实际列表可能会因应用程序而异。)
**Azure 机器学习 😗* 在基于云的环境中构建、训练、部署和管理 ML 模型。
- **Azure 视频分析器 😗* 使用您选择的 AI 构建智能视频应用。
- Azure container registry:构建、存储和管理容器化的(Docker)计算机视觉/ML 模型。
- Azure stack edge:设计用于边缘的机器学习推理。数据在传输到 Azure 之前在边缘进行预处理,Azure 是一种加速器硬件,可以提高边缘人工智能推理的性能。
- **Azure 物联网中心 😗* 一种基于云的托管服务,用于物联网设备和 Azure 之间的双向通信。
- **媒体服务存储 😗* 使用 Azure 存储存储大型媒体文件。
- **本地数据:**存储并用于机器学习模型的训练。
- 下面的示例图简要介绍了 Azure 如何帮助杂货店等零售商监控实时事件并采取及时行动。现场安装的摄像机可以捕捉顾客在收银台排队、顾客在特定区域拥挤、识别空货架、顾客在一段时间内的购买模式、自助收银台发生的盗窃或欺诈等活动的实时视频。
下图是 Azure edge 部署为视频分析系统使用的代表性架构。您可以通过相同的链接详细了解部署架构。
AWS 全景
AWS Panorama 是亚马逊的一款机器学习(ML)设备和软件开发套件(SDK ),可将 CV 引入内部/边缘设备,尤其是 IP 摄像机。企业可以从他们现有的摄像机中访问许多视频资产,但这些数据仍然没有得到利用,主要是因为没有获得洞察力的正确工具。
Edge deployment solutions by Azure | Source
通过 AWS Panorama,您可以将计算机视觉引入本地设备,同时降低延迟影响。它适用于边缘设备;因此,默认情况下,互联网带宽有限的情况可以顺利管理。此外,用户可以轻松地将定制的训练模型带到边缘,并构建与定制业务逻辑集成的应用程序
这里是使用 AWS Panorama 的停车场汽车计数器应用程序的实现的链接。
类似于上面引用的例子,可能有过多的类似应用,例如计算购物中心的访客数量、计算任何给定时间的交通密度、改善餐馆运营等。
CV 模型部署 UI
Parking lot car counter using AWS Panorama | Source
在讨论了 API 端点之后,我们讨论 CV 部署可用的流行 UI 选项的时机已经成熟。让我们探索一些流行且方便的 UI 选项。
命令行界面
命令行界面(CLI)是一种基于文本的用户界面(UI),用于运行程序、管理计算机文件以及与计算机进行交互。CLI 接受通过键盘输入的输入命令;在命令提示符下调用的命令然后由计算机运行。
Bash 是 Linux、Mac OS 最常用的 CLI,PowerShell/Windows 的命令提示符。
这里的要求是 CLI 识别 python 文件,该文件包含 CV 代码和输入数据。结果会生成并存储在您以后可以访问的位置。但是如前所述,由于显而易见的原因,这种模型服务的方式通常对潜在用户不是很有吸引力。
带有 Flask-REST API、HTML 和 CSS 的 Web 应用程序
Flask 是一个小型轻量级的 Python web 框架,它提供了有价值的工具和特性,使得用 Python 创建 web 应用程序和 API 变得更加容易。它允许我们创建轻量级的 web 应用程序,您可以用相当低的代码在本地机器、云环境或容器中运行。它还可以在浏览器上呈现 HTML 文本,允许您定制用于模型服务的 UI。因此,如果我们能在使用 HTML 的同时使用 CSS,这将变得更具视觉吸引力,与我们在网上冲浪时看到的网络应用程序相一致。
下面显示了 python 使用 Flask 的代码片段:
通过执行上面显示的代码片段,会发生以下情况:
导入 Flask 模块并创建 Flask web 服务器
from flask import Flask, render_template
app = Flask(__name__)
@app.route("/")
def home():
return render_template("homePage.html")
@app.route("/new_address")
def salvador():
return "Hello, new_address!"
if __name__ == "__main__":
app.run()
name 表示当前文件
- app . route(“/”)表示默认页面。当我们将浏览器连接到本地主机端口时,会弹出此消息
- render_template 呈现代码提供的 HTML & CSS 文件;这使得用户界面更好!
- 来自浏览器的 app.route("/new_address ")路由到代码片段中显示的下一个方法,该方法又打印出" Hello,new_address!"
- 有关更多信息和实际实施,请参考此文章。
- 下面显示了一个使用基于 Flask 的 web 应用程序的例子,该应用程序是为多类图像分类定制的。
如果你想开发一个类似的应用并进一步阅读,请点击这个链接。
使用 Flask 的模型部署非常适合本地部署,甚至是在有许多用户使用 API 的云服务器上。你可以使用` docker-compose 和 Nginx 负载均衡器构建一个可伸缩的 Flask 应用程序,其中 Nginx 是一个开源的 HTTP web 服务器,也可以充当反向代理服务器。
Example of using Flask based web application tailored for multiclass image classification | Source
使用 Docker-compose,您可以创建由 Nginx 负载平衡器提供服务的 Flask 应用程序的多个实例。您可以在这篇文章中浏览相同的详细实现。
带有 Flask API(或任何 Python API)和 React FE、CSS 的 Web 应用程序
Building a Python scalable Flask application using docker-compose and Nginx load balancer | Source
香草烧瓶并不总是用户友好的。自动用户界面更新、动态查询等并不总是有用的。
此外,我们不能指望它能创造出像 React 或 Angular 那样酷的 ui,除非你已经在其中嵌入了一些高级的 JQuery 表单提交技术。React Native 是目前最流行(也是最强大)的 web UI 工具之一。它支持一些最广泛使用的网络/移动应用程序和界面。
作为一名熟悉 Python 的经验丰富的数据科学家,使用基于 JavaScript 的工具对您来说可能很困难。但是通过将 React 与 Flask API & python 耦合用于后端,这就成为了为 CV 模型创建 UI 的最酷的方式之一。下面是使用 React 原生 UI 进行图像分类的截图。
这里有一个使用 React 和 Tensorflow 创建图像分类 app 的链接。部署到 Heroku 的 React 和 Flask 的另一个实现在这里显示为。
决定使用 React for UI 意味着雇佣一个专门的 UI 开发人员或者学习一个新的 UI 工具和脚本语言!。
React Native UI for image classification | Source
使用细流服务 web ui 的模型
在我看来, Streamlit 可能是一位经验丰富的数据科学家创建 web 应用程序的最快方式,他对 Python 比对 Javascript 更熟悉(React 主要基于 Javascript)。开发人员可以创建一个 web 应用程序以及后端 ML 算法。所以与基于 Flask/React 的系统不同,它不需要单独的 http/s 路由来发送 JSON 数据。最好的部分是,它有内置的功能来呈现表格,图像,gif 数据等。,放到网络屏幕上,而且也是开源的!你还需要什么?
出于同样的原因,它正在成为服务于计算机视觉模型或者任何机器学习模型的最流行的方式之一。
下面展示了一个 Streamlit web UI 有多酷的例子:(所有这些都使用了最少的 python 风格代码!)
CV 模型服务平台
上面讨论的所有事情,不管是 ML 生命周期操作还是 UI,都需要某种平台来操作。这些平台之间的选择通常主要基于:
Model serving web UI with Streamlit | Source
CV model serving platforms
1 涉及的费用
2 组织对云提供商的选择
- 3 可用的内部基础设施
- 4 目标用户角色的技术成熟度
- 5 目标用户量等。
- 例如,用户通常希望在使用解决方案时,人工智能是不可见的。这意味着用户通常不想纠结于基于人工智能的复杂决策。
- 对他们来说,部署在任何云平台上的 web 应用程序形式的 UI 就足够了。但是在某些情况下,用户需要足够的灵活性来修改算法&需要定制的用户界面。你如何为你的模型服务将取决于上面提到的因素。
许多云服务提供商都有完全集成的机器学习平台。让我们来看看其中的几个。
aws pagemaker
SageMaker 是 AWS 完全集成的机器学习平台。它具有图像注释平台、嵌入式 Jupyter 笔记本环境、实验跟踪、模型监控等功能。与 Rekognition 中给出的点击式解决方案相比,它还是一个开发需要仔细裁剪和定制的机器学习算法的优秀工具。
该生态系统与所有其他 AWS 相关工具配合得非常好。因此,如果您的组织是 AWS 的客户,并计划构建复杂的计算机视觉或任何机器学习模型,Sagemaker 将是现有套件的一个很好的补充。
在中给出了端到端多类图像分类的示例。该示例具有通常的机器学习项目步骤:
The ecosystem works very well with all other AWS-related tools. Hence, if your organization is an AWS customer and plans to dive into building complex computer vision or any machine learning models, Sagemaker would be a great addition to the existing suite.
1 预处理
2 数据准备
- 3 模特培训
- 4 超参数调谐
- 5 训练&推论
- 以上分享的文章里都有提到。
- 除了图像分类,Sagemaker 还提供了内置的注释工具,用于语义分割、实例分割、对象检测等。但是一些独立工具(本文前面已经讨论过)所提供的复杂程度可能会比这些通用注释服务更好。
下图显示了 Sagemaker 提供的一些注释选项。
下图显示了一个使用 Sagemaker 进行语义分段的例子。
Azure 机器学习
Image annotation options using Sagemaker | Source
Azure ML 是另一个基于云的环境,你可以用它来训练、自动化、部署和监控机器学习模型。
Semantic segmentation annotation using Sagemaker | Source
Azure 中的自动化 ML 支持计算机视觉任务的模型训练,如图像分类、对象检测和实例分割。目前通过 Azure 机器学习 Python SDK 支持为计算机视觉任务创作 AutoML 模型。由此产生的实验运行、模型和输出可以从Azure Machine Learning studio UI访问。
它内置了与流行的机器学习和深度学习库的集成,如 Pytorch 、 TensorFlow 、 MLflow 等。有趣的是,它有自己的开源 MLOps 环境。下面显示了使用 Azure ML 的 ML 管道的步骤,这对于使用计算机视觉的管道也是常见的:
Automated ML in Azure supports model training for computer vision tasks like image classification, object detection, and instance segmentation. Authoring AutoML models for computer vision tasks are currently supported via the Azure Machine Learning Python SDK. The resulting experimentation runs, models, and outputs are accessible from the Azure Machine Learning studio UI.
1 任务类型选择
2 数据消耗
- 3 数据增强
- 4 配置和运行实验
- 5 评估指标的选择
- 6 超参数优化
- 7 注册和模型部署
- 与 AWS 环境提供的功能类似,Azure AutoML 支持图像分类、图像分类多标签、图像对象检测、图像实例分割等任务。
- 右侧还显示了不同的内置注释工具。因此,带有相当简单注释的 CV 项目可以在 Azure ML 中轻松处理。
下面的架构展示了如何在支持 GPU 的机器集群之间进行 CV 模型的分布式训练。该场景是图像分类,但是该解决方案可以推广到其他 CV 用例
例如语义分割、对象检测等。
使用 Azure Kubernetes web 服务可以轻松部署在 Azure 中端到端开发的 CV 模型。
这里有一个链接设置 AutoML 用 Python 训练计算机视觉模型。如果您想进一步探索 Azure ML 的功能,请仔细阅读。
谷歌云人工智能平台
这个平台是谷歌的另一个相当先进的平台,具有许多支持机器学习生命周期管理的功能。谷歌在计算机视觉方面提供的旗舰产品有:
**Vertex AI 😗* 将所有的谷歌云服务,连同一个 UI 和一个 API,集合在一个平台下。在 Vertex AI 中,您可以使用 AutoML 或自定义代码训练来训练和比较模型,并且您的所有模型都存储在一个中央模型库中。Google 提供的所有 MLOps 工具都可以在一个平台上使用。
**AutoML Vision 😗* 提供了一个易于使用的 GUI 来训练您自己的定制 CV 模型。AutoML Vision 优化了模型的准确性、延迟和大小,并将它们导出到云或任何边缘设备。
谷歌公司的另一个强大的解决方案是视觉检测 AI 。这直接应用于检测制造业中的产品缺陷。
一些应用包括机器人焊缝的视觉检查、PCB 检查等。
目测 AI | 来源
您将发现来自同一来源的易于学习的用例,以帮助您开始使用任何 google cloud vision 工具。无论需求是什么,谷歌云工具都有适合你的价格。它可以是按使用付费、按比例按月收费、按节点小时固定费率等。
Kubeflow
Kubeflow 是另一个开源的机器学习平台,与各大云平台无缝集成。
Kubeflow 旨在让机器学习(ML)工程师和数据科学家轻松利用云资产(公共或内部)来处理 ML 工作负载。通过 Kubeflow,Jupyter 笔记本电脑可以开发 ML 模型并创建 Kubernetes 资源,以便在任何平台(即内部、远程或云环境)上培训、封装和部署其模型。由于 Kubeflow 开发的初始阶段发生在谷歌,它已经具有与谷歌云平台(GKE-谷歌 Kubernetes 引擎)的出色集成能力。
运行在 Kubernetes 之上的 Kubeflow 可以在云和内部平台上运行,但部署 Kubernetes 优化的机器学习模型是一项艰巨的工作。然而,开发人员一直在努力简化它的采用。
无论是哪种情况,Kubeflow 都是部署计算机视觉模型以及云服务提供商甚至内部安装的绝佳平台。
从计算机视觉模型部署的角度来看,当提供充足的资源(如 RAM、存储空间和处理能力)时,Kubeflow 可以创建可伸缩的 CV 部署。MLOps 工程师在使用它时面临的一个问题是学习和掌握 Kubeflow 提供的功能的内在复杂性。
A diagrammatic workflow for deploying deep learning models using Kubeflow in Azure | Source
Neptune.ai
Neptune 是 MLOps 的元数据存储,为运行大量实验的团队而构建。它为您提供了一个单一的位置来记录、存储、显示、组织、比较和查询所有的模型构建元数据。
海王星是一个理想的工具:
说到数据版本控制,Neptune 是一个可靠的轻量级解决方案。
从 CV 模型部署的角度来看,Neptune 为每次实验运行中的每个模型性能参数提供了大量的见解。这为试验更多的超参数(如学习率、优化算法等)提供了足够的空间。因此,通过这些功能,为 AI 开发人员简化了生产部署的模型选择。
下图显示了与 CV 模型实验相关的跟踪仪表板。这是一个定制仪表板,任何人都可以在 Neptune 为 ML 项目创建它。
工具将与众多流行的机器学习库很好地集成在一起,如 Scikit learn 、 TensorFlow 、 Pytorch 、 XGBoost 、 LightGBM 等等。
随着计算机视觉中使用的 PyTorch 和 TensorFlow 等流行库的集成,Neptune 将非常有能力处理基于这些库的 CV 模型。
Custom dashboard created for a Computer Vision project in Neptune | Source
MLflow
MLflow 是一个管理 ML 生命周期的开源平台,包括实验、可复制性、部署和中央模型注册。MLflow 提供了诸如实验跟踪、模型打包、模型注册等功能。MLflow 集成了大多数流行的机器学习工具/库,如 Scikit learn、Tensorflow、Pytorch、Spark 等。此外,Docker & Kubernetes 等容器化工具以及与最流行的云平台的内置集成也是可用的。
和其他 ML 项目一样,MLflow 也可以支持计算机视觉相关的项目。这包括为实验模型、在每个实验中产生的工件等创建模型注册。下图显示了 MLflow 可以集成的一些流行库。实际列表比图表中显示的要大。Databricks 内置了与 MLflow 的集成。
MLflow 易于与 docker-compose 代码集成,这也使它成为开源代码用户中一种流行的部署替代方案,用于快速的容器化部署。作为一个开源工具,MLflow 在处理模型注册和元数据方面非常通用。因此,如果您的 CV 模型部署预算有限,这将是一个理想的平台。
使用 MLflow & Redis AI 制作计算机视觉模型的例子可以在这个链接上看到。
阿帕奇气流
这是一个主要用于数据工程管道的工作流管理平台。气流是用 Python 写的。因此,Airflow 的一个关键优势是,您可以通过 python 脚本编排工作流。工作流被设计成大部分是静态的或缓慢变化的。预计气流工作流程在后续运行中看起来相似;这使得工作单元和连续性更加清晰。
从计算机视觉的角度来看,气流可以用于对图像数据集、它们的版本化等执行某种流水线操作。一个有趣的用例是流入训练自动驾驶算法的图像/视频数据。新的数据集需要通过转换管道进行传递,以便持续进行模型再训练和数据漂移监控。
DVC
DVC 的建立是为了让 ML 模型可以共享和复制。它是专门为处理大型数据集、文件、ML 模型、元数据以及代码而设计的。它是所有类型的 ML 部署的通用工具,而不仅仅是专门针对计算机视觉的。
Object detection for self-driving cars | Source
DVC 提供以下功能:
DVC matches the right versions of data, code, and models | Source
**数据版本控制 😗* 允许您在 Git 提交中捕获数据和模型的版本,同时根据选择的存储硬件将它们存储在本地或云存储中。
**ML 项目版本控制:**即通过连接 google 云存储、Amazon s3 buckets 等云存储,对 ML 模型和数据集&元数据进行版本控制。
- ML 实验跟踪:使用 Git 版本控制来跟踪实验。DVC 在 Git 中做实验和关联分支一样快。
- 部署和协作:由于其固有的类似 git 的功能,生产部署也更加直观。此外,不同团队之间的强大协作是可能的,并且引入了高度的灵活性。
- CV 模型部署成熟度级别
- ML 部署的成功很大程度上取决于自动化水平。因此,这意味着在生产中维护模型所需的人工干预越少,它就变得越成熟。
成熟度级别可以归因于下面显示的当前部署实践。你可以在谷歌云文档页面阅读详细文章。本节不是专门针对计算机视觉的,而是针对所有 ML 模型部署的通用指南。
手动过程
顾名思义,ML 模型开发周期的每一步都是手工完成的。这个过程更具实验性和反复性。模型开发、验证等。,发生在 iPython 笔记本或类似的快速开发环境中。通常,每一个步骤都是相互分离的。然而, CI/CD 操作在这一级不存在。当数据科学家/团队只处理很少的模型和数据集时,它特别适合,这些模型和数据集通常不会随时间而改变。
与计算机视觉模型相关的典型步骤包括:
通过网络搜集或开放数据集收集训练数据
使用注释工具
- 使用笔记本进行代码/模型开发
- 模型训练和验证的迭代步骤
- 将模型交给工程团队进行 API 配置、测试和部署。
- 对于刚刚开始在用例中应用机器学习的企业来说,这种成熟度是常见的。但它也带来了各种挑战,例如模型无法适应输入数据的变化,或者在最坏的情况下,模型可能在生产中失败。CI/CD/CT 等 MLOps 实践有助于应对这些挑战。
- ML 流水线自动化
在这个自动化水平上,再培训和交付是自动进行的。这意味着,当大量新数据到达时,或者随着时间的推移,或者当观察到模型性能漂移时,就会触发重新训练。在参数空间中运行实验、记录生产模型、模型验证和生产模型的重新部署预计会在这个成熟度级别自动发生。
这一级别的 ML 管道的一些特征是:
快速实验
持续培训
- 组件和管道的模块化和可重用代码。
- 连续发货等等。
- 在此阶段可以预期的一些附加组件有:
- 数据有效性
在这一级,需要通过预先构建的数据管道来验证数据。这包括对数据质量、漂移、偏斜、稳健性等的检查。如果较新的数据不符合遗留模式,则应停止培训管道,并提醒数据科学团队缓解这些问题。
模型验证
自动化管道预计将针对较新的训练数据,针对现有的生产模型来评估新训练的模型的性能。例如,在计算机视觉对象检测模型的情况下,必须确保新训练的模型的所有对象类(或至少三分之二的对象类)的平均 IoU ( 交集/并集)的平均精度优于现有的生产模型。
CI/CD/CT
在这一级,模型部署升级到完全可扩展的架构。最常见的是具有健壮的 web 用户界面、负载平衡器、可伸缩数据库等的云部署。随着可训练数据的不断增加,基于并行和 GPU 的计算在这一阶段变得更加重要。模型性能参数被更详细地审查。
它可以包括:
源代码控制:跟踪和管理代码变更的实践
测试服务:评估和验证一个产品做了它应该做的事情的过程
- **模型注册中心 😗* 一个中央存储库,允许模型开发人员发布生产就绪的模型以便于访问
- **特征库:**一个集中的存储库,在这里可以标准化对用于训练&服务的特征的访问。
- 元数据管理:关于实验、模型参数、时间戳、模型性能度量、模型工件等等的信息。
- 可扩展的集装箱化部署
- 网络流量负载平衡器,数据库扩展等。
- 可扩展的 MLOps 设置保证了如下所示的几个组件:
令人惊讶的是,只有一小部分机器学习系统是由 ML 相关代码组成的。周围的组件使它变得复杂。
因此,我们在 DevOps(开发和操作大规模软件系统的流行实践)中遵循的一些步骤也经常在 MLOps 中使用。比如:
Surprisingly only a small fraction of Machine learning systems are composed of ML-related code. The surrounding components make it complex.
1 持续集成
2 连续交货
- 3 持续培训(MLOps 独有)
- 但是在 MLOps 的上下文中,CI 不仅仅是关于代码测试和验证,还包括验证数据质量和模型特性。在 CD 环境中,还有额外的交付培训渠道和预测服务。
- 计算机视觉模型部署的最佳实践
测试驱动的机器学习开发
这是从传统的测试驱动软件开发中借鉴来的另一种实践。
“测试驱动开发(Test-driven development,TDD)是一种软件开发过程,它依赖于在软件完全开发之前将软件需求转换为测试用例,并通过针对所有测试用例重复测试软件来跟踪所有软件开发。这与先开发软件,后创建测试用例的情况相反"
因此,测试和代码不是一开始就开发一个成熟的解决方案,而是在以后的阶段进行测试,而是一次一个功能地迭代构建在一起。
自动化测试和 TDD 在几个方面帮助了人工智能工程师。其中一些是:
提供及时反馈:即时了解代码是否符合规范,及早发现问题,进行增量调试。
迭代地解决挑战:就像通过小增量开发软件一样,类似的方法也可以在人工智能系统开发中使用。
- 花费很少或没有浪费精力:只写实现需求所需的代码。
- TDD 使得组织代码和有效解决问题变得容易。这篇文章展示了一个计算机视觉网络应用的一步一步的测试驱动开发。你可以在这篇文章中了解到一个更通用的适用于所有人工智能系统的 TDD 方法。
测试驱动开发的另一个很好的解释在这篇文章中给出。ATDD 代表验收测试驱动的开发。在开始开发之前,这项技术在循环中涉及到客户、测试人员和开发人员。验收标准是根据所有相关利益方的共识决定的。ATDD 确保所有利益相关者与团队努力的目标一致。
计算机视觉模型的单元测试
Test-driven machine learning procedures to reduce risks | Source
单元测试是测试驱动软件开发必不可少的便捷技术。单元测试包括测试源代码的各个部分,主要是函数和方法,以确定它们满足预期的行为/输出。
单元测试通常是轻量级的,不需要太多的计算工作。特定的 python 库可以帮助您设置这些框架。CV 模型管道中单元测试的一个例子是断言由数据加载器函数返回的图像或张量的大小。
模型监控:确保 CV 模型部署保持相关性的方法!
在生产中,计算机视觉模型可能比生产中的 NLP 相关模型退化得更快。这完全是因为我们看到的事物变化的速度比我们使用语言的速度快得多。
那么,我们需要监控哪些参数呢?嗯,它们就是我们首先用来测试模型性能的那些!。要监控的参数因型号而异。除了统计指标,我还建议在你考虑任何再培训之前进行人工干预。有时,性能衰减可能不会在指标中显示出来,但它在视觉上是可以辨别的。
Model monitoring: the way you ensure the CV model deployment stays relevant | Source
在我们监控生产机器学习模型之前,我们需要有基础事实(标签)。这意味着目标标签是模型监控的黄金标准。嗯,这在很多情况下可能不可行。本节稍后将讨论如何在标签不可用的情况下进行监控。
下面讨论的指标主要基于这样的假设:对于较新的数据集,标签是可用的。
目标检测
在计算机视觉中,目标检测是帮助从图像中分类和定位目标的强大算法之一。
您需要监控的主要对象检测指标有:
并集上的平均交集(IOU): 它被定义为检测边界框和地面真实边界框的并集上高于评估阈值(比如 0.5)的平均交集。IoU 可以确定检测到的真阳性和假阳性的数量。其他相关参数有精度,回忆一下& F1 的成绩。想了解更多,请参考这里的。
- 平均精度(AP): 平均精度可以定义为在各种 IoU 阈值下,单个对象类的精度/召回曲线下的面积。如果您的对象检测模型被分配为只查找一种特定的对象类型,那么跟踪此指标可能是有意义的。
平均精度(mAP): 使用平均精度总体类(如上所述)和总体 IoU 阈值来计算 mAP 分数。
Average intersection over union (IOU) | Source: Author
有了上面提到的指标,我们可以在更新的数据集上跟踪模型性能。可以用现有的模型性能值作为基准来决定是否需要重新训练。
语义分割
The precision-recall curve for SSD model for four object classes,
where IoU threshold is 0.5 | Source
语义分割中使用的主要监控指标是 IoU。这与训练模型时用作损失函数的 dice 系数相同。与对象检测相比,语义分割中的 IoU 变得更加精细,即它是在像素级计算的。
就像对象检测一样,IoU 度量是为每个类计算的,以获得平均 IoU 分数,并且可以进行监控。
另一个监控指标可以是像素精度,它计算正确分类的像素与图像总像素的比率。
Ground truth vs predicted pixels | Source
准确度= TP + TNTP + FP + TN + FN
在监控过程中,这一指标有时会产生误导,因为随着时间的推移,输入数据会出现类别不平衡。
实例分割
实例分段的监控度量与对象检测非常相似。但在这里,我们寻找的是遮罩的 IoU,而不是边界框。与物体检测不同,在这种情况下,IoU 是按像素计算的。
好了,我们讨论了标签可用于监控模型的情况,如果标签不可用呢?
是的,你没听错!有时标签不可用,也不能完全依赖。但是为什么呢?
Instance segmentation | Source
**预测和基础事实标签数据之间的长等待时间:**在要预测的输入数据和它们的基础事实标签可用之间存在长滞后的可能性很大。一个例子可能是:今天生产的故障电路不会被标记,直到生产批次被检查,然后数据被传递给图像标记团队。这可能需要几天甚至几周的时间。
人工标注:在大多数情况下,计算机视觉数据标注是一项耗费时间和资源的人工活动
**模型干预:**部署模型时,您可能会根据模型的预测采取行动,这可能会改变传入系统的数据。
在这些场景中,通过捕获不断变化的数据模式及其统计特征,在数据接收阶段进行监控和干预。关于数据漂移,下面将详细讨论这个概念。一个额外的阅读将是文章分享在这里。
一些有用的工具有 Prometheus ,它可以帮助存储时间序列,比如指标。Grafana 帮助将存储在普罗米修斯中的数据可视化。两者都是开源工具,可用于模型参数监控/跟踪。
计算机视觉应用中的数据漂移
在生产中,很可能会发生数据漂移,进而影响模型性能。一个典型的例子是,在室外背景上训练的对象检测模型突然被输入来自室内背景的数据。在这种情况下,模型性能可能会下降。
计算机视觉应用中的数据漂移| 来源
在另一个例子中,仅在来自独特设备的图像上训练的模型暴露于来自不同环境的图像。一种典型的情况是来自不同设备的医学成像数据。在这些场景中,用更新的数据量化模型性能的变化。
解决这些类型的数据漂移的机制将有助于延长部署的计算机视觉模型的寿命。有一些工具可以用来监控这类问题。 Arthur 是一个漂移检测工具,它可以识别模型是否无法泛化,并提示您采取纠正措施。它们确保进入部署模型的数据看起来像预期的那样。在基于 CV 的系统中,这意味着输入的数据看起来类似于模型被训练的数据。他们的算法是基于这篇论文中使用的 非分布异常 算法。
下图显示了输入数据在不同地区以及随时间的变化情况。
监控 CV 模型的算法偏差
就像任何机器学习模型一样,偏见也可能蔓延到计算机视觉系统中。
How the input data can vary across regions as well as with time | Source
根据技术指标 :
“算法偏差(Algorithm bias)或 AI 偏差(AI bias)是一种现象,当一种算法产生的结果由于机器学习过程中的错误假设而具有系统性偏见。
例如,人们发现,与白人相比,一些面部识别系统更偏向于有颜色的脸。这可能是由于缺乏对平衡数据集的接触。这些偏见通常是无意的,但它们会造成严重的后果,甚至是法律后果。为了避免这种情况,数据科学家应该充分了解数据集、它们的来源、多样性等。数据应该代表可能受到不利影响的不同种族、性别和文化。
谷歌搜索“护士”显示大多是女护士。
谷歌搜索医生显示大多是男医生。
Google search for “nurse” | Source
这种偏差可能来自以下任何一种情况:
Google search for “doctor” | Source
算法偏差:顾名思义,问题出在机器学习算法上。
样本偏差:在这种情况下,训练数据集可能不够有代表性,或者不够大,不能给真实样本空间足够的表示。
偏见偏见:在这种情况下,制度反映了社会上现存的偏见/成见。一个例子是上面说明的现有性别刻板印象,例如训练数据集中出现的女护士和男医生。
测量偏差:这种偏差是由数据的准确性以及如何测量或评估数据的潜在问题引起的。
不平衡的类别:典型的场景可能包括面部特征识别算法,这些算法主要建立在西方白人努力理解典型亚洲面部特征的基础上。
虽然我们知道偏见可以通过许多方式蔓延到最先进的计算机视觉系统中,但意识和良好的治理可以防止这种情况。
这里可以采取一些步骤来解决这些问题:
While we know there are many ways bias can creep even into the state of the art computer vision systems, awareness, and good governance can prevent this.
1 选择具有充分代表性的训练数据
2 在模型部署前进行单独的算法偏差测试
- 3 随着输入数据的变化,积极监控偏差
- IBM 的 AI fairness 360 是一个开源工具包,可以帮助你在整个 AI 应用生命周期中检查、报告和减轻机器学习模型中的歧视和偏见。
- CV 模型开发和部署需要考虑的事项
计算机视觉和数据质量
训练数据的质量是制造健壮和高效的计算机视觉模型的关键因素。您可以考虑糟糕的数据质量可能导致不想要的结果的场景,例如在制造过程中犯下代价高昂的错误、自动驾驶系统造成的错误等。
人工智能开发人员面临的另一个挑战是转换海量数据,例如,通过创建视频注释。取决于帧速率,注释可能是高度劳动密集型的。典型的自动驾驶系统可能需要带注释的图像、视频、GPS 数据、物联网传感器数据等。此外,生成和存储这些不同的数据点可能会很棘手。
那么我们如何解决这些问题呢?
这是通过人员、流程和技术/工具的组合来实现的。
人
根据组织的规模和预算,注释工作人员可能是雇员、承包商、外包团队、众包人员等的混合。为了生成高质量的数据集,对所使用的工具和有针对性的 CV 应用的基本知识是必要的。令人惊讶的是,该项目的很大一部分成本可能仅仅在于数据准备方面。
过程
当你训练、验证和测试计算机视觉模型时,数据注释过程甚至可以发展。因此,这里重要的是团队应该是敏捷的。它们应该能够根据数据类型、注释类型、使用的工具等进行调整。
技术/工具
这些解决方案可以是基于云的、内部部署的,甚至是内部开发的。如果您的模型需要定制注释类型,开发内部注释工具将是一个好主意。由于大多数商业注释工具提供的功能比开源工具多得多,这里最重要的决定可能是内部构建还是购买。其他需要考虑的因素是集成平台的使用、数据安全性等。
部署硬件
有效的计算机视觉部署融合了硬件和底层软件。我们通常只考虑托管部署的本地硬件系统或云环境。但是大量其他应用包括在边缘设备上进行的部署。即使我们能够开发有效的算法,一些部署也可能是在边缘设备上,在那里您无法访问快速处理器,更不用说 GPU 了!。一些系统还与其他物联网设备集成,增加了更多复杂性。
自主无人机是在这种情况下讨论的完美候选,即边缘设备的硬件要求。一些行业现在依靠自主无人机在短时间内完成更多工作。
下图展示了世界各地的军队如何使用自主无人机进行主动监视。如今,许多无人驾驶侦察机都是自动化的、嵌入计算机视觉的边缘机器。
像 UAV (无人机)这样的设备需要以合理的帧速率处理从摄像机流出的视频。作为一个处理工具, OpenCV 或者 Tensorflow Lite 会是不错的选择。另一个突出的例子可能是送货的自动化无人机。他们使用嵌入式视觉来帮助无人机识别他们“看到”的东西,就像无人机可以分辨物体是静止的还是移动的。
这篇论文很好地解释了基于视觉的自主无人机的硬件/部署架构。
Autonomous drones used to carry out active surveillance | Source
其他流行的 edge 设备都是基于 Raspberry Pi 的。Raspberry Pi 4,2GB RAM 型号的起价仅为 35 美元,Raspberry Pi 4 可以作为物联网设备的媒体中心、网络服务器或推理引擎。
来自 Charmed Labs 的 Vizy 配备了一个 Raspberry Pi 4,这是一个嵌入了高分辨率摄像头的智能设备,适用于那些开始使用基于计算机视觉的应用程序的人。Vizy 利用 Raspberry Pi 4 的强大功能和一个高质量的摄像头,让学生或更高级的用户可以轻松构建计算机视觉项目或解决方案。
Sample hardware architecture of the vision-based autonomous drone navigation | Source
An autonomous drone: representative | Source
Vizy 是通过网络界面控制的,而不是通过浏览器的 HTTPS 界面的桌面应用程序。在线编辑器和 Charmed Labs 的大量文档和 API 参考使得入门相对容易。电源板,一个 GPIO 附加板,有它的 API 控制,比如板载 led,风扇控制器,IR 遥控器等。
其他有趣的部署应用包括主要用于仓库/物流应用的 AGV(自动导引车)。最近被称为 vgv(视觉制导车辆),它们是从 AGV 发展而来的。与 AGV 不同,它们不需要任何磁条或反射器。由于它们是基于地面的,不像无人机,它们可以负担更重的内置硬件。
Vizy hardware specifications | Source
Vizy- a raspberry pi-powered AI camera | Source
在亚马逊机器人履行中心使用的机器人是另一个具有边缘设备计算能力的计算机视觉模型部署的经典例子。但是,他们再次使用计算机视觉、物联网和传感器数据的组合来导航和执行他们的预期职责。
CV 模型开发和部署的经济性和可行性
明确的业务目标对于部署成功的计算机视觉模型至关重要。比如:
Robots carrying inventory pods to warehouse I Source
是提高生产效率或盈利能力还是提高销量?
它是否最大化/最小化了与业务目标相关的 KPI?
- 模型部署能够为您的组织带来什么样的货币价值?
- 从长远来看,收益是否大于成本?
- 在组建团队或选择部署工具时,成本效益分析非常有意义。每种工具都有各自的优缺点。一个昂贵的云原生集成平台可以节省大量的培训时间和资源以及数据 ETL 成本,但与此同时,订阅可能会很昂贵。与 NLP 或经典机器学习模型开发相比,计算机视觉模型开发可能会开发额外的工具开销,如专门的注释工具。
- 值得注意的是,近 90%的 ML 模型从未投入生产;计算机视觉模型也是如此。在许多公司中,这背后的一些原因包括我们无法确保在小环境中工作的模型在其他地方也能工作,障碍可能来自数据不可用、云存储不足等形式。
估算计算资源的数量和成本
对于熟练的人工智能开发人员来说,想出一个可行的算法不再是问题。他们已经存在了!挑战通常在于计算资源的可用性。领导者经常低估硬件需求,以及使用云服务时产生的成本。这通常导致他们将大部分预算花费在算法开发上,但是由于其估计成本(通常发生在后期阶段),因此无法进行充分的培训和测试。
训练一个 ML 模型要多少钱?
下面是 AI21 研究人员训练不同大小的 BERT NLP 模型的一些大概的标价成本。
两个数字被并列提及-一次训练运行的成本和典型的满载成本。
$ 2.5k-$ 5 万(1.1 亿参数模型)
$ 10k-$ 20 万(3.4 亿参数模型)
- $ 80k-$ 160 万(15 亿参数模型)
- 好吧,你可能认为这只是 NLP 模型?。那么,看看最新的 CNN 建筑尺寸吧!
- 那里也一样!因此,为了了解所产生的成本,重要的是要知道深度学习模型的大小、训练批量大小、训练次数以及获得令人满意的训练模型所需进行的实验的预期数量。
跨语言和工具支持问题
许多旧的计算机视觉模型都是用 open CV 构建的(主要是用 C++构建的)。后来 Python 脚本的兴起,导致 Pytorch、Caffe、Tensorflow 等工具的广泛使用。最近,随着 Tensorflow JS(基于 Javascript)的到来,CV 也嵌入到网络应用和边缘/移动设备中。这意味着您也可以将您的 ML 模型带入前端!。现在是朱丽亚的黎明!
由于每种语言都有独特的库和依赖集(甚至是硬件),ML 项目很快变得难以构建和维护,更不用说我们专门的计算机视觉模型了!一些管道使用 Docker 和 Kubernetes 的集装箱化,而其他管道可能不使用。一些管道需要使用专门的 API,而另一些则不需要。
如前所述,一些部署工具能够解决这些不断发展的问题,但与传统软件行业相比,它仍然需要成熟。这就产生了一个独特的问题,对全栈、多语言人工智能工程师的需求。拥有这种技能的人很难找到,雇佣起来甚至更贵。
摘要
在本文中,我们涉及了各种主题,从注释、实验、UI、部署平台、监控、数据/模型验证、最佳实践等等。如果每个人都给予适当的关注,那么所有这些都是 ML 模型成功部署的秘诀。
MLOps 是 ML 世界中一个著名的术语。但是,如果我们能够开始使用术语 CVOps 来表示与计算机视觉模型相关的部署活动,那就太好了。谁知道呢,这可能会成为一个常见的术语!
如果你没有遵循这些步骤,我会说尝试一下!。即使是小型(概念验证)PoC 或可扩展的高性能部署,上面提到的实践也是有价值的。
这篇文章不是路的尽头,所以继续学习吧!
参考
使用 AWS Panorama 在边缘构建和部署对象检测计算机视觉应用
谷歌云视觉 AI
- 适合您的计算机视觉项目管道的最佳 MLOps 工具
- https://cloud . Google . com/architecture/mlops-continuous-delivery-and-automation-pipeline-in-machine-learning
- 野生:野生分布变化的基准
- 在 Azure 上使用 Kubeflow 部署深度学习模型
- 2022 年计算机视觉数据收集指南
- 使用 docker-compose 和 Nginx 负载平衡器构建 Python 可扩展 Flask 应用
- 亚瑟。艾〔t1〕
- 机器学习偏差(AI 偏差)
- 当人工智能遇到商店布局设计:回顾
- AI &基于机器视觉的制造业焊缝缺陷自动检测
- Python 和 REST APIs:与 web 服务交互
- AI & machine vision based automated weld defect detection for manufacturing industry
- Python and REST APIs: interacting with web services
在无服务器上部署下一个图像分类(AWS Lambda、GCP 云功能、Azure Automation)
原文:https://web.archive.org/web/https://neptune.ai/blog/deploying-image-classification-on-serverless
可以说,部署 ML 应用程序从根本上来说是一个基础设施问题,这个问题在很大程度上减缓了 ML 模型进入生产的速度。配置您的基础设施的想法、您的应用程序在生产中的长期维护、可伸缩性和节约成本都是阻碍许多 ML 模型进入生产的挑战。
作为 ML 工程师,我们的首要任务应该是专注于我们的 ML 应用,而不是担心如何灭火。事实证明,有一种技术可以为我们做到这一点。输入…无服务器!无服务器使您可以专注于构建您的应用程序,而不必担心底层基础设施,从而提高您构建模型并将其部署到生产环境中的速度。
在本指南中,您将了解与您作为 ML 工程师相关的无服务器的核心概念,并且您还将在无服务器平台上部署一个影像分类应用程序,这样您就可以看到它是多么简单和快速。
什么是无服务器?
在我们继续定义无服务器的含义之前,让我们了解一下我们是如何做到这一点的:
Serverless definition | Source: modified and adapted from Youtube
我们首先在托管服务器和数据中心上构建和部署应用程序,并负责配置和管理这些服务器。随着云和其他远程计算平台的出现,出现了虚拟机,你可以按需租用和使用服务器。当容器成为主流时,Kubernetes 等应用基础设施的容器编排平台也成为主流。我们现在正在迈向无服务器时代,在这一时代,我们在基础设施的定制化与开发和部署速度之间进行权衡。
那么什么是无服务器呢?无服务器是构建、部署和管理技术基础设施的全面管理方法。
为了完全掌握这个定义,让我们来理解当您部署您的机器学习应用程序时,无服务器为您提供了什么。使用无服务器,您可以:
- 为您的应用进行计算,无需拥有、维护甚至调配底层服务器。
- 复杂的网络和企业级后端集成工具和服务,可根据您的应用程序工作负载自动扩展。
- 无需管理备份即可实现持久存储的持久性。
- 数据库的托管版本,可以根据应用程序的需求进行扩展。
无服务器是如何工作的?
无服务器平台允许您构建和运行您的应用程序和服务,而无需考虑服务器。这是一种新的范式,有两个方面:
带着你的代码去执行
将您的应用程序代码与其他托管后端服务集成在一起。
- 对于代码执行,大多数无服务器平台都有一个“功能即服务”( FaaS)产品,它将为您提供在无服务器平台上执行代码的功能。这样,您就可以开发、运行和管理您的应用程序,而不必担心底层的基础设施。您是在功能级别工作,而不是在容器、服务器或虚拟机级别工作。
- 在无服务器上运行您的 ML 应用程序还需要您集成其他后端即服务产品,如数据库、存储、消息传递和 API 管理服务。
无服务器模式变化包括:
无需管理基础设施:您只需对您的应用负责。基础设施完全由服务提供商管理。
事件驱动的应用:你的架构依赖于事件和无状态计算。
- 为你使用的东西付费:当什么都没发生的时候,你什么也不用付。当事情发生时,您可以获得细粒度的计费可见性。
- 在您开始计划在任何无服务器计算平台上构建和部署您的 ML 应用程序之前,让我们先理清一些事情。
- 你在“无服务器”里做什么?
构建无服务器应用程序时,您有责任:
编写代码,指导您的应用程序如何运行(服务交互、认证管理、输出转储位置等等)。在大多数情况下,您应该保持代码最少,以避免应用程序中的漏洞。
定义触发器一旦有事件(活动的发生)就立即发挥作用。例如,如果存储服务接收到一个文件,那么它应该启动无服务器服务,该服务将依次获取该文件,在其上运行程序,并将输出转储到另一个存储桶中。
- 在“无服务器”中你不做什么?
- 构建无服务器应用程序时,您而不是负责:
为您的应用运行预配置基础设施,因为这种麻烦应该由服务提供商来处理。
修补和管理基础设施在基于容器的基础设施管理中很常见。管理由服务提供商负责,您只需要维护您的代码。
- 定义扩展策略,因为服务应该根据您的应用程序的使用情况自动扩展。您也可以决定设置一些计算设置来启用缩放,但在大多数情况下,这是由服务提供商处理的。
- 在无服务器环境中构建或部署任何应用程序时,另一个需要注意的要点是,您不要将状态与计算一起存储,因为无服务器环境中的计算是短暂的——您的服务器在事件期间会启动。它们并不总是运行,等待请求。这意味着它的状态存储在其他地方,通常在另一个托管服务中。这也是无服务器应用可以轻松扩展的原因之一——计算是无状态的,允许在引擎盖下添加更多服务器以实现水平可扩展性。
- 总结这一节,使用无服务器,您将获得一个环境,在这个环境中,您只需要部署您的代码,将您的应用程序连接到其他后端托管服务,其他一切都由提供商负责。
什么时候应该考虑在无服务器平台上部署 ML 模型?
根据您试图解决的问题,大多数 ML 应用程序都是动态的,当您了解您的模型哪些做得好,哪些做得不好时,需要不断的更新和改进。这非常适合无服务器的使用情形,因为此类平台:
能够处理大量活动。例如,您的模型可以处理来自客户端的预测请求,并根据请求的数量自动伸缩,因此无论处理的请求数量有多少,周转时间都可以保持较低水平。
适合动态工作负载。您可以将新模型快速部署到平台,而无需配置基础架构或担心扩展问题。这就像是把旧型号拿出来,换上新型号。
- 按需提供相比之下,虚拟机或容器服务即使在没有活动的情况下也始终保持运行。从长远来看,这可以节省你的钱,因为你的 ML 服务可能不像你的其他服务那样受欢迎。
- 非常适合预定任务。对于您的生产用例,您可能会在特定的时间间隔运行计划的任务,比如模型再训练。借助无服务器工作流,您可以根据时间表自动执行重新培训和数据处理步骤。
- 在无服务器上部署 ML 应用程序的挑战
- 在尝试将 ML 应用程序部署到无服务器环境时,您可能会遇到一些挑战。
功能是短暂的
**挑战:**部署到无服务器环境意味着您的应用程序将经历冷启动,尤其是当事件被触发时底层服务器还没有托管某个功能时。当您的应用程序想要处理新的预测请求时,这可能会导致延迟问题,尤其是对于在线模型。如果您也想离线运行您的模型,这也可能是一个问题,因为您的离线评分必须在实例仍在运行的时间窗口内结束。
**潜在解决方案:**您可能希望确保 FaaS 满足您所需的 SLA(服务水平协议)。尽管值得注意的是,您的模型总是能够以比服务器冷启动后的启动延迟更低的延迟实时返回预测。在选择无服务器之前,试着理解你在优化什么。你在为实时评分做优化吗?如果是,请尝试理解什么是可接受的延迟。
对远程存储的依赖
**挑战:**由于计算是无状态的,先前客户端请求的会话不会被保留,因此需要在 blob 存储、缓存、数据库或事件拦截器中远程存储会话。这可能会导致性能问题,因为该函数需要在每个实例中写入慢速存储并读回。如果您正在运行高性能的机器学习模型,这可能是一个需要注意的问题。
**潜在的解决方案:**您的函数使用的任何状态都需要存储在外部,最好存储在读写性能相当高的存储器中。
输入/输出性能
**挑战:**功能密集打包并共享网络 I/O,因此涉及高吞吐量计算的进程可能不适合 it。
**潜在解决方案:**如果您正在运行高性能的 ML 应用程序,您可能需要考虑使用另一个计算平台,如虚拟机或容器服务。
通用硬件
**挑战:**在大多数无服务器平台中,您可以使用的是驱动底层服务器的基本 CPU 和计算硬件。你可能找不到通过他们的无服务器平台提供 GPU 或 TPU 的提供商。尽管随着 AWS 最近宣布Lambda 函数现在由它们的 Graviton2 处理器支持,这种情况开始改变。无论如何,内存大小和处理器类型仍然存在限制。例如,在编写本文时,您可以为一个 Lambda 函数分配高达 10 GB 的内存,并访问 6 个 CPU 进行计算。
**潜在解决方案:**如果您的 ML 模型需要运行 GPU 或 TPU 等硬件加速器,您可能需要考虑使用虚拟机来代替。
供应商锁定
挑战:虽然你可以移植你的代码,但你不能总是移植你的架构。对于无服务器,迁移成为一个挑战,尤其是当您的应用程序与供应商提供的其他服务集成时。在大多数情况下,您可能会发现迁移的唯一方法是重新构建您的生产系统。此外,无服务器是一个新兴领域,过早选择赢家存在风险。
**潜在解决方案:**在选择供应商之前,请确保您考虑了他们提供的服务、他们服务的SLA,以及他们是否是您组织的主要供应商,是否也很容易转移您的工作负载。
安全风险
**挑战:**虽然无服务器平台是完全托管的,但是将应用程序部署为功能仍然存在安全风险。其中之一就是不安全的配置。让您的服务和外部连接之间的 API 交互变得脆弱可能会有问题,这可能会导致严重的安全威胁,如数据泄漏、分布式拒绝服务(DDoS)攻击等。
在其他情况下,给予服务和用户比他们需要的更多的访问权限也会带来威胁。虽然在学习过程中这样做可能没问题,但是要确保清理您的架构,并且只给服务或用户提供完成功能应用程序所需的最少特权。对安全和恶意攻击的风险保持敏感的另一个原因是,它们也可能导致高额费用。
**潜在解决方案:**确保您遵循云安全的最佳实践,来自 AWS 的行业标准可在本文档中找到。请确保在您的无服务器平台提供商本机提供的凭据管理服务(推荐)中保护您的凭据。对你的服务和用户来说,始终遵循最小特权原则。
较少的监控和可观察性
**挑战:**应用程序、模型的可观察性,以及它们对业务目标的贡献至关重要。这对于无服务器应用程序来说是很难做到的,因为为您提供的日志和跟踪工具可能不足以让您对应用程序有一个完整的监督。
**潜在解决方案:**您可能希望与第三方 ML 监控工具集成,以便更有效地监督您的生产应用。
其他风险
**挑战:**这里也有 ML 应用固有的风险,如对抗性攻击,尤其是计算机视觉应用。虽然这不是无服务器 ML 应用程序所特有的,但保护模型免受恶意攻击对于无服务器来说是非常困难的,因为你不能控制模型运行的基础设施。例如,攻击可能来自于将恶意输入作为对模型的请求。
**潜在解决方案:**您可能想要尝试使用现有的最佳学术或行业方法构建一个更健壮的模型,因为您的安全基础架构应该只是保护您模型的第二层。
无服务器平台提供商
目前市场上有几家无服务器平台提供商。在本指南中,您将了解如何使用亚马逊网络服务无服务器平台和服务部署您的应用程序。您还将简要了解其他流行的公共云解决方案,如谷歌云平台无服务器 FaaS 产品和微软 Azure 。目前,这是市场上的三个主要参与者。
谷歌云托管的 FaaS 产品叫做云功能。撰写本文时支持的语言包括 Node.js、Python、PHP、.NET,Java,Ruby,还有 Go。云功能的可用触发器是 HTTP 请求、通过发布/订阅的消息传递、存储、Firestore、Firebase、调度程序和现代数据服务。
一些功能包括:
带有“max”选项的自动扩展功能,如果您不想运行太多实例来自动扩展到您的工作负载,您可以选择一个 max 选项。
您可以在唯一身份下运行您的每一项功能,帮助您进行更精细的控制。
- Cloud Run 可用让你在 Google Cloud 的无服务器平台上运行任何无状态的请求驱动容器。
- Azure Functions 是 Azure 面向无服务器应用的功能即服务平台。它支持多种语言,包括 C#、F#、Java 和 Node。Azure 函数的可用触发器包括 Blob 存储、Cosmos DB、事件网格、事件中心 HTTP 请求、服务总线(消息传递系统)、计时器(基于事件时间的系统)。
- 一些功能包括:
AWS Lambda 是亚马逊网络服务的托管功能即服务(FaaS)平台。可以用 Node、Java、C#和 Python 等多种语言编写函数。Lambda 的可用触发器包括 Kinesis、DynamoDB、SQS、S3、CloudWatch、Codecommit、Cognito、Lex 和 API Gateway。
在本指南中,您将学习如何在 AWS 上将图像分类模型部署到无服务器环境中,以构建无服务器 ML 应用程序。
在无服务器上部署图像分类模型[演示]
了解要部署的模型
我们将使用一个预先训练的模型,该模型将主要困扰非洲玉米作物的蛾类物种分为 3 类:非洲粘虫(AAW)秋粘虫(一汽)和埃及棉叶蝉 (ECLW)。
要求
这里,我们希望构建一个移动应用程序,它可以查询一个 ML 模型,并根据上传到外部存储(可能来自其他外部应用程序,如农场中的摄像机)的蛾类物种的新图像返回结果。ML 模型需要不断改进,因为这只是收集更多蛾图像数据的第一个版本。后端的 ML 应用程序应该能够处理非结构化的数据(图像),这些数据可能以批处理和流的形式出现,偶尔也会以突发的形式出现,同时保持尽可能低的成本。
你可能已经猜到了,这听起来像是无服务器的工作!
模型细节
该模型使用 Tensorflow 2.4.0 进行训练,它使用 ResNet-50 模型权重,并添加一些自定义层作为微调的最终层。该模型期望输入图像为 224×224 大小,输出层根据我们正在解决的问题只返回 3 个类。
这个模型已经被压缩成一个tar.gz档案文件,并上传到 S3 存储桶中的一个文件夹。为了确保文件可读,对象被授予了公共读取权限。
如果您遵循您的模型,您可以在这里学习如何授予公共读取权限[。此外,确保您的模型得到正确保存。这个模型是用****](https://web.archive.org/web/20221206031244/https://aws.amazon.com/premiumsupport/knowledge-center/read-access-objects-s3-bucket/)**[TF . saved _ model . save()](https://web.archive.org/web/20221206031244/https://www.tensorflow.org/guide/saved_model)
**格式保存的,并压缩成 .tar
文件(最好)。
先决条件
在开始之前,您需要具备几件重要的事情——
一个自由层 AWS 帐户或一个最多有 3 美元的活动帐户。截至本指南发布时,跟随它的成本应该不到 3 美元。
使用 AWS 云的基本经验。
- 一个完全配置好的 命令行界面工具与你的 IDE 一起工作。你可以在这里安装完整的 vs codeAWS 工具包。
- 稍微熟悉一下 Docker CLI。
- 一个活跃的 IAM 用户(用于最佳安全实践)。我建议您不要使用 root 用户来阅读本技术指南。您可以为用户提供对下列服务的访问权限:
- 下面是我为该角色创建的附加到用户的策略示例(不包括对 DynamoDB 的完全访问权限):
- 第二个弹性容器注册(ECR)策略是公共策略。如果您希望能够与世界上的任何人共享您的容器软件,您可能希望包含此策略。此外,为了使本指南易于理解,我已经允许该用户拥有所有资源和完全访问权限–如果您要将此应用到您的项目中,您可能只想授予完成项目所需的最低权限,以避免安全问题。
解决方案概述
List of attached policies to the user | Source: Author
对于本技术指南,我们将构建的解决方案将使用两个工作流:持续集成/交付(CI/CD) 工作流和主部署工作流。这是我们的整个工作流程:
我们将使用 CI/CD 管道在云上构建和打包我们的应用程序。
然后,我们将把打包的应用程序部署到一个无服务器的功能中,该功能与其他服务集成在一起,以提供一个完全托管的后端生产系统。
- 持续集成/持续交付工作流
- 以下是我们的 CI/CD 架构的外观:
以下是我们将在此工作流程中采取的步骤:
IAM 用户将使用 AWS CLI 和 git 客户端将我们的应用程序代码和一些配置文件推送到私有的 CodeCommit 存储库。
Continuous integration/ delivery workflow | Source: Author
这个新的提交将触发代码管道从我们的Docker 文件为 Docker 映像创建一个新的构建,并使用代码构建创建一个指定的构建配置。
- 一旦构建完成并成功,Docker 映像将被推送到 AWS ECR 中的私有注册表中。
- 现在,您可以使用 Docker 映像来创建 Lambda 函数,它将在生产中充当推理端点。
- 虽然在这个管道中运行您的模型测试和验证是很重要的,但是本指南并不包括测试过程。
- 部署工作流程
这是我们的部署架构的样子:
以下是此工作流程中的步骤:
客户端通过 REST API 端点或管理控制台将映像上传到 S3 存储桶。
Serverless backend deployment workflow | Source: Author
Eventbridge 触发托管我们模型的 Lambda 函数。
- 该函数将日志流式传输到 Amazon Cloudwatch 日志。
- 该函数还将结果写入 DynamoDB。
- 您将使用从 ECR 存储库中构建的 Docker 映像创建一个 Lambda 函数推断端点。此时,您将在部署之前测试该功能。部署完成后,您现在可以通过向您将创建的 S3 存储桶上传新映像来执行端到端测试,以确保一切按预期运行。
- 这是您将在本指南中构建的解决方案的概述。说够了,我们来解决一些问题吧!
构建解决方案
为了实现这个解决方案,克隆本指南的库。在我们查看应用程序代码和配置文件之前,让我们设置一些将用于该解决方案的 AWS 服务。确保您的用户拥有这些服务的必要权限,并且位于正确的区域。
创建一个 S3 桶来保存推理图像
要使用管理控制台,请前往https://s3.console.aws.amazon.com/s3/。要使用 CLI,请查看文档并跟随操作。
点击屏幕右侧的创建存储桶。
- 为您的时段输入描述性名称,并选择适当的区域:
- 4.在阻止该存储桶的公共访问设置下,取消选中阻止所有公共访问并选中复选框以同意以下条款:
- 5.接下来,启用 Bucket Versioning ,这样同名的新图像就不会被覆盖(尤其是如果你的应用开发者没有考虑到这一点的话):
Create the S3 bucket to hold inference images | Source: Author
5.保留其他默认设置,点击创建存储桶:
Block public access settings for the bucket | Source: Author
对于本指南,我们将授予公共读取权限,以防您希望您的应用程序返回由您的模型预测的图像。由于数据不是敏感的,我们可以不考虑它,但是您可能希望添加经过身份验证的用户或服务来查看数据(出于安全原因)。对于写访问,这取决于您希望哪个设备或用户上传图像以进行推断。如果您有特定的设备,则只授予对它们的访问权限。
Enable bucket versioning | Source: Author
6.点击权限标签:
Create bucket | Source: Author
7.在权限选项卡下,转到存储桶策略并点击编辑:
8.输入以下策略,并将 <替换为您的存储桶的名称>
更改为您的存储桶的名称:
Go to permissions tab | Source: Author
您的策略编辑器现在应该如下所示:
Go to bucket policy to edit | Source: Author
9.向下滚动并点击保存更改:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicRead",
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:GetObject",
"s3:GetObjectVersion"
],
"Resource": "arn:aws:s3:::<REPLACE WITH THE NAME OF YOUR BUCKET>/*"
}
]
}
就是这样!bucket 中的对象现在应该可以公开访问(读取)了。这对于我们返回图像 URL 至关重要。
Policy editor | Source: Author
创建一个 DynamoDB 表来存储预测
Save the changes | Source: Author
在本指南的前面,我们了解到无服务器功能是无状态的。我们需要将我们的预测存储在某个地方,以便更容易与我们的应用程序进行通信。我们将为此使用亚马逊的 NoSQL 无服务器数据库 DynamoDB ,因为它伸缩性很好,并且很容易与无服务器功能集成。
与您选择的任何托管服务一样,您必须确保它符合您的应用程序要求。在我们的例子中,我们需要存储以下字段:
菲尔茨
描述
| |
模型做出预测的日期
模型做出预测的日期 | |
模型预测的蛾的名字 | |
当我们在生产中监控和管理我们的模型时,由模型做出的预测的唯一 ID 将会有所帮助 | |
做出预测的时间 | |
被预测的图像的公共 URL | |
模型的概率得分 | |
在给定预测日期预测的同一类别的数量 |
要创建一个 DynamoDB 表,只需要两个字段:主键**(分区键)和辅键**(排序键)。测试应用程序时,可以将其他键添加到表中。****
****要通过 CLI 创建表,请确保 CLI 配置了正确的帐户详细信息,并使用:
你也可以使用管理控制台或者通过 Python SDK 以编程方式完成。要检查该表是否处于活动状态,请运行:
前往https://console.aws.amazon.com/dynamodb/并检查可用的桌子。如果表创建成功,您应该会看到:
aws dynamodb create-table
--table-name PredictionsTable
--attribute-definitions
AttributeName=PredictionDate,AttributeType=S
AttributeName=ClassPredictionID,AttributeType=S
--key-schema
AttributeName=PredictionDate,KeyType=HASH
AttributeName=ClassPredictionID,KeyType=RANGE
--provisioned-throughput
ReadCapacityUnits=50,WriteCapacityUnits=50
创建一个弹性容器注册库
aws dynamodb describe-table --table-name PredictionsTable | grep TableStatus
要使用 CLI 创建一个 ECR 私有存储库,请在 AWS 配置的命令行中输入以下内容,用您项目的区域替换 <区域>
:
Successful operation view | Source: Author
您也可以从管理控制台创建私有回购。您应该会看到类似下面的输出:
检查控制台以确认您新创建的 ECR 存储库。您应该会看到类似的视图:
aws ecr create-repository
--repository-name image-app-repo
--image-scanning-configuration scanOnPush=true
--region <REGION>
复制您的库 URI,并将其保存在某个地方,因为您将在下一节中需要它。
Output | Source: Author
检查应用程序代码和配置文件
Confirm the newly created ECR repository | Source: Author
要继续操作,请确保您处于 AWS CLI 环境中(您也可以选择创建一个虚拟环境)。完成以下步骤:
在你的本地电脑上,新建一个文件夹,命名为**image-classification-app
**。
在文件夹中,在该目录下创建一个新的 requirements.txt
文件。您将添加一些您的应用程序使用的外部库,这些库不是 Lambda Python 运行时的本地库。这个函数将使用 python3.8
运行时。
- 创建一个
app.py
脚本,其中包含 Lambda 函数的代码以及将您的函数与其他服务集成的粘合代码。 - 在同一个目录下创建一个
Dockerfile
。 - 另外,创建一个
buildspec.yml
配置文件,CodeBuild 将使用它来构建 Docker 映像。 - 下面是
requirements.txt
的样子: - 在本应用中,我们将使用 TensorFlow 2.4 ,因为我们的模型是用 TensorFlow 2 版本构建的。我们还将使用 pytz 来确保我们的申请时间格式正确。
接下来,我们将看看 Lambda 函数的代码。完整的代码可以在这个库中找到。从 lambda 函数开始,一旦事件触发了该函数,它就运行这个脚本,从包含用于推理的图像的 S3 桶中收集事件细节(用于推理的图像
)。此外,如果客户端上传同名图像,对象将使用 versionId
进行版本控制,而不是被覆盖。
tensorflow==2.4.0
pytz>=2013b
将类名存储在一个变量中,并编写代码在将图像提供给模型之前对其进行预处理。模型的输入层期望一个大小为 224×224 的图像:
使用模型和概率得分进行预测。也获取预测的类名:
def lambda_handler(event, context):
bucket_name = event['Records'][0]['s3']['bucket']['name']
key = unquote(event['Records'][0]['s3']['object']['key'])
versionId = unquote(event['Records'][0]['s3']['object']['versionId'])
做出预测后,代码检查 DynamoDB 表,查看当天是否已经做出了相同的预测。如果有,应用程序将更新当天预测类的计数,并用更新后的计数创建一个新条目。请注意,如果您计划在这个数据库中存储大量项目,那么使用 [table.scan](https://web.archive.org/web/20221206031244/https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#DynamoDB.Client.scan)
可能会成为的低效和高成本。您可能需要找到一种方法来用 [table.query](https://web.archive.org/web/20221206031244/https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#DynamoDB.Client.query)
或其他方式编写您的逻辑,例如**[GetItem](https://web.archive.org/web/20221206031244/https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#DynamoDB.Client.get_item)
** 和**[batch GetItem](https://web.archive.org/web/20221206031244/https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#DynamoDB.Client.batch_get_item)
**API。
class_names = ['AAW', 'ECLW', 'FAW']
image = readImageFromBucket(key, bucket_name).resize((224, 224))
image = image.convert('RGB')
image = np.asarray(image)
image = image.flatten()
image = image.reshape(1, 224, 224, 3)
如果这是当天的第一个预测,代码会将其作为新项添加到表中。
prediction = model.predict(image)
pred_probability = "{:2.0f}%".format(100*np.max(prediction))
index = np.argmax(prediction[0], axis=-1)
predicted_class = class_names[index]
这段代码从桶中读取图像,并将其作为将由 Lambda 函数使用的枕头图像返回:
for i in class_names:
if predicted_class == i:
details = table.scan(
FilterExpression=Key('PredictionDate').eq(date)
& Attr("ClassName").eq(predicted_class),
Limit=123,
)
if details['Count'] > 0 and details['Items'][0]['ClassName'] == predicted_class:
event = max(details['Items'], key=lambda ev: ev['Count_ClassName'])
current_count = event['Count_ClassName']
updated_count = current_count + 1
table_items = table.put_item(
Item={
'PredictionDate': date,
'ClassPredictionID': predicted_class + "-" + str(uuid.uuid4()),
'ClassName': predicted_class,
'Count_ClassName': updated_count,
'CaptureTime': time,
'ImageURL_ClassName': img_url,
'ConfidenceScore': pred_probability
}
)
print("Updated existing object...")
return table_items
完整文件
elif details['Count'] == 0:
new_count = 1
table_items = table.put_item(
Item={
'PredictionDate': date,
'ClassPredictionID': predicted_class + "-" + str(uuid.uuid4()),
'ClassName': predicted_class,
'Count_ClassName': new_count,
'CaptureTime': time,
'ImageURL_ClassName': img_url,
'ConfidenceScore': pred_probability
}
)
print("Added new object!")
return table_items
print("Updated model predictions successfully!")
您完成的代码(也在这个存储库中)应该类似于下面的代码,确保您将 <替换为您的表名>
替换为您的 DynamoDB 表名,将 <替换为您的推理映像桶>
替换为您之前创建的 S3 桶:
def readImageFromBucket(key, bucket_name):
"""
Read the image from the triggering bucket.
:param key: object key
:param bucket_name: Name of the triggering bucket.
:return: Pillow image of the object.
"""
bucket = s3.Bucket(bucket_name)
object = bucket.Object(key)
response = object.get()
return Image.open(response['Body'])
检查 Dockerfile
,用你的名字替换 <你的名字>
,用你的邮箱替换 <你的邮箱>
。
检查 buildspec.yml
文件,将 <替换为您的 ECR REPO URI >
替换为您在上一节中创建的 ECR 库的 URI:
import json
import boto3
import datetime
import numpy as np
import PIL.Image as Image
import uuid
import pytz
import tensorflow as tf
from urllib.parse import unquote
from pathlib import Path
from decimal import Decimal
from botocore.exceptions import ClientError
from boto3.dynamodb.conditions import Key, Attr
from datetime import datetime as dt
tz = pytz.timezone('Africa/Lagos')
date_time = str(dt.now(tz).strftime('%Y-%m-%d %H:%M:%S'))
date = date_time.split(" ")[0]
time = date_time.split(" ")[1]
timestamp = Decimal(str(dt.timestamp(dt.now())))
import_path = "model/"
model = tf.keras.models.load_model(import_path)
IMAGE_WIDTH = 224
IMAGE_HEIGHT = 224
IMAGE_SHAPE = (IMAGE_WIDTH, IMAGE_HEIGHT)
s3 = boto3.resource('s3')
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('<REPLACE WITH YOUR TABLE NAME>')
def lambda_handler(event, context):
bucket_name = event['Records'][0]['s3']['bucket']['name']
key = unquote(event['Records'][0]['s3']['object']['key'])
versionId = unquote(event['Records'][0]['s3']['object']['versionId'])
class_names = ['AAW', 'ECLW', 'FAW']
print(key)
image = readImageFromBucket(key, bucket_name).resize((224, 224))
image = image.convert('RGB')
image = np.asarray(image)
image = image.flatten()
image = image.reshape(1, 224, 224, 3)
prediction = model.predict(image)
print(prediction)
pred_probability = "{:2.0f}%".format(100*np.max(prediction))
index = np.argmax(prediction[0], axis=-1)
print(index)
predicted_class = class_names[index]
print('ImageName: {0}, Model Prediction: {1}'.format(key, predicted_class))
img_url = f"https://<REPLACE WITH YOUR BUCKET FOR INFERENCE IMAGES>.s3.<REGION>.amazonaws.com/{key}?versionId={versionId}"
for i in class_names:
if predicted_class == i:
details = table.scan(
FilterExpression=Key('PredictionDate').eq(date)
& Attr("ClassName").eq(predicted_class),
Limit=123,
)
if details['Count'] > 0 and details['Items'][0]['ClassName'] == predicted_class:
event = max(details['Items'], key=lambda ev: ev['Count_ClassName'])
current_count = event['Count_ClassName']
print(current_count)
updated_count = current_count + 1
table_items = table.put_item(
Item={
'PredictionDate': date,
'ClassPredictionID': predicted_class + "-" + str(uuid.uuid4()),
'ClassName': predicted_class,
'Count_ClassName': updated_count,
'CaptureTime': time,
'ImageURL_ClassName': img_url,
'ConfidenceScore': pred_probability
}
)
print("Updated existing object...")
return table_items
elif details['Count'] == 0:
new_count = 1
table_items = table.put_item(
Item={
'PredictionDate': date,
'ClassPredictionID': predicted_class + "-" + str(uuid.uuid4()),
'ClassName': predicted_class,
'Count_ClassName': new_count,
'CaptureTime': time,
'ImageURL_ClassName': img_url,
'ConfidenceScore': pred_probability
}
)
print("Added new object!")
return table_items
print("Updated model predictions successfully!")
def readImageFromBucket(key, bucket_name):
"""
Read the image from the triggering bucket.
:param key: object key
:param bucket_name: Name of the triggering bucket.
:return: Pillow image of the object.
"""
bucket = s3.Bucket(bucket_name)
object = bucket.Object(key)
response = object.get()
return Image.open(response['Body'])
就是这样!确保将您的代码与本指南的库中的代码进行比较。我们现在将设置 CI/CD 管道来推送我们的应用程序代码和配置文件。
FROM public.ecr.aws/lambda/python:3.8
LABEL maintainer="<YOUR NAME> <YOUR EMAIL>"
LABEL version="1.0"
LABEL description="Demo moth classification application for serverless deployment for Neptune.ai technical guide."
RUN yum -y install tar gzip zlib freetype-devel
gcc
ghostscript
lcms2-devel
libffi-devel
libimagequant-devel
libjpeg-devel
libraqm-devel
libtiff-devel
libwebp-devel
make
openjpeg2-devel
rh-python36
rh-python36-python-virtualenv
sudo
tcl-devel
tk-devel
tkinter
which
xorg-x11-server-Xvfb
zlib-devel
&& yum clean all
COPY requirements.txt ./
RUN python3.8 -m pip install -r requirements.txt
RUN pip uninstall -y pillow && CC="cc -mavx2" pip install -U --force-reinstall pillow-simd
COPY app.py ./
RUN mkdir model
RUN curl -L https://sagemaker-mothmodel-artifact.s3.us-east-2.amazonaws.com/models/resnet_model.tar -o ./model/resnet.tar.gz
RUN tar -xf model/resnet.tar.gz -C model/
RUN rm -r model/resnet.tar.gz
CMD ["app.lambda_handler"]
创建代码提交 Git 存储库
version: 0.2
phases:
install:
runtime-versions:
python: 3.8
pre_build:
commands:
- echo Logging in to Amazon ECR...
- pip install --upgrade awscli==1.18.17
- aws --version
- $(aws ecr get-login --region $AWS_DEFAULT_REGION --no-include-email)
- REPOSITORY_URI=<REPLACE WITH YOUR ECR REPO URI>
- COMMIT_HASH=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7)
- IMAGE_TAG=build-$(echo $CODEBUILD_BUILD_ID | awk -F":" '{print $2}')
build:
commands:
- echo Build started on `date`
- echo Building the Docker image...
- docker build -t $REPOSITORY_URI:latest .
- docker tag $REPOSITORY_URI:latest $REPOSITORY_URI:$IMAGE_TAG
post_build:
commands:
- echo Build completed on `date`
- echo Pushing the Docker images...
- docker push $REPOSITORY_URI:latest
- docker push $REPOSITORY_URI:$IMAGE_TAG
1.按照页面上的说明为 CodeCommit 创建您的 git 凭证。
2.一旦你创建了你的 git 证书,在https://console.aws.amazon.com/codesuite/codecommit/home打开 CodeCommit 控制台
3.点击创建存储库:
4.输入一个存储库名称,一个描述,将其余选项保留为默认,然后单击创建:
在显示的页面上确认您新创建的 repo,并查看如何用 git 克隆您的 repo 的信息。您应该看到以下内容:
Create repository | Source: Author
5.要进行第一次提交,请确保您位于正确的文件夹中,即您之前在指南** image-class ification-app
**中创建的文件夹,并输入以下内容(假设您遵循了本指南中的命名约定并使用了相同的区域):
Add repository details | Source: Author
如果成功克隆,您现在应该已经准备好提交代码并将其推送到 CI/CD 管道。
Clone your repo with git | Source: Author
6.在** image-class ification-app
**文件夹中,使用以下命令查看哪些文件尚未提交:
git clone
https://git-codecommit.us-east-2.amazonaws.com/v1/repos/image-app-repo ../image-classification-app/
7.将所有要提交的文件存放在文件夹中:
8.检查文件是否准备好提交:
git status
您应该会看到类似的输出:
git add *
9.或者,您可能需要为此提交配置您的姓名,您可以用您的详细信息替换下面的标签:
git status
10.提交文件并包含一条消息。
Output | Source: Author
您应该会看到类似的输出:
git config user.email "<YOUR EMAIL ADDRESS>"
git config user.name "<YOUR NAME>"
现在,您的代码和配置文件已经准备好被推送到您之前创建的 CodeCommit 存储库中。要将它们推送到存储库,请遵循以下说明:
git commit -m "Initial commit to CodeCommit."
11.使用以下命令将您的提交推送到主分支上游:
您的命令行或 IDE 可能会要求您输入之前创建的 git 凭据。确保您输入了正确的详细信息。如果提交成功,您应该会看到类似的输出:
使用 CodeBuild 构建容器映像
git push -u origin master
为了构建我们的容器映像,我们必须用 CodeBuild 创建一个项目。
1.前往 https://console.aws.amazon.com/codesuite/codebuild/home
2.选择构建项目,点击创建构建项目:
3.在项目配置下,输入您的项目名称和项目描述:
4.在 Source 下,确认选择了 AWS CodeCommit,并选择您的源库( image-app-repo
)。在参照类型下,选择分支,选择主分支。
Create build project | Source: Author
5.在环境下,确保管理镜像被选中。在操作系统下,选择 Ubuntu。选择标准运行时,选择标准:5.0 图像。在镜像版本下,确保始终使用该运行时版本的最新镜像被选中。在环境类型下,选择 Linux 并点击特权下的复选框,因为您正在构建 Docker 映像:
Add project details | Source: Author
6.如果您没有现有的服务角色,请确保选择了新服务角色,并将其他角色保留为默认角色,除非您需要其他配置:
Add source details | Source: Author
7.在 Buildspec 下,确保使用一个 Buildspec 文件被选中。其他默认,包括批量配置下的选项:
Add environment details | Source: Author
8.您的应用程序中没有包含任何工件,因此您可以将工件下的选项保留为默认值。在日志下,确保云观察日志被勾选。输入一个描述性的组名和流名。确认所有选项并选择创建构建项目:
Select new service role | Source: Author
如果您的项目创建成功,您应该会看到类似如下的页面:
Ensure use a buildspec file is selected | Source: Author
如果您想在构建完成时得到通知,您可以点击为这个项目创建一个通知规则。
Create build project | Source: Author
9.在开始项目的构建之前,您需要向您创建的 CodeBuild 角色附加一个新策略。进入你的 IAM 页面,点击角色,搜索你创建的代码构建角色:
Successful new project view | Source: Author
10.点击附加策略:
11.搜索 amazone C2 containerregistrypoweruser 策略。点击旁边的复选标记,并在页面末尾点击附加策略:
Attach new policy | Source: Author
12.在下一页上,确认策略确实已添加:
Select attached policies | Source: Author
13.返回到您创建的项目的 CodeBuild 页面,点击 Start build 来测试您的应用程序构建。如果您的应用程序构建是成功的,您应该会看到如下页面:
Attach AmazonEC2ContainerRegistryPowerUser policy | Source: Author
如果您的构建失败了,日志对于故障排除非常有帮助。如果您正确地遵循了本指南中的步骤,您应该能够成功地构建应用程序。您可以返回到 image-app-repo
(或您创建的 ECR repo)的Elastics Container Registry页面,以确认 Docker 映像确实已创建。
Confirm attached policies | Source: Author
使用代码管道自动构建应用程序
Successful build status view | Source: Author
您不希望依靠手动步骤来部署无服务器组件。要在将新的提交推送到 CodeCommit 时自动化构建过程,可以使用 CodePipeline。
1.转到代码管道管理控制台http://console.aws.amazon.com/codesuite/codepipeline/home
2.确保管道被选中,点击创建管道:
3.输入您的管道名称。如果您没有现有的服务角色,选择新服务角色并输入角色名称。保留其他默认设置,点击下一个:
4.在下一步中,选择 AWS CodeCommit ,输入存储库名称,选择主分支,并将其他选项保留为默认:
Create pipeline | Source: Author
5.在添加构建阶段步骤下,选择 AWS CodeBuild 作为构建提供者。确保选择了项目区域和在上一节中创建的 CodeBuild 项目。其他选项保持默认,点击下一步:
Choose pipeline settings | Source: Author
6.因为我们将手动部署我们的映像,我们将不得不跳过管道中的连续部署步骤。点击跳过展开阶段,当弹出跳过展开阶段对话框时,点击跳过:
Add source stage | Source: Author
7.最后,检查您的设置并点击创建管道:
Add build stage | Source: Author
8.现在,您应该位于应用程序构建过程已经自动开始的页面上:
Add deploy stage | Source: Author
5 分钟后检查,如果构建成功,您应该会看到一个成功的通知。
Create pipeline | Source: Author
现在,您的持续集成和交付管道已经完成。现在,您可以对您的应用程序源代码进行最终提交,以确保您的管道按预期工作。
Successful new pipeline view | Source: Author
确保您仍在项目文件夹中,如果您没有更改代码中的任何内容,请再次暂存代码并添加新的提交消息:
使用以下方式将您的提交推至代码提交:
您可能需要输入 CodeCommit git 凭据。确保您输入了正确的详细信息。
git add *
git commit -m "Final commit"
主分支的推送成功后,返回到 CodePipeline 页面,确认您的推送已经触发了管道中的新构建:
git push
构建完成后,进入 Elastics 容器注册表中的 image-app-repo
(您的 repo)查看新的映像构建:
太好了!您现在可以开始部署了。由于这是一个教程,我们将跳过大部分安全和其他漏洞的测试阶段。如果这是您组织的生产应用程序,您肯定应该考虑进行安全检查。您不希望在 CI/CD 管道中硬编码您的凭证或 API 密钥。您可以使用凭证管理工具,如 AWS 参数存储库。
Confirm your push has triggered a new build in the pipeline | Source: Author
将影像分类应用程序部署到 AWS Lambda
Open image-app-repo | Source: Author
现在,您的应用程序构建已经准备好部署到无服务器功能。要部署它,我们必须设置 AWS Lambda,以便在有新事件时运行应用程序构建。在我们的例子中,每当一个新的图像上传到我们的 S3 桶,它应该触发 Lambda 函数来运行图像上的应用程序,并将预测和其他细节返回到 DynamoDB。
使用 AWS Lambda 创建无服务器功能
1.打开 Lambda 控制台上的功能页面。
2.选择创建功能。
3.在创建功能下,选择容器图像。在基本信息下,输入您的函数名,选择您创建的 ECR 库中的镜像,确保选择 x86 作为微处理器。其他选项保持默认,点击创建功能:
4.一旦你的图像被创建,在功能概述下,点击添加触发器:
Create function | Source: Author
5.在触发配置下,选择 S3 和您想要触发该功能的铲斗。将其他选项保留为默认选项(假设您没有任何文件夹或需要包含特定的扩展名)。勾选递归调用下的复选框,确认信息:
Add function details | Source: Author
添加触发器后,您需要通过为 Lambda 函数的执行角色设置适当的 AWS 身份和访问管理(IAM) 权限,来允许 Lambda 函数连接到 S3 存储桶。
Open add trigger view | Source: Author
6.在您的功能的权限选项卡上,选择 IAM 角色:
Add trigger | Source: Author
7.选择附加策略:
8.搜索亚马逊 3ReadOnlyAccess 和亚马逊 DynamoDBFullAccess 。将两个策略附加到 IAM 角色:
Select IAM role | Source: Author
9.返回到您的功能页面。在配置选项卡下,确保选择通用配置,点击编辑:
Select attached policies | Source: Author
10.将内存大小升级到 7000 MB (7 GB ),以确保应用程序运行时有足够的内存可用。另外,将超时增加到大约 5 分钟。其他选项保持默认,点击保存:
Attach AmazonS3ReadOnlyAccess and AmazonDynamoDBFullAccess policies | Source: Author
就是这样!您现在已经准备好测试您的应用程序了。
Edit general configuration | Source: Author
测试应用程序
Edit basic settings | Source: Author
为了测试您的应用程序,上传一个测试图像到您的推理桶。在我们的例子中,它是**用于推理的图像
**。这里有一个秋天粘虫(FAW)图像的例子,如果您正在跟踪,您可以使用它来测试这个应用程序:
当您将图像上传到 bucket 时,等待几分钟让您的应用程序启动(我们前面讨论过的冷启动问题)。转到 Lambda 函数的页面。在我们的例子中,它是 image-app-func
。在监视器选项卡下,点击查看 CloudWatch 中的日志。检查最新的日志流并查看您的应用程序日志:
您可以看到,应用程序返回了正确的预测,它还通知我们,由于没有现有的对象,它已经向数据库添加了一个新对象。周转时间为 48705 毫秒(或 48.75 秒)。如果您计划运行实时应用程序,这可能是不可接受的。一旦您在前一次预测的 5 分钟内运行了其他预测,延迟应该会显著减少,并且更适合于实时任务。
Image of Fall armyworm (FAW) | Source: Author
转到您之前创建的 DynamoDB 表,检查并确认是否有新项目添加到表中:
Check the latest log stream and see your application logs | Source: Author
干得好!你的应用现在正常工作。您可以检查这个存储库以获得更多的测试图像。
如果您打算就此打住,请确保删除 ECR 中以前的映像构建,以避免为此付费。您不需要为其他服务付费,因为它们是按使用付费的。
Open DynamoDB table | Source: Author
后续步骤
祝贺您阅读完本指南!下一步,您可能希望将无服务器 API 管理服务 API Gateway 连接到您的表,这样您的应用程序就可以从表中获得结果,甚至删除不相关的结果。类似于下图的架构模式:
如果您对此感兴趣,您可以找到 Lambda 函数的示例代码,该代码将 API Gateway 与 GET 和 DELETE 方法连接到这个存储库中的 DynamoDB 表。
对 Google Cloud serverless 应用相同的架构模式
Deployment workflow for serverless ML application | Source: Author
如果您选择将您的图像分类应用程序部署到 Google Cloud 无服务器而不是 AWS,好消息是这种架构模式可以应用到 GCP 的大多数无服务器服务,使用以下工具:
所有这些服务很好地集成在一起,使用本指南中的架构模式,您可以在 Google Cloud 上构建一个类似的应用程序。
对 Azure serverless 应用相同的架构模式
如果您选择将您的图像分类应用程序部署到 Azure 无服务器,那么在以下服务的帮助下,这种架构模式也可以在这里复制:
结论
这是一篇冗长的技术指南,重点介绍部署影像分类应用程序的最佳无服务器模式。不用说,这种架构也适用于涉及非结构化数据的其他类型的 ML 应用程序——当然,需要做一些调整。
总结一下,以下是你在使用无服务器 ML 应用时应该遵循的一些最佳实践:
限制对包的依赖因为在大多数情况下,一个函数的依赖越多,启动时间就越慢,除了管理应用程序的复杂性。
尽量避免你的应用程序长时间运行的函数。如果你的应用很复杂,把它分解成不同的功能,然后松散地耦合它们。
批量发送和接收数据可能会有所帮助。使用无服务器函数,当用批处理数据实例化一个函数时,可以获得更好的性能。例如,您可能希望将图像存储在 S3 桶中,而不是在图像来自客户端时将其发送到您的应用程序,并且只在特定的时间间隔或当一组新的图像上传到桶中时才触发该函数
考虑您选择的平台中可用的工具生态系统对无服务器环境中的应用进行可靠的跟踪、监控、审计和故障排除。
- 负载测试 **您的应用程序在部署到实际环境之前。**这对于无服务器的 ML 应用尤为重要。
- 考虑用于选择部署策略的特性,例如蓝绿色部署、 A/B 测试和金丝雀部署是否在您选择的平台中可用,并在您的部署工作流中使用它们。
- 参考资料和资源
- Consider the ecosystem of tools available in your platform of choice for robust tracing, monitoring, auditing, and troubleshooting your applications sitting in serverless environments.
- Load test your application before deploying it to a live environment. This is especially crucial for serverless ML applications.
- Consider if features for selecting deployment strategies such as blue-green deployment, A/B testing, and canary deployment are available in your platform of choice and use them in your deployment workflow.
References and resources****
部署 ML 模型:如何确保新模型比生产中的模型更好?[实用指南]
让我们假设我们正在进行一个与 ML 相关的项目,并且第一个 ML 模型已经成功地部署到生产中,遵循了大多数 MLOps 实践。好吧,但是现在怎么办?我们完成工作了吗?
我假设你们大多数人都知道答案是什么,当然,答案是否定的。我们预计,由于模型陈旧或数据漂移,该模型不会永远正常工作。而且,模型不需要自己变坏,说不定还能产生新的更好的模型!
等等,但是更好的模型是什么意思呢?在测试集上准确率更高的模型?还是嵌套,分层,k 折,什么交叉验证后精度更高的模型?
嗯,可能不会。答案要复杂得多,尤其是对于生产中的更好的模型。
在本文中,我们将解释如何确保您的新模型比生产中的模型更好。我们将尝试提及所有可能影响决定更好模型的因素。除此之外,重点将放在模型的生产上,还将介绍一些部署新模型的技术。
为什么以及何时需要在生产中部署新的 ML 模型?
ML 项目是高度依赖于输入数据的动态系统。与传统软件相比,大多数软件会随着时间的推移而退化,或者变得越来越不相关。这个问题也被称为模型过时。ML 模型在生产中部署后可能发生的一些问题是:
- 数据漂移–当输入特征(即独立变量)的分布与模型在训练中观察到的情况发生剧烈变化时。
- 模型或概念漂移——当目标变量即因变量的性质发生变化而不改变输入特性时。
- 培训-服务偏差-生产中的模型,与培训的性能不同。
- 技术 bug等类似的东西。
为了及时发现这些问题并采取行动,我们需要实施相关的监控策略。
Model monitoring and retraining | Source: Author
除了监控之外,解决模型陈旧的方法是实施再培训策略。模型再训练的时间取决于业务用例,但是通常有四种不同的方法:
- 基于时间间隔–每天、每周、每月或类似时间重新训练模型。
- 基于性能的–当模型的性能低于预定义的阈值时,重新训练模型。
- 基于数据变化–在重大数据变化或引入新功能后触发培训。
- 按需重新培训–出于其他原因手动重新培训模型。
但再训练毕竟只是作为数据和概念漂移问题的急救手段。很可能在几次重新训练迭代之后,模型将不会达到它以前拥有的最大性能。此外,如果重新训练逻辑基于模型性能,则模型重新训练之间的时间间隔可能会变得更短。
当再培训变得越来越低效时,这是一个信号,表明我们需要考虑一种新的模式。而且新的模型需要按时准备,因为我们不想等到最后一分钟,模型才完全停止良好的表现。
一般来说,当开发团队确信一个新的生产模型满足了所有被推向生产的需求时,可以在任何时候部署这个新的生产模型。我们不一定需要等到生产中的旧模式变得无用。
但是在部署新模型之前,我们需要确保它确实比旧模型更好。即使从各个角度来看,开发中的新模型似乎比旧模型更好,直接部署它们也是不安全的。
在下面的小节中,我们将讨论一些部署新模型的技术和最佳实践。
如何比较 ML 车型?
要知道哪种模式“更好”是一项非常具有挑战性的任务。立即出现的一个大挑战是过度拟合。当最大似然模型过于接近训练数据时,就会出现问题,这会导致在新数据上表现不佳。这甚至可能发生在有经验的机器学习实践者身上,因为过度拟合和良好拟合之间没有明确的界限。
Overfitting challenge | Source
另一个挑战是为模型评估选择正确的指标,这将考虑所有的业务需求。例如,网飞在 2009 年给一个开发团队颁发了 100 万美元的奖金,奖励他将网飞的推荐算法提高了 10%。最终,他们从未使用过这种解决方案,因为这种解决方案太复杂,无法部署到生产中,而且工程成本不值得。
模型评估指标
在生产中部署新模型之前,我们需要确保开发中的新模型比旧模型更好。有许多不同的评估指标可用于比较模型,选择正确的指标至关重要。这里就讨论几个比较流行的。
分类指标
说到分类指标,选择指标时要考虑的主要因素是:
- 类别数量——二元或多元分类。
- 每堂课的样本数量——我们有一个平衡的数据集吗?
- 业务用例——例如,根据业务用例平衡精确度和召回率。
最常用的分类标准是准确性。对于更不平衡的数据集,使用 F1、精度和召回率等指标。所有这些以及更多都可以从混乱矩阵中计算出来。对于多类分类,使用相似的度量标准,但公式略有不同。为了利用预测类别的概率,使用诸如 ROC 和 AUC 的度量。
回归度量
回归度量通常会计算出预测值和地面真实值之间的某种距离,用误差来表示。最常用的回归指标是:
- 均方误差
- 平均绝对误差
- 均方根误差(RMSE)
- 平均绝对百分比误差(MAPE)
- r 平方
推荐系统指标
另一方面,推荐系统和搜索引擎中使用的排名算法有自己的一套衡量标准。其中一些是:
- 平均倒数排名(MRR)
- 命中率(小时)
- 标准化贴现累积收益(NDCG)
- 平均精度
相似性度量
最后,当涉及到无人监督的问题时,相似性度量总是有用的。最常见的有:
- 欧几里得距离
- 余弦相似性
- 莱文斯坦距离
- 雅克卡相似性
还有一些其他指标与计算机视觉项目更相关,如交集超过联合(IoU)和结构相似性(SSIM),其中一些与 NLP 相关,如双语评估替角(BLEU)和困惑(PP)。
操作指标
除了性能指标之外,还有一些其他指标在模型比较过程中也很重要。这方面的一个例子是我们前面提到的网飞 100 万美元奖金。
许多技术人员忘记了一件事,那就是他们正在构建的产品的商业价值。如果一个简单的线性回归模型或几个决策树就可以很好地解决问题,为什么要开发一些繁重的神经网络模型并花费大量资源呢?此外,像我们是否有预算在云 GPU 机器上维护和运行沉重的模型,以及是否值得比更简单的模型高 0.5%的准确性这样的问题的答案也很重要。
因此,我们需要注意一些流行的业务指标:
1 点击率
2 转换率
3 上市时间
4 软硬件成本
5 用户行为和参与度
在开发和部署 ML 模型之前,我们需要记住一些技术需求,比如计算时间和基础设施支持。例如,一些 ML 模型可能需要比生产中可行的更多的时间来训练。或者,使用 R 开发模型并不是集成到现有 MLOps 管道中的最佳选择。
最后,我们必须指出在部署 ML 模型之前进行测试的重要性。这是捕捉生产中可能发生的错误的好方法。最常用的测试包括:
- 冒烟测试–运行整个管道,确保一切正常。
- 单元测试–测试项目的独立组件。
- 集成测试–确保项目的组件在组合时能够正确交互。
ML 验证技术
为了实现一般化并且不过度拟合数据,应用兼容的验证策略是很重要的。这对于防止新数据输入的性能下降是必要的。
为了实现欠拟合和过拟合之间的平衡,我们使用不同的交叉验证策略。交叉验证是一种统计方法,用于在 ML 算法投入生产之前对其进行性能评估。一些最受欢迎的是:
1 坚持(列车试运行)
2 K 倍
3 留一手
4 分层 K 折
5 嵌套 K 折
6 时间序列 CV
Time series cross-validation | Source
有时候,正确地实现一份简历是很棘手的。我们需要避免的常见错误有:
- 对于 k 倍 CV ,使用不同的 k 值进行灵敏度分析,以观察结果在不同验证中的表现。
- 倾向于分层验证,以便在每个文件夹中有平衡的类。
- 注意数据泄露。
- 对于时间序列,不要验证过去的数据。
如何在生产中部署新的 ML 模型?
ML 模型部署是将模型集成到现有生产环境中以做出实际业务决策的过程。ML 模型几乎总是需要部署来提供商业价值,但是不幸的是,大多数模型从来没有投入生产。部署和维护任何软件都不是一项简单的任务,部署 ML 解决方案会带来更多的复杂性。正因为如此,MLOps 的重要性上升了。
我们使用的模型部署策略有可能将我们从昂贵的和不想要的错误中拯救出来。这对于 ML 系统尤其重要,在这种系统中,检测生产中的数据或模型错误可能非常困难,并且可能需要大量的“挖掘”。此外,在许多情况下,精确复制生产数据输入可能很困难。
为了缓解这些问题,并确保新模型在各个方面都优于旧模型,创建了一些部署策略。它们中的大部分来自一般的软件行业,但是为了 ML 的目的稍微修改了一下。在本教程中,我们将解释 ML 中一些最常用的部署方法。
影子部署
影子部署是一个概念,不仅在 ML 中使用,而且在一般的软件开发行业中使用。这是一种部署策略,我们在实时部署之前将应用程序部署到单独的环境中。影子部署通常被公司用来在向公众发布应用程序之前测试它们的性能。这种类型的部署可以在小规模和大规模上进行,但在部署大型应用程序时尤其有用,因为它们有很多依赖项,容易出现人为错误。
影子部署的优势
随着影子部署,我们将能够测试一些事情,如:
- 整个管道的功能——模型收到预期的输入了吗?模型输出结果的格式是否正确?整个过程的延迟是多少?
- 模型的行为,以防止在实际生产中出现意外和昂贵的决策。
- 与实时模型相比,阴影模型的性能。
即使从一般的角度来看,在生产环境中进行测试也比在 ML 中使用沙盒或登台环境有很多好处。例如:
- 在非生产环境中创建真实的数据是一项非常复杂的任务。对于更复杂的输入数据,如图像、流数据和医疗记录,为非生产环境创建包括所有可能的边缘情况的测试数据几乎是不可能的。
- 对于具有许多节点和集群机器的复杂设置,在非生产环境中测试相同的基础设施将是昂贵的,并且可能不值得。
- 维护非生产环境需要额外的资源。
- 对于实时 ML 系统,逼真地复制数据流量和模拟模型的频繁更新是一个挑战。
- 最后,如果 ML 模型在非生产环境中的行为和预期的一样,这并不意味着它在生产环境中的行为也一样。
影子部署怎么做?
在应用程序级别,影子部署可能以简单明了的方式非常简单地实现。基本上,这是一个代码修改,将输入数据发送到 ML 模型的当前版本和新版本,保存两个版本的输出,但只返回当前版本的输出。在性能很重要的情况下,比如实时预测系统,最佳实践是异步传递输入和保存输出,首先是生产中的模型,然后是新模型。
与应用程序级别相反,在基础架构级别,影子部署可能有一些复杂的元素。例如,如果一些服务进行外部 API 调用,那么我们需要确保它们不会在两个模型中重复,以避免速度变慢和额外的开销。基本上,我们需要确保所有应该只发生一次的操作不会触发两次或更多次。如果我们影子部署不止一个新模型,这一点尤其重要,这也是可能的。
在保存了所有的模型输出和日志之后,我们使用一些度量来查看新模型是否更好。如果新型号证明更好,我们就安全地更换旧型号。
A/B 测试
A/B 测试是一种基于统计数据做出业务决策的技术,它被广泛用于测试给定特性相对于旧特性的转换率。在部署策略的情况下,想法是有两个独立的模型,即 A 和 B,它们有两个我们想要测试的不同的特性或功能。当部署具有新特性或功能的模型时,用户流量的子集在特定条件下被重定向以测试该模型。
除了转换率,公司还使用 A/B 测试来衡量其他业务目标,例如:
- 总收入
- 用户参与度
- 每次安装的成本
- 流失率和其他。
为了对这两个模型进行无偏见的测试,应该谨慎地在它们之间分配流量。这意味着两个样本应该具有相同的统计特征,这样我们才能做出正确的决定。这些特征可能基于:
- 人口属性,如性别、年龄、国家等
- 地理定位
- 浏览器 cookies
- 技术类型,如设备类型、屏幕大小、操作系统等。
与影子部署相反,A/B 测试通常只用于测试一个单独的功能,以了解其真正的贡献。例如,模型中新特征的存在。它不适合一个有多种变化的新模型,因为我们无法确切知道哪个功能正在影响性能,以及它的贡献有多大。
A/B 测试的好处
对于模型中的简单更改,A/B 测试比影子部署要方便得多。此外,A/B 测试和影子部署之间的主要区别在于,A/B 测试中的流量在两个模型之间分配,而在影子部署中,两个模型使用相同的事件进行操作。这样,A/B 测试消耗的资源至少减少了两倍。
如何对 ML 车型进行 A/B 测试?
第一步是确定我们希望实现的业务目标。这可能是我们上面提到的指标之一。
下一步是定义测试的参数:
- 样本大小——用户流量如何在 A 和 B 模型之间分配?比如 50/50,60/40 等。
- 测试持续时间——定义达到测试预期显著性水平的截止日期。
之后,我们需要做一些架构上的改变。一个好的方法是在用户请求和模型之间增加一个额外的抽象层。这一路由层负责将流量定向到托管在不同环境中的两个模型。基本上,路由层接受传入的请求,然后根据我们定义的实验设置将它们定向到我们的一个模型。所选模型将输出返回给路由层,路由层将输出返回给客户端。
One good A/B architecture | Source
金丝雀部署
canary 部署的思想是向新模型发送一小部分请求,以验证它是否如预期的那样运行。仅使用一小部分流量,我们就能够验证新模型,检测潜在的错误和问题,而不会对大多数用户造成伤害。一旦我们确定新模型按预期工作,我们就可以逐渐增加流量,直到整个流量不切换到新模型。
总之,canary 部署可以分为三个步骤:
- 将流量的一个小的子样本导向一个新的模型。
- 验证模型是否按预期工作。如果没有,请执行回滚。
- 在将所有流量释放到新模型之前,重复前面的两个步骤,直到所有错误都得到解决并且验证完成。
通常,当测试没有很好地实现或者对新模型没有信心时,使用这种技术。
金丝雀部署的优势
Canary deployment 提供了一种根据生产中的真实数据测试新模型的简单方法。与影子部署相比,canary 部署不要求所有流量都流向两个模型,正因为如此,它在模型推理资源方面便宜两倍。在失败的情况下,它只影响一小部分流量,如果实施得当,不会造成重大伤害。
金丝雀部署怎么做?
首先,我们需要定义 canary 部署将选择多少用户,在多少个阶段,以及 canary 部署的持续时间。与此同时,我们必须计划如何挑选用户的策略。一些可能的选项包括:
- 随机用户选择
- 按地区-将金丝雀部署到一个地理区域。
- 早期采用者计划——让用户有机会作为测试者参与金丝雀测试。
- dog fooding——首先向内部用户和员工发布 canary 模型。
之后,我们需要指定我们将要使用的度量标准以及成功的评估标准。最佳选择标准可以结合几种不同的策略。例如,脸书首先向员工部署金丝雀,然后向一小部分用户部署。架构部分非常类似于 A/B 测试。我们需要一个路由层来控制模型之间的流量。此外,当第一只金丝雀的输出被分析时,我们将决定我们是否应该增加流量的百分比或放弃新的模型。
功能标志
特性标志,也称为特性切换,是快速安全地发布新特性的强大技术。特性标志的主要目的是打开或关闭功能,以便通过将代码部署与特性发布分开,在生产中进行安全测试。
其思想是将新模型或功能的代码集成到生产代码中,并使用功能标志来控制模型的流量,而不是花费资源来构建新的独立基础设施或额外的路由层。功能标志可分为不同类别的切换,其中主要类别有:
- Release toggles–开发人员在主分支中生成一个 Release toggles,让他们的代码在工作时保持非活动状态,而不是创建一个具有新特性的分支。
- 实验切换–用于简化 A/B 测试。基本上,是集成到产品中的代码的一部分,用于划分模型之间的流量。
- 操作开关–用于关闭功能。例如,如果不满足某些条件,操作开关会关闭我们之前部署的新功能。
- 权限切换-旨在使某些功能对特定用户子集可用,如高级用户等。
功能标志的好处
由于它们的简单性,当我们需要快速部署新的变化到我们的系统时,特性标志是有用的。在大多数情况下,它们是临时的解决方案,应该在变更测试完成后删除。
一旦实现,特性标志不仅可以由工程师和开发人员控制,也可以由产品经理、销售团队和市场团队控制。有了特性标志,就有可能在不回滚代码的情况下关闭在生产中意外执行的特性。
如何实现特征标志?
功能标志的范围从简单的 if 语句到更复杂的决策树。通常,它们直接在项目的主分支中实现。部署后,可以使用配置文件控制功能标志。例如,可以通过修改配置文件中的特定变量来关闭或打开操作标志。此外,许多公司使用 CI/CD 管道来逐步推出新功能。
示例:影子部署
作为一个例子,我们将展示如何影子部署一个简单的 ML 应用程序。首先,让我们在 AWS EC2 上部署一个简单的基于情感分析转换器的模型。该模型将从 IMDB 拥抱面部数据集中随机接收文本段落,并将它们分类为积极情绪和消极情绪。情绪的结果将保存在 AWS S3 桶中。
创建 EC2 实例的步骤:
- 转到 AWS → EC2 →启动实例
- 选择名称、实例类型,并为登录创建新的密钥对。
- 单击启动实例
创建 S3 时段的步骤:
- 转到 AWS →亚马逊 S3 →桶->创建桶
- 写入存储桶名称,并可选地启用存储桶版本控制。单击创建一个存储桶。
为 S3 访问创建 IAM 用户的步骤:
- 转到 AWS → IAM →用户->添加用户
- 填写用户名,并在 AWS 访问类型下,选择“访问键-编程访问”,然后单击权限选项卡旁边的。
- 选择以下策略“AmazonS3FullAccess”
- 单击“下一步”按钮两次,然后单击“创建用户”。现在,将出现用户凭证,请确保下载并保存它们,因为您将无法再次看到它们。
为了连接到创建的实例,请转到 EC2,单击 Instances,然后单击 connect。
Instructions on how to connect to the instance | Source: Author
将出现如何连接到实例的说明。可以通过浏览器连接 EC2 实例,但是通常我们使用 SSH 连接从本地机器进行连接。在这种情况下,它是
ssh -i "sentiment_analysis.pem" ec2-user@ec2-54-208-121-4.compute-1.amazonaws.com
其中“情绪分析. pem”是我们之前创建的登录密钥对的路径。
在这个例子中,我们使用一个 EC2 Red Hat Linux 实例,在连接到该实例后,我们需要更新包并安装 python 和 git。
sudo yum update -y
sudo yum install python3 -y
sudo yum install git -y
此外,我们将使用 python 环境直接在机器上运行我们的项目。为此,我们需要安装 virtualenv 并创建一个环境。
pip3 install --user virtualenv
virtualenv venv
为了从 EC2 机器访问 S3 存储区,我们需要使用命令安装 AWS CLI
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
并使用配置凭据
aws configure
在这里,我们需要输入在创建 IAM 用户步骤中下载的凭证中的访问密钥 ID 和秘密访问密钥。要测试 S3 访问,请使用命令
aws s3 ls
之后,我们需要克隆项目,安装需求并运行我们的主脚本。可以使用 cron 作业将脚本部署到生产环境中,方法是设置它将被执行的确切时间,或者如果它是一个正在进行的进程,则使用“nohup”命令。
要设置 cron 作业,请使用命令
crontab -e
按“I”进入插入模式并写入
* * * * * cd ~/sentiment_analysis_neptunel/src; ~/venv/bin/python ~/sentiment_analysis_neptune/src/main.py
其中“* * * * *”是一个 cron 模式,可以从https://crontab.guru/.中定义,路径“~/情操 _ 分析 _neptunel/src”是我们需要运行主脚本的地方,“venv/bin/python”是我们使用的 python 环境。之后,按 ESC,然后按:wq,然后按 ENTER。要仔细检查创建的 cron 作业,请使用命令–
crontab -l
要使用“nohup”运行 python 脚本,请使用命令激活您的 python 环境“venv”
source venv/bin/activate
然后跑
nohup python main.py > logs.out &
我们的主脚本看起来像
if __name__ == '__main__':
data_sample = get_data()
run_model(data_sample)
其中“get_data”函数准备数据样本,围绕模型和预测的整个逻辑由“run_model”函数完成。现在,如果我们想要影子部署另一个模型,可能只需在主脚本中添加一行代码即可:
if __name__ == '__main__':
data_sample = get_data()
run_model(data_sample)
run_shadow_model(data_sample)
其中函数“运行影子模型”运行新影子模型的所有逻辑。模型异步运行,首先是生产中的旧模型,然后是新的影子模型。此外,函数“get_data”只被调用一次。如果在“运行”函数中没有外部 API 调用,这种架构可能会工作得很好,这样我们就不会重复它们。
App architecture | Source: Author
在我们确保影子模型顺利运行,没有任何错误和预期的延迟之后,我们需要比较实时和影子结果。这种比较基于我们在开始时提到的一些指标。如果两个模型都有监控系统,可以使用现有的监控系统在线进行比较,也可以离线进行比较,离线时可以对结果或附加日志进行更深入的分析。如果阴影结果更好,我们用阴影模型替换真实模型。
这个项目的全部代码可以在这个库中找到。
结论
在本文中,我们讨论了在生产中确保新模型优于旧模型的所有步骤。我们已经描述了从开发到部署的所有阶段,其中我们将新模型与生产中的模型进行比较。这是必要的,因为只在一个阶段比较模型会留下一些错误和问题的可能性。除此之外,我们提到了几个可用于比较的指标。
主要的一点是,仅仅比较开发中的模型是不够的,还必须有一个可靠的部署策略,以确保从业务/用户的角度来看,新模型确实比生产中的模型更好。
参考
enes zvornianin
Enes 是一名拥有三年多经验的数据科学家。Enes 在数学、计算机科学和机器学习方面有很强的背景,并且热衷于学习和探索与机器学习相关的任何领域。你可以在 Linkedin 上和他联系。
阅读下一篇
Continuum Industries 案例研究:如何跟踪、监控和可视化 CI/CD 管道
7 分钟阅读| 2021 年 8 月 9 日更新
Continuum Industries 是一家基础设施行业的公司,希望自动化和优化线性基础设施资产的设计,如水管、架空传输线、海底电力线或电信电缆。
其核心产品 Optioneer 允许客户输入工程设计假设和地理空间数据,并且使用进化优化算法来寻找可能的解决方案,以在给定约束的情况下连接 A 点到 B 点。
首席科学家安德烈亚斯·马莱科斯(Andreas Malekos)致力于研究人工智能发动机,他解释道:
“建造像电力线这样的东西是一个巨大的项目,所以你必须在开始之前获得正确的设计。你看到的设计越合理,你就能做出更好的决定。Optioneer 可以在几分钟内为您提供设计资产,而成本只是传统设计方法的一小部分。”
但是,创建和操作 Optioneer 引擎比看起来更具挑战性:
- 目标函数不代表现实
- 有很多土木工程师事先不知道的假设
- 不同的客户给它提出完全不同的问题,算法需要足够健壮来处理这些问题
与其构建完美的解决方案,不如向他们展示一系列有趣的设计选项,以便他们做出明智的决策。
引擎团队利用来自机械工程、电子工程、计算物理、应用数学和软件工程的各种技能来实现这一目标。
问题
无论是否使用人工智能,构建一个成功的软件产品的一个副作用是,人们依赖它工作。当人们依赖您的优化引擎做出价值百万美元的基础设施设计决策时,您需要有一个强大的质量保证(QA)。
正如 Andreas 所指出的,他们必须能够说,他们返回给用户的解决方案是:
- 好,意思是这是一个土木工程师可以看到并同意的结果
- 更正,这意味着计算并返回给最终用户的所有不同工程数量都尽可能准确
除此之外,该团队还在不断改进优化引擎。但要做到这一点,您必须确保这些变化:
- 不要以这样或那样的方式破坏算法
- 实际上,它们不仅改善了一个基础设施问题的结果,还改善了所有问题的结果
基本上,您需要**建立适当的验证和测试,**但是团队试图解决的问题的性质带来了额外的挑战:
- 您无法自动判断算法输出是否正确。这不像在 ML 中,你已经标记了数据来计算你的评估集的准确度或召回率。
- 您需要一组示例问题,代表算法在生产中需要解决的那类问题的。此外,这些问题需要被版本化,以便尽可能容易地实现可重复性。
使用 Kyle Morris 在 GPU 上部署 ML 模型
原文:https://web.archive.org/web/https://neptune.ai/blog/deploying-ml-models-on-gpu-with-kyle-morris
这篇文章最初是 MLOps Live(T1)的一集,这是一个互动的 Q(T2)环节,在这里,ML 从业者回答来自其他 ML 从业者的问题。
每集都专注于一个特定的 ML 主题,在这一集里,我们和来自 Banana 的 Kyle Morris 谈论了关于在 GPU 上部署模型的事情。
你可以在 YouTube 上观看:
视频
或者作为播客在以下位置收听:
但如果你更喜欢书面版本,这里有!
您将了解到:
1 开始部署 GPU 之前需要知道的事情
- 2 GPU 工具及其实用程序
- 3 围绕 GPU 的常见误解
- 4 充分利用 GPU
- 5 最佳 GPU 用例
- 6 使用 GPU 管理权衡
- 7…等等。
- Sabine: 大家好,欢迎来到 MLOps Live。这是与我们今天的嘉宾凯尔·莫瑞斯的互动问答环节&。谁是今天这个话题的专家,就是在 GPU 上部署模型。凯尔,让你暖和一下。你如何解释在一分钟内在 GPU 上部署模型?
凯尔·莫里斯:是的,好问题。
我会说这感觉类似于在 21 世纪初部署一个网站。当我开始我的职业生涯时,没有基础设施来做这件事。我们已经建立了许多工具来使网站上线,并能够处理诸如可扩展性和平衡流量之类的事情,部署在不同的国家。一旦你用 GPU 做事情,基础设施就不存在了。我会称之为非常相似的底层基础设施,直到你深入了解并意识到它还没有建成。
当你问自己为什么会意识到有很多独特的延迟边缘情况。我认为 GPU 的游戏名称是延迟。缓慢的启动时间,如果你在做机器学习,缓慢的推理,诸如此类的事情是阻碍市场的原因。生产环境中的延迟越快,托管成本越低,世界就越容易访问它。成本和速度是阻碍生产基于 GPU 的系统的两个因素。我认为这是与传统系统的主要区别。
部署 GPU:开始之前要知道的事情
斯蒂芬:再问一个问题,你希望自己在创业时知道的三件事是什么?关于部署 GPU 的事情,通常只是使用基于 GPU 的模型?
凯尔:有两件事我希望一开始就知道。一个是集装箱化,在这方面非常精通。使用 Docker,Kubernetes,Pulumi,设置并能够容器化依赖 GPU 的应用程序。知道了如何设置 CUDA 驱动程序,你会花很多时间去做。假设你是一个早期的初创公司,你正试图部署一个生产应用程序,你不熟悉那些工具,你对 GPU 几乎没有希望。
第二件我觉得很不直观但很有趣的事情是,你用来做机器学习的应用程序主要是为训练而构建的。 Pytorch 、 TensorFlow ,这些都是研发工具,还有 Flask ,你要设置的很多服务器,你都将处于开发模式。人们有一个很大的误解,就是他们带着开发工具去生产,他们没有意识到…
举一个具体的例子,我们有多少次客户试图给我们生产应用,他们没有启用 GPU。他们已经在 GPU 上启动了,但他们实际上只是在使用 CPU,他们甚至没有意识到他们没有这样做。然后,当您走到引擎盖下时,您意识到您的 Pytorch 脚本正在 CPU 上部署。诸如此类的小事,但当它深入下去,你会意识到这些工具并不是为快速运行这些事情而构建的。这就是我一直以来的观点,意识到我们需要一套全新的工具来部署生产 GPU 应用程序。
Stephen: 你谈到了这些工具中的大部分都是为训练自己而优化的。在我们深入探讨其他领域之前,我只想简单介绍一下这些工具。例如,您用于部署的工具是什么?它们有多相关?考虑在 GPU 上部署时,我是否需要学习一些原则?
Kyle: 我认为从任何编程的角度来说,理解你正在运行的硬件都是非常重要的。我的职业是机器人工程师。在此之前,我从事自动驾驶汽车的工作,如果你不了解硬件是如何执行的,你就无法利用速度优化的优势。这与人们一开始没有意识到他们部署在错误的硬件上有关。
GCP 上的 GPU 机器,或 AWS 上有一个 CPU。人们没有意识到他们甚至没有利用这个系统。一旦你做到了,你需要意识到 GPU 有一种不同的读、写和使用内存的方式。您可以做很多事情来大大提高模型的速度,比在训练环境中要快得多。我认为对 GPU 内存与 CPU 内存的工作原理有一个基本的了解,只是对操作系统有一个基本的了解,会给你一个新的视角。意识到这不仅仅是引擎盖下的计算,如果你认真尝试对生产机器学习进行压力测试,你会想要挖掘不同的提取,如 GPU 应用程序。
生产中的 GPU 与 CPU
**斯蒂芬:**对。在计算方面,你认为团队在部署 GPU 和 CPU 时应该了解的最大区别是什么?
凯尔:是的。我认为最重要的是你正在使用的 GPU 驱动程序,并了解它们是否针对 ML 设置进行了优化。你真的在快速地加载和卸载一个 GPU 吗?例如,在我所做的工作中,我采用了需要 30 分钟加载的模型,并且我将它们优化为在 10 秒内加载。然后人们会说,“这不可能。”这就像,“不,你还没有打开引擎盖,意识到你正在像在 CPU 上一样按顺序加载它,而 GPU 不是这样工作的。你可以做这些新的事情。”我真的认为对内存接口的理解是一个很大的区别。
当你看一台计算机时,你有处理,就像一个单元,你有从内存读取的操作系统,但然后是 GPU 和 CPU,根本的区别是指令中的并行性。了解您是否真正充分利用了并行性。我建议你深入研究那些可以让你可视化 GPU 使用的工具,比如监控软件,基本上是为了真正看到你正在利用你正在使用的这个昂贵的硬件。
同样,为了将堆栈附加到它上面,我已经…
我在 ML 主机领域,我和几十个人一起工作过,90%的人没有利用 GPU——超过一半,他们没有意识到这一点。即使专家喜欢来自特斯拉、克鲁斯和汽车公司的人,他们仍然没有利用这一点。大多数 CPU 工具都是为了利用我们已经拥有多年的 CPU 而构建的。有了 GPU,还没有大量的生产机器学习。这只是,这只是开始成为一个大事情,所以这就是大优势所在。
围绕 GPU 的常见误解
Stephen: 您还发现人们会犯其他错误吗,尤其是在理解他们如何利用或不利用他们在 GPU 上的部署时?
Kyle: 我之前说的不实际使用 GPU 是最大、最昂贵的错误。人们将自动扩展到 10 个 GPU 来处理流量。他们会过来对我说,“嘿,我需要更快地做出推论。”然后,我会意识到您正在使用一个 CPU,但他们已经部署在一个 GPU 上,碰巧他们使用的 CPU 更快,所以他们获得了 20%的速度提升。他们认为这就是 GPU 的力量。然后我们会说,“不,实际上在 GPU 上正确地运行这个并启用并行”,就像一个较低的级别。
如果你不熟悉 Python 全局解释器锁,我认为另一个模块是……它确实很具体,但这阻碍了许多 ML 应用程序,因为在 Python 语言中,大多数机器学习应用程序现在都是用 Python 编写的,它禁用了真正的并发或真正的并行。如果你知道如何把一些东西移植到 C++,或者另一个就像……我没有和 Golang 在机器学习或 infra 方面合作太多,你可以拥有真正的并行性。我说的是 30 倍的速度提升,不是 2 倍,3 倍。我的意思是,比如 10x,30x,32x,具体来说,基于 GPU 的大小。
你可以做很多很酷的事情。这需要努力,但没错,这是一个大障碍,人们通常不会意识到。那他们就不会堕落到承认这一点。他们只是认为,“哦,硬件一定很慢”。我认为一个常见的错误是人们过早地指责硬件。
他们没有意识到,如果你知道如何破解,GPU 硬件是非常强大的。如果你是一个新的工程师,我会看到的典型情况是,他们会尝试 CPU,就像这样,“我需要更快。扔在一个 GPU 上。”
他们意识到他们甚至没有使用它,或者他们没有意识到,然后他们会说,“我需要更快,使用 TPU”。他们只是使用这种每月 3000 美元的硬件,并在其上投入开箱即用的东西。我想重点是,如果你深入研究,你可以获得 10 到 30 倍的改进。这需要工作,这就是为什么我试图民主化,我想开始建立那里的工具。那是我的焦点。我在做,这样别人就不用做了。如果你在前沿领域遥遥领先,比方说,你在一家大的 ML 公司工作,但那里什么都没有,那就是你能创造很多价值的地方。
充分利用 GPU
Stephen: 在回答社区问题之前,我会稍微深入一点。使用 GPU 的主要目的当然是为了加快推理时间。您首先会做什么,尤其是考虑到您希望优化正在进行的任何部署时?无论是从软件端还是硬件端?
凯尔:是的。第一件事是了解你在什么硬件上运行,以及该硬件的基本限制是什么。其次,了解你使用了多少,并知道如何使用调试器。对于 CPU,对于大多数代码,如果你在做 Python,你可以做第三步调试。一旦你开始使用 CUDA,在这个级别上,许多人不再看引擎盖下面,他们说,“哦,那是 CUDA。不是我的事。”可能这个社区有点不一样。
给自己一个周末的时间,就像这样,我要成为一名 GPU 工程师,一头扎进 CUDA。不要把它和一个结果联系在一起,只是强迫自己进入一点点的杂草中。了解 CUDA 如何分配内存,以便能够使用…即使最基本的命令行工具是 NVIDIA-SMI。然后能够理解如何在 GPU 上进行相当于步骤 3 的调试,并查看使用了多少内存。
一个好的第一步是什么是我的…假设你正在运行一个 ML 推理。这是一个很常见的方法,如果我把这个给每个人,我会说,“试试这个”。你们中的一半人可能会找到更好地使用 GPU 的方法。这个东西将运行你的应用程序。假设是一个 ML 服务器,看看有多少 GPU 内存。然后,只需对自己思考“我首先使用的是完整的 GPU 吗?”然后意识到可以并行加载东西。这是一个巨大的优势。
然后你会开始意识到有很多基础设施阻碍了内存虚拟化。其实很难做到。还有这些深层的技术问题。我并不是说这些都是容易的,快速的胜利,但是如果你真的想在这些系统上推动大的改变,那是你应该开始的地方。只是理解,我是在使用所有的 GPU 能力,还是有更多的可用?然后你可以开始做批量推理,这样你就可以调整你的模型。希望我使用的是以 ML 为中心的。我假设那是观众,但是如果你正在做 ML 工作负载,你可以开始批量处理输入,然后你可以说,开始。
到目前为止,我有需要 3GB 内存的型号。我开始批量处理。我基本上是并行进行推理,现在我使用 12GB 的内存。还是一个 GPU,除了做更高的吞吐量。这意味着推理之类的成本降低了 4 倍。这一切都始于理解如何调试你正在做的事情。如何真正打开它,看看发生了什么,然后问问题。
你调试得越好,你调试的工具就越好,这些显而易见的东西就会越快出现。人们是聪明的,你会看到什么是错的。但如果没有调试工具,一切都只是黑匣子。那么 GPU 就是这个用数字做事的无定形盒子。你只是无法利用他们提供的性能。
浏览当前的 ML 框架
**斯蒂芬:**对。稍后我们将回到理解和工具上来。我想我们有几个来自社区的问题。
**萨宾:**是的。凯尔,你肯定已经提到这个了。Pietra 在 chat 中还提到,在 TensorFlow 这样的 ML 框架出现之前,你必须在底层用原生 CUDA 编码。开发起来更困难,需要更多的时间,但是你有很多的控制力和能力来优化你的代码。他想知道,在当前的框架下,你真的能做些什么来使推论更快?什么是典型的瓶颈,你能做些什么?
是的,我可以说你肯定可以。我正在做一个名为 banana.dev 的项目,主要是为了生产而优化 ML。一个例子是,我们让 GPTJ(一个非常大的变压器模型负载)快了近 100 倍。仅仅是通过开放库,在引擎盖下破解一些东西,并开始问一些简单的问题,比如“我们如何分配内存?这是我们能做的最好的吗?这个操作系统允许我们做什么?”所以,你肯定可以。是的,我同意。刚开始编程的时候,我是用 C++从头开始写渐变下降的。我知道这些新的抽象已经消除了这一点。
所以你不再问自己这些问题,但是从 Python 的角度你可以做很多事情。在一定程度上,你必须开始降低到 C++的全局解释器锁之下,因为要实现真正的并行,你肯定可以做到。我认为区别在于训练优化和生产推理。这些是非常不同类别的优化模型。训练更多的是关于机器之间的并行,你如何更快地收敛到一组重量?而生产推理就像,你如何向前传递?
首先,培训是向后传递,生产是向前传递。非常相似的事情,除了在生产中,你试图最小化你使用的计算量。在训练中,你会问,我如何最大限度地提高计算并行性,以便更快地进行训练?你只需要同时做一堆这样的事情。更多的是关于培训的吞吐量优化。在生产中,它是关于单个呼叫延迟和每次呼叫的价格。有一整套的东西,只要想想大多数人。您就培训优化与生产进行了多少次对话。就像人们还没有真正探索它一样。我看到还有第二个问题,但是…
GPU 适合实时推理吗?
萨宾:是的,没错。这第二个问题正是关于在生产中使用 GPU 进行推理。问题是,它只是用于批量预测,还是真的可以用于近实时?例如,在引擎盖下使用 GPU 的 REST API 端点。
Kyle: 是的,我再次假设,这意味着机器学习推理,并考虑使用 GPU 生产。这个问题取决于您的用例。通常,我可以说,我已经从 CPU 到 GPU 完成了大约 50-100 个项目。根据推理,你将看到的平均加速是通过 GPU 运行的 3-8 倍,就像现有的框架一样。您将更快地看到端到端延迟,并且您可以使用类似 REST API 的东西。
我多次构建的基本上是一个调用后端的 SDK,它只是一个 rest API。获取一个任务 ID,提取它,然后跟踪该任务。你把它作为一个长期的东西登记在一个数据库里。然后检查该任务的状态,并从推理服务器更新该任务。你有一个中间层。
用 GPU 肯定更快。最重要的是价格。如果你在做类似聊天机器人的事情,大多数人最终需要 GPU 推理,因为你不能…如果客户发送一条消息,需要 20 秒钟来响应,这与三秒钟、五秒钟的记忆有很大不同。这里的问题是,应该考虑用 GPU 做生产吗?是的。你需要考虑的最重要的事情是你的成本。您是否有一个支持成本的应用程序?
我不想无耻地插太多,但我在 Banana 做的大事,我正在做的项目,就是让 GPU 主机更便宜,完全公开。我能说的是,如果你有一个 GPU 应用程序,即使你有无服务器的 GPU,你也可以在不使用时关闭它们。如果使用它们的成本超过了客户交互的成本,你就不会想使用 GPU。
例如,有人进来,他们正在与你的聊天机器人聊天,你正在使用 GPU,他们的聊天时间是 10 分钟。如果这 10 分钟的 GPU 成本超过了客户为您的业务创造的成本或支付的成本,那么您就有负单位经济。我认为主要的障碍不是 GPU 很贵,而是人们总是开着它。主要的障碍是永远在线的图形处理器让你的单位经济变得很糟糕。你需要无服务器的…你可能会减少很多。
我会考虑这些不同的权衡。应该考虑 GPU 吗?当然,这样更快。客户喜欢更快的体验。也许你可以给出一个你可能不想使用 GPU 的边缘案例。我认为,如果您正在处理客户不需要响应的批量工作负载,比如说,在周五晚上,您将运行一个 cron 作业或他们现在的名称,这是一个基本的自动化作业,可以处理大量数据。CPU 可以便宜很多。这对你来说可能是一个不错的选择,但是一旦速度成为一个因素,GPU 肯定应该被考虑用于 ML。
观看与凯尔·莫里斯的另一次精彩谈话:
视频
实时 GPU 使用技巧
斯蒂芬:是的,我会跟进这个问题。一名社区成员向我们提出了一个问题。因此,这个特殊的团队过去常常通过他们的批处理工作流来运行 GPU 推断。现在,他们正在转向更实时的工作流程,因为这是业务发展的方向。这是更好地为他们的用户服务的东西。团队现在询问您在使用 GPU 实时节省成本以及优化资源方面有什么建议。我是说,这就是我们目前为止所说的。也许是更具体的东西。
凯尔:对不起。首先,我想澄清一下,当你说批处理时,你的意思是有两种类型的批处理。一种是批处理,你的电话在一周的某个时间打进来,你可以一次处理所有的电话。那么第二次批处理就是并行推理。你实际上是在向你的神经网络发送更大的有效载荷。我假设这需要后者,也就是你同时处理多个入口。就像你发送一个更大的有效载荷,然后问题是,如果你想把它像单独的调用一样分散,你不需要做这个庞大笨重的调用。你如何使它实时,这是我对这个问题的理解。
如果你想加快速度,我要考虑的主要事情是为你的用例重写内核,所以思考 GPU 所做的底层主要操作就像是网络的内核乘法,很多时候,我发现这一点。同样,有一种误解,认为你使用的工具是完美优化的,一旦你进入生产推理,你需要挑战这个假设。
你需要意识到,如果你深入了解——例如,我已经进入了最先进的图书馆,查看了他们的 GPU 所使用的内核。我会说,“嘿,这里有一个更好的方法来做矩阵乘法,”然后建立像 2-3x 这样的推理。我得说这是一个立竿见影的好方法。是的,它是这样的,因为你试图成为一个单一的调用速度内核,像乘法是最好的方式,或者尝试具有更快时钟周期的硬件,诸如此类,因为如果你不做批处理,那么这些都是你的选择。
如果你愿意沿着 JAX 的道路走下去,开始进行即时编译并查看你使用的硬件,即使是 CPU 也是值得考虑的,但我认为如果你想要 2 倍的速度,内核重写将是最容易实现的。那也许能让你实时。
最佳 GPU 用例
Sabine: 是的,我们确实有一个关于 GPU 用例的问题。你在哪里看到最好的用例?显然,ML 训练和推理,尤其是神经网络,但是对于一些数据处理工作流或类似的东西是否也有好处?约书亚在问。有哪些最好的用例?
在我看来,我还是不知道真相。我希望你去发现你认为最好的,因为有很多东西要学。我所看到的是,视频处理是仅次于 banana.dev 的客户。这是他们来找我们进行视频处理的地方,他们没有使用机器学习,他们只是试图做基本上,我不能进入太多的细节,但基本上处理大型视频和做搜索之类的事情,没有神经网络,这只是传统的处理,但在 GPU 上你可以做得很好,因为你可以开始抨击帧,你可以比 CPU 快 10-30 倍。
我在想还有什么。机器人感知,我的意思是,这是我以前在克鲁斯时研究的。处理现场。同样,很多都是在引擎盖下进行的机器学习,但基本上,快速处理复杂丰富的场景就像是 GPU 的事情。视频最终会成为机器人感知,因为如果你在建造一辆自动驾驶汽车,你会不断地拍摄世界,你基本上是在创建一个视频,但你也可以有不同帧的视频,如点云和不同的数据类型。
任何需要像非 ML 那样的高帧率的地方。ML 是预测输出的东西,比如在 bash 过程和传统方法中进行推理。这些是我在实践中看到的主要事情。
无服务器 GPU 的问题
Stephen: 说到基础设施,我们有一个问题,实际上是来自社区提交的。这个人问你怎么看待无服务器 GPU?您在与他们合作时发现了什么问题,他们正计划将其工作流程迁移到无服务器。问题是,他们在考虑无服务器的低延迟容忍度和冷启动问题。
凯尔:我的意思是,这是我的激情问题,我要试着回答正确。基本上,这里的理解是为什么?
Stephen: 你在使用无服务器 GPU 时发现了哪些问题?
凯尔:是的。第一个问题是它们没有被提供,所以这就是为什么我试图为它们建立一个解决方案,像一些可靠的东西。他们不存在的主要原因,从我的理解,是冷启动一个模型的能力。我可以给你一个例子,如果你要去建立无服务器的 GPU,我可以解释你接下来的三个月基本上会怎样。
这就像如果你从一个模型开始,你想设置自动缩放或什么的。你会发现的第一件事是,配置 GPU 可能需要几分钟时间来访问某些东西。一旦你有一个可用的 GPU,使用 Torch 或 TensorFlow,任何传统的库,加载一个典型的模型可能需要 5 到 20 分钟才能放入 GPU 内存。您需要进入并真正优化模型启动时间。在 Banana,这是我们唯一的焦点。这就是我们如何将启动一个模型的时间从 20 分钟缩短到几秒钟。基本上,如果你能做到这一点,你的推理速度是相同的速度,那么你就可以关闭电脑。
我认为这种类比就像,想象你有一辆车,你知道你可能要去做一次非常重要的旅行,比如说,去医院或者去朋友家什么的,你不知道什么时候,你只知道,在某个时候,你不得不这样做,那辆车需要 30 分钟才能熄火,然后你可能会一直开着车。这就是我们对 GPU 的问题,因为机器学习工作负载需要很长时间,人们只是让他们的 GPU 开着,因为这是保证客户拥有良好体验的唯一方法。
无服务器 GPU 的主要问题是启用它们,延迟,并消除这一点,因为这样你就有了一台永远在线的机器。他们擅长客户体验,除了你节省 90%或更多。我们正在朝这个方向努力。我们已经将它降低了 95%到 99%,但在许多应用程序中仍然不够,如果你有,比如说,一个客户进来,你可以通知 GPU 打开,你有 5,10 秒的时间,但如果你的应用程序需要亚秒,它还不存在,这是非常困难的。
我可以解释为什么这很难,但如果你想在一秒钟内启动一台机器,你需要能够在一秒钟内将内存加载到 GPU 上,最先进的固态硬盘的加载速率为 3-4GB/s,所以这就像是将内存加载到硬件上的能力有一个理论界限,足够快,可以在不到 5 秒钟内将 20GB 的型号加载到内存中。我们正试图寻找解决方法。这是一个限制,我们可能正在试验分片加载,一次跨多个 GPU 加载,我们正在进行分片推理,这样一来,每个 GPU 只需加载一秒钟的工作,因此在网络中展开各层,这基本上是我们试图解决的问题。
使用 GPU 进行模型维护
Sabine: 然后,Piatra 向我们提出了更多的模型维护问题。让我们假设我们有一个生产模型,由数据科学家手动重新训练,可能每三个月改变一次网络架构、额外功能等。这是否意味着生产代码必须由 ML 工程师手动重写,以便在每次更新时针对 GPU 进行优化?
凯尔:这真是个好问题。只是说,只是权重在变化,还是有其他东西,因为 ML 模型有不同的组件,有代码和权重,基本上,想想看,你只是用某种语言定义了这个网络,然后你就有一堆权重加载到网络上。通常,如果权重发生变化,您不必更改底层代码。权重是最常见的,如果你微调模型,你不必改变底层代码,因此你不必重新优化。
第二件事是,即使权重或架构发生变化,通常情况下,你会希望编写抽象来捕获一组广泛的神经网络,你不会希望为一个网络硬编码你的优化,这通常不是它的工作方式。例如,如果你正在做像 Keras 这样的东西,这是一个非常高级的抽象,他们有什么,他们有一些层 API,如果你在优化它,你希望它能确保任何类型的层通过该 API,被编译成优化的 GPU 代码,或解释什么取决于你在使用什么。通常情况下,您不必对其进行太多更改。
我正试图想出一个例外,因为我认为这比只是说你不必这样做更有价值。我想一个例外是,如果你正在做—在 Banana,我们做了很多关于启动的事情,快速启动机器。一个很酷的例子是,如果您不断改变重量,或者您有许多不同的重量,您需要考虑如何快速存储和加载这些重量,因此存储成为一个实际的瓶颈,这成为您更多问题的来源,就是我在哪里放置所有这些优化的重量,我如何跟踪哪些需要进入瓶子,然后缓存它,使这个过程变得更快?这是花费时间最多的地方,而不是你的代码。
使用 GPU 管理权衡
萨宾:谢谢。马塞洛还有一个问题。正如您所说,在进行推理时拥有低延迟和降低成本之间似乎存在矛盾。如果你想能够足够快地进行推理,内存必须被加载到内存中,并且一直在为它的成本付费,即使是在不使用的时候。有没有解决这个问题的办法,基本上是让 GPU 的延迟和使用费用都很低?
凯尔:是的。我认为这取决于最终客户的体验。我假设每个人都在为客户构建,也许这是一个不正确的假设,但有人在消费你的模型的输出,这是我的假设。如果您的客户需要真正快速的响应,您可以做一些事情,如 GPU 的预测可用性。基本上,速度和成本是相互权衡的,我发现解决这个问题的唯一方法是在需要时让 GPU 可用,即无服务器 GPU,但有两个阵营,无服务器 GPU 仍然需要几秒钟才能启动,所以如果可以的话,对于您的应用程序,我会使用无服务器 GPU,就个人而言,这是节省大量成本的主要方式。
如果您的应用程序需要实时响应,而它何时出现是完全不可预测的,这是另一个未解决的问题,您只需要在成本不变高的情况下更快地做出推断。再说一遍,核仁是一个东西。沿着 ASIC 的道路,创建一个定制电路,在硬编码的网络架构上执行操作,这绝对是另一个角度。
我认为一个简单的方法是尝试预测流量,例如,您的应用程序需要快速响应,并且您有五个始终运行的 GPU,您能找到一种方法让其中一个始终运行,然后在需要时让其他四个自动扩展吗?然后,你可以处理 99%的流量高峰,除了你不用为五台永不停机的机器付费,这是你最省钱的地方。
我想我应该换一种说法,如何在不牺牲延迟的情况下省钱?这是我迄今为止想到的最好的办法。如果你想换一种方式,那就是真正的深度 R&D,解决这些硬件能源瓶颈,这是一样的。在 Cruise,我们正在进入这个领域,进入非常非常低的层次,深入到硬件之下。大多数团队可能不会这样做。如果这里有人对无服务器 GPU 感兴趣,显然,我不知道如何联系,但 DM 我,这是我正在努力做的事情。我很乐意帮忙。
云与本地 GPU
**Sabine:**Sri Kant 向我们提出了一个关于本地与云的问题。例如,您如何看待由 NVIDIA AI 企业软件套件结合 Red Hat OpenShift 或 VMware Tanzu 管理的内部 GPU 集群,而不是由 EKS 管理的相同 GPU 集群的 AWS 堆栈或 Azure 堆栈?
凯尔:我想确定我收到了。他们特别询问现场体验。在 VPC,一个虚拟的私有云,可以访问您的资源,我假设存在隐私问题或其他问题,并且您正在询问多个不同的云。我没有和所有的软件都进行过深入的合作,我使用过 GCP 和 AWS,并对其他一些软件进行过实验。我认为,当你开始使用 Kubernetes 时,需要优化的是,如果你在所有东西上都有一个容器抽象,你基本上可以相当容易地改变云提供商。
我发现有一些令人头痛的问题,但我正在寻找一个提供最容易部署您的应用程序的抽象概念作为第一步,因为我认为大多数人在公司早期遇到的瓶颈还不是延迟或成本,而是他们是否为人们建立了有价值的东西,特别是如果你是一家初创公司,所以我会优化部署快速学习。我注意到的是,在很大程度上,许多提供商平衡了他们的 GCP 在一个领域的成本,但这将为您在其他产品上节省资金。
例如,我不能引用 Azure 的确切数字,但我知道 AWS 上有一组 EC2 实例要贵得多,而 GCP 上没有。这是一个立竿见影的效果,但当你进入后,你会看到网络成本或更多,然后开始正常化。我真的会优化,比如,我会问这样的问题,你的团队熟悉哪一个?您是否使用了使云不可知论者变得容易的抽象?如果不是,那就更成问题了。
如果你不使用像 Pulumi 这样的东西,我会认真考虑的。Pulumi 是我去年发现的最喜欢的工具之一,因为基本上,你可以使用相同的 Python 代码在 GCP 的 AWS 上部署。你不必进入控制台,这样会减少很多决策变量。它专注于在全球范围内为您节省最多时间的决策,比如如何使您的代码云不可知?那么仅仅选择决定也是高风险的。对吗?因为你真正要问的是,哦,所有这些供应商锁定了我,所以我必须做出这个重大决定,因为我知道这很难改变。
如果你去掉这个假设,你就很容易改变。你可以两全其美。你可以做一个多云部署,你可以说对于高 GPU 工作负载,使用 GCP,我认为这是我推荐的一个非常好的选择,不确定 Azure,然后如果你做一些高网络带宽或隐私中心,AWS 有很多好的产品,如 EKS。
削减 GPU 使用成本
Stephen: 好的,在我们进入社区之前,当然,我们一直在说的一件事是成本节约,特别是在 GPU 方面。当然,使用 GPU 的一个关键障碍是价格。你不想有一天醒来,你有几千美元,因为你只是简单地让一个 EC2 实例和你的 GPU 等一切都开着。你节约成本的最佳秘诀是什么?我们谈到了无服务器,这是一方面,或者我可以通过使用 GPU 或部署模型和 GPU 来节省成本吗?
凯尔:这是个好问题。最简单的?我是根据做起来有多难以及能为你节省多少来衡量的。最简单的就是我前面说的,就是看你的模型占用多少内存,放在内存少的 GPU 上。如果可以的话,像这样,你只需要在内部削减成本。这真是太神奇了。
很多推理服务器在 Torch 中都有内存泄漏。很多 Torch 代码都有内存泄漏,比如超过 50%。事实是它一直在你的记忆痕迹中蔓延。如果你能够修复这样的东西,你可以把它保存在一台 GPU 内存更少的机器上。另一个问题是,如何将多个模型打包到一个 GPU 上?这是我们目前正在努力解决的问题。我们正在努力,因为在引擎盖下,这些工具,你可以自然地做到这一点。GPU 内存没有一个可访问的虚拟化层,因此这变得令人头痛,但这将是第二个赌注,就像自然的事情一样。就像,怎么把多个内存的东西放到同一个 GPU 上?
第三,我认为这是如果你愿意牺牲一点点性能,这在我的经验中是大多数团队都不愿意的,但是如果你愿意放弃 1%到 5%的性能量化,那么就像通过将浮点 64、浮点 32 改为 8 位浮点来减少模型权重的大小,你可以将模型大小减少 2-4 倍,并且你牺牲了性能,但是这看起来像是一个非常容易的胜利,我推荐你。我推荐一种混合的方法,所以如果你,再次,我在和种子阶段的 A 轮公司说话,就像早期阶段的产品,但是看看你正在做一个演示应用。
你需要速度。你能对模型进行量化吗?所以好像便宜了四倍。你只需要让它一直开着,你可以把它作为一个演示来提供,然后给那些需要真正高质量的超级用户。向你付费的人,你给他们一个不同的模型,没有那个,有额外的 5%,我会看到很多团队这样做,他们基本上根据客户类型在他们使用的模型之间切换。
我认为,如果你在这方面很聪明,如果你将产品思维和工程思维结合起来,而不是一切都只是工程问题,这就像,你的客户需要什么?你可以开始变聪明了。你可以说,这是前端人员的廉价模型,然后真正掏钱的人,他们得到这个模型。我认为你可以很容易地做到这些事情,你可以削减一半的成本。
使用 GPU 的分布式处理
萨宾:好吧。Ricardo 还有一个问题,您会使用哪些工具或框架来构建一个模型组合,这是一个需要由许多模型处理的推理请求,可能会在不同机器的分布式环境中运行。它们中的每一个都可能具有单独的资源约束、自动缩放策略等等。
Kyle: 有意思,模型链,我试着不要太偏向,因为我有一种方法来做我正在构建的产品,但我试着挑战自己,想想还有什么其他方法可以做到这一点。最简单的抽象是将每个模型视为一个单独的实体,您可以通过抽象掉几行代码来调用它。如果延迟–
让我们来看看目标是一个真正干净的架构的例子。然后你可能想要做的是有一个编排服务,能够发送一个请求给每一个模型,它基本上做一个调用管道。如果假设这些都是大型模型,它们可能运行在不同的服务器上,你基本上需要一个传送带式的过程,像调用一样,服务器将响应插入下一个服务器。
这是一个非常干净的设计,因为这样你就可以在管道的每一步进行日志记录。你将避免 GPU 内存耗尽的混乱,然后优化就会出现,就像,你会有网络延迟,对不对?如果你在所有这些之间做一个网络调用,并把它们链接在一起,那就很容易扩展,因为这样你就可以根据瓶颈自动扩展这个链的各个部分。短期内会容易些。一旦需要长期节省,那么瓶颈就是网络延迟。您可能想要相同的架构,但是如何在同一台机器上打包模型呢?然后,您可以在同一个服务器上调用它们。
香蕉就像是一个中间层。你有一个 Python SDK,你有一个类似 banana.run 或你正在使用的任何 SDK 的函数,它调用这个中间层,然后将它路由到一台机器,如果你有一个模型链,你只需调用六个不同的运行命令,你将它们绑定在一起,然后在幕后,你可以将它们打包在同一台机器上作为性能优化,但最终用户不应该改变他们的代码。
我认为最令人头痛的是,你必须不断地修改应用程序代码,以便与这些新的链式推理服务器一起工作。在用户和这个模型网格之间建立一个抽象将为您省去很多麻烦,因为每次您必须更改应用程序代码时,那都是一个新的轮询请求。这是新的测试,它真的增加了,人们低估了它。
使用 GPU 进行模型推理
**萨宾:**爽。我们对推论有一些疑问。Gagan 想知道像 TFSerb、ONNX Runtime 等推理服务器有多好。帮助我们对付 Q2。例如,将 REST API 包装在一个巨大的模型上,比如拥抱面部变形金刚。
Kyle: 为了澄清,相对于仅仅做那件事或者仅仅是除此之外,这些工具有多少帮助——如果你想为一个模型服务,基本上,这些工具有多少帮助。
萨宾:是的,我想是的。
Kyle: 是的,我认为他们帮助很大的领域是,如果你在一个生态系统中,你试图快速部署一个开源模型,就像它是一个已经拥有所有这些服务基础架构设置的大型存储库的一部分。你可以做得很快。我使用一个叫做 Zeep 的工具。这不是我的,它只是一个很酷的东西,基本上可以让您获取这些报告并快速部署它们。我认为 TFServe,很多这种类型的-他们熟悉其他部署软件,有一个标准接口,更容易设置它,而如果您在像 Flask app 这样的准系统中进行操作,您必须思考这样的问题,好吧,这可以处理负载平衡吗?诸如此类的事情。
那里有帮助。我想我有点偏见,因为我已经陷入了足够多的杂草。我用过 Triton 之类的东西。我们现在开始,至少在 Banana,我们正在构建我们自己的东西,因为我们遇到了自然瓶颈,所以我想应该怎么说呢,如果您是部署基础架构、生产和所有方面的新手,我认为这真的会很有帮助,然后如果您试图比市场上的任何其他地方都更快地打包东西,您试图去别人不去的地方,您可以选择这些工具。
最终,你会在它们下面结束,它们都像 Python,C++一样。在这一点上,它只是运行在 GPU 上的一些位,最终,你开始意识到所有这些框架都只是一些抽象,你失去了以同样的方式将它们视为工具的能力。基本上,作为一个初学者,我会从他们开始,直到,一般来说,我会这样,如果有一个工具可以解决你的问题,使用这个工具,而不是构建它,但如果你有任何真正的可伸缩性需求,你可能最终不得不去引擎盖下。然后,你最终必须在我所在的公司建立硬件。
Sabine: 好的,为了防止对这些推理框架有任何补充,我们有 Ricardo,他有兴趣知道你对这些的看法。像比如说 RayServe,TorchServe,KFserving,还有你说的那个 NVIDIA Triton 推理服务器,有用吗?它们只是增加了不必要的复杂性吗?他们中有谁开始超越其他人了吗?有什么要补充的吗?
Kyle: 是的,老实说,这些我都没用过。我还没有用过 RayServe 。我用过 TorchServe、KF 和 NVIDIA,所以我可以在这些上面发言。就我个人而言,我是《T4》和《海卫一》的粉丝,我认为在制作环境中,我看到海卫一走得相当远。在中,我看到它扩展到数百人的团队和相当大的生产工作负载,我认为像这样的工具有助于它在 NVIDIA 生态系统中,你有内置的 GPU 兼容性,他们已经在内核优化的掩护下完成了一些工作。他们正在努力,所以越来越好了。如果你想要最好的 GPU 兼容性,我认为这将是我的默认选择。
老实说,TorchServe 已经有一段时间没用了,所以我可以根据我被吸引到的地方来谈论它。我不认为我有足够的全球视野来对哪个更好有一个坚定的看法,但我会说 Triton 是推理服务器的一个很好的起点。此外,我想我认为一件大事不仅仅是推理服务器,而是它所部署的基础设施,就像它是一件大事一样。
酷,你可能有一个准系统 Flask 应用程序或一个 Sanic 应用程序或基本上公开一个端口的东西,你可以发出 post 请求,我们正在进行推理。那是一个推理服务器。我认为更大的问题是您将在哪里部署它。这仅仅是在 EC2 实例上运行而没有自动重启吗?这在 Docker 上吗?在 Kubernetes 上吗?您是否正在进行与云无关的部署?这就是可靠性高于单个服务器的地方。
我几乎要缩小范围说,如果你过度专注于这些单独的服务器,你不会从它们那里获得胜利,那么它可能是不必要的复杂性。我在生产中部署的许多应用程序实际上都是 Torch 或 TensorFlow,我们得到了模型,我喜欢将它打包在一个应用程序中。然后,我注意到最大的故障模式来自——想想看,这不是单个服务器。它让你的服务器运行了很多。现在问题变成了自动扩展、冷启动和负载平衡。所有这些都在单个服务器之外。让我们来看看。
如果你从中获得了巨大的回报,那就继续钻吧,说实话,我不会太在意。感觉 GPU 游戏真的变成了低级游戏。有两个阵营。如果你只是尝试部署一些东西,使用一个框架,使用一个工具,走出去,并有可靠性。如果你试图优化一个 GPU 生产工作负载,那么你将不得不放弃这些框架。您可能会向这些提交拉取请求。我们需要更多的人这样做。
**萨宾:**没关系。我们之前确实跟进过这个问题,对于实时推理,你会推荐什么编排框架?
**凯尔:**是的,我显然会选择香蕉,因为我认为这是我们正在努力解决的问题之一。你会有永远在线的机器,但就像我们正在开发一个自助服务工具,就像尝试制作它,所以你只需上传你的模型,然后恢复调用它的能力,它将是实时的,因为它在 GPU 上。它永远在线,它会花费更多。如果您使用无服务器,基本上会有额外的延迟。我想跟进一下。
我还见过其他一些工具。再次,我会推荐 Zeep,如果你想把一堆推理服务器连在一起,我发现这个工具真的很有帮助。它与云无关。您只需点击一个回购,部署它,然后将它们链接在一起,实时性更多地是关于您在什么硬件上运行,以及它是否支持您的使用情形?在我看来,这不是一个真正的框架级别的事情。真正的实时推理是当你的推理足够快时,比如每秒 32 帧或其他什么。你可以在许多不同的框架上这样做,比如你如何实时连接是你推理的速度,这是两个不同的问题。
其他问题
萨宾:好吧。我们可以从聊天中获取一些问题。我们有一个安德烈斯的。您对云中的加密货币挖掘有什么看法吗?在云中部署加密货币挖掘网格并根据哈希算法的复杂性调整 GPU 负载是否可行?
凯尔:我不是密码专家。我很早就在现场,但后来我在过去的十年里一直在做 ML。我可以给出一点背景。是的,你可以。通常,我所看到的是采矿最终没有最大的投资回报,例外是如果你在做与优步相同的模型,即你有一辆未使用的汽车,所以你把它租出去,如果你有一个未使用的 GPU,你为采矿这样做,这可能很酷。
我认为一个非常有趣的使用案例,我很喜欢,如果这里有人构建它,我会成为客户,就是找到那些忘记从云中关闭 GPU 的人,过去,如果你忘记关闭 GPU,用它挖掘一些东西,利用它,这就是一个例子。如果只是部署他们,我觉得是可行的。
我还没有钻够,以了解看哈希率和你的投资回报率是多少,但我已经尝试了采矿的场景。一般来说,你会做一些东西,但必须是非常专注的。从技术上讲,如果你想用香蕉之类的东西来做这件事,你可以部署一个比特币挖矿机。我不知道云提供商是怎么想的,有些人会检查服务条款,但我认为你可以像机器学习一样做这件事。
Sabine: 我们也有一个来自 Marcello 的问题,很多时候,ML 模型可以作为 PyTorch 或 TensorFlow 模型使用,但是当将它们转换为 TensorRT 时,它们的性能会提高。这种情况总是发生吗,还是只适用于某些类型的神经网络?
Kyle: 我不知道,老实说,我对底层工作的了解还不足以胜任,我会鼓励你去经历,我不想说,我基本上知道这一点,但我会假设像循环网络这样的东西,会有更好的优化,因为你可以用循环数来兑现任何东西的权重,但是的,我真的不够了解。我对这些工具的底层还不够了解。我只是猜测,我不想浪费任何人的时间去猜测,如果我知道,我宁愿回答。
Sabine: 很好,我想我们还有时间回答另一个问题,这个问题是 Piotra 在聊天中提出的。当您通过降低浮点精度来缩小模型时,是否遇到过任何数值稳定性问题?
凯尔:这个问题很复杂。我想确保我理解了这个问题。你说的数值不稳定性是指爆炸梯度吗?基本上,你改变了权重,然后突然,输出变成了垃圾,因为通过改变的权重传播计算?你会得到这个的。这是相对于精度损失的渐近行为。我会注意到,从 64 位浮点到 32 位浮点,几乎没有不稳定性,32 到 16 趋于正常,16 到 8,你会开始看到它,然后 8 更少,它只是很快下降,成为垃圾。我不知道它背后的所有数学原理,但在实践中,我会把它视为一个渐近位,一旦接近 8 位精度,它就会有一堵墙。
我认为这也取决于网络大小,就像网络越长,乘法越多,误差通过精度传播的机会就越大。这尤其是一个给你上下文的东西,尤其是在循环网络中的问题。也许我在这里没有正确地使用递归,网络中有反馈回路,如果你在做重复的计算,你在把东西传递给下一层之前,你要多次运行它。基本上,乘法次数越多,误差就会越大。
仔细想想,64 位和 32 位之间的差异非常大,与 8 位到 7 位或 8 位到 4 位相比,这是一个巨大的差距,相对于另一种类型,这是一个巨大的信息损失,所以你会更快地看到这一点。这是非常特别的。我肯定有论文显示了这方面的实际渐近下降。我记得看到过一些。我不认为我有足够深刻的数学理解或数字来让你确切地知道它何时发生。
把它包起来!
斯蒂芬:我们今天已经谈论了很多关于工具的话题。我认为我们应该把它们都集中起来。可能把它们都绑在一起。什么是您部署 GPU 模型的关键工具,您随身携带并觉得有用的工具?
**凯尔:**基本上,就是码头工人,库伯内特,普鲁米。那应该是三个。如果你在一个岛上有三个工具,你必须建立一个生产栈,而你只有这三个工具,那就是我会选择的三个。我知道可能会有一些特定的容器运行时与 Kubernetes 一起工作,如 Containerd,我相信您可能会想探索其他一些容器,但如果您试图做一个生产工作负载,您需要容器编排,因为您需要能够将它连接到前端,像重新启动逻辑等等。这是我最简单的,那三个。
我知道我们的时间不多了,但我还有最后一个问题来总结这一切,把一切都确定下来。我来找你,我在试着优化我的 GPU 模型来进行 like 推理。我来找你,你带我经历你会带我经历的过程,从拥有我的模型到能够在 GPU 上运行实时推理等等。
凯尔:我们有两条路,对吧?我们有自助服务,这是我们现在真正的早期 MVP。你可以尝试一下。我可以跟进一个 git-repo。基本上,你按照一些指示,然后你可以上传你的模型到我们的服务器。你会得到两行你可以调用它的代码。你得到一个 API 模型密钥,这将给你无服务器的 GPU 速度。第二种会帮到你。对于那些不想为计算这些东西而头疼的人,我们可以建立一个 Slack 频道,我们的团队会和你一起工作。
我们仍处于起步阶段,所以我们希望有亲身体验来了解单个客户的痛点。如果后面有分享链接的方法,就像香蕉 ML 和 GitHub 一样。我们有回购协议。这是一条完全自动化的管道。前端 UX 还不多,主要是我们团队不是前端团队。
我们是非常深入的 R&D 工程师,因此如果您遇到任何问题,我们很乐意提供帮助,但我可以说,我们目前提供的通常是 5 到 10 倍的成本降低,因为您不必一直开着机器。我们有像自动驾驶汽车领域的人,我们有音频应用程序,像 GANs 这样的图像生成,以及许多不同类型的应用程序正在运行。很想听听你在做什么。
有没有让人伸手的方法?我不知道,我可以放弃一个 LinkedIn,或者如果你们有它,但基本上这里的任何人,也是非正式的,我喜欢帮助人们解决 GPU 问题。你还有什么问题吗?跟我一拍即合。我很高兴成为一个接触点。这可能是我们最擅长的一件事。我喜欢用它来帮助这个行业。我认为它现在在生产方面非常落后,所以如果它还没有在这次对话中传达出来,我可能会给你几个星期甚至几个月的时间。
**萨宾:**优秀。所以,LinkedIn 是和你联系的地方?是这样吗?也是通过香蕉和松脆?
Kyle: 是的,你可以这么做——我需要仔细检查一下我的 LinkedIn 是什么,但我可以把它放在这里。我认为,就像凯尔·j·莫里斯一样,你可以随心所欲地分享。
Sabine: 是时候结束了。非常感谢你,凯尔,和我们在一起,有你在真是太好了。
Sabine: It is indeed time to wrap it up. Thank you so much, Kyle, for being with us here, it was wonderful to have you.
为最混乱的行业部署数据和 ML 管道:加密的搅动河流
在阿根廷有一句老话是这样说的:“A río revuelto,ganancia de pescadores”。这翻译过来就是“当河水被搅动时,渔民获利”。
2022 年将作为加密生态系统的决定性一年而被铭记。这是出于好的还是坏的原因还不得而知,但毫无疑问,生态系统的波动性引起的巨大波动(包括整个加密货币和可以说是第二重要的交易所的崩溃和毁灭)影响了它们触及的一切。
这包括数据。
鉴于机器学习的整个理论假设今天的行为至少有点像昨天,在这样一个混乱的环境中,算法和模型能为你做什么?甚至更多:你如何利用 crypto 固有的海量数据的力量,跟踪这些极端的变化,并真正从中提取价值?
这些是 CTF 资本(一家交易基金)的家伙们的疑问。我们在 deployr ,与他们一起工作,为每个参与的人找到最好的答案,并建立他们的数据和 ML 管道。
我们希望我们应对这些挑战的经验能够帮助您理解加密世界的复杂性,并可能在如何处理您自己的数据问题和团队管理方面给予您冷静的见解。
简要说明:本文的重点不是讨论加密交易本身的复杂性(可以说是经济角度),而是讨论我们如何使用 MLOps 方法的最佳实践来领导一家在技术和计算要求最高的领域之一工作的公司的转型过程。
解决了这个问题,让我们开始吧!
构建数据和 ML 管道:从地面到云端
这是 2022 年初,封锁结束后,事情看起来很光明。当时,我们收到了一条来自一位在加密交易基金工作的朋友和同事的消息:“我设法组建了一个令人惊叹的数据团队,但我们缺乏方向和重点”。
为了让你对我们这边的世界有所了解(我们来自阿根廷,你想要一个配偶吗?),在拉丁美洲,我们面临着实现顶级绩效的独特挑战,同时要解决三个主要问题:
缺乏西班牙语的形成性资源:虽然幸运的是两个团队都能够流利地使用英语,但残酷的现实是大多数技术框架都是用英语设计和编码的,并且大多数时候试图在网上找到西班牙语的示例和指南会导致低质量的资源,甚至根本没有结果。
云计算的固有成本:为了说明这一点,阿根廷的最低工资目前是每月 200 美元左右。这看起来可能不是一个真正的问题,但是当你不得不花钱在云中实现一些东西时,花一两美元就可以让失败的成本(这是开发这些解决方案的自然部分,失败并快速迭代以获得最佳结果)非常高。
**高级人才流失:**主要是由于比索和美元之间巨大的汇率差距造成的。
最高价和最低价
CTF 资本公司的人正在开发一个可以整合到更大的决策系统中的模型。这个想法是为了帮助交易者(真实的人)对特定的加密货币对(大多数情况下,与稳定的货币相比,如 USDC 或 USDT)进行卖出或买入。
说到加密,管道的每一个部分都可能很快变成极端和危险的东西。虽然几乎每个行业的每个项目都是如此,但请记住,密码世界的变化可能会突然发生**。**
**作为一家处理数百万美元(转化为多种加密货币)的交易基金,决策过程必须尽可能清晰,为此,跟踪和问责至关重要。
“In crypto, we call this a Wednesday”
考虑到这种情况,在我们开始动手编写一行代码之前,我们必须为我们将要构建的一切建立最坚实的基础。
构建数据和 ML 管道图
如果你曾经是这种转型过程的一部分,我肯定你已经知道这是一个所有人都在甲板上的时刻。
达到这种卓越和绩效水平要求每个人都必须清楚地了解情况。要做到这一点,你必须从技术、业务和人员层面对组织和进行诚实的诊断。以此为起点,设计并引导你的客户到达他们希望到达的地方就成了问题。
我们也相信沟通很重要,对每一步会发生什么保持神秘是没有意义的。如果你想让数据科学家、工程师、架构师、利益相关者、第三方顾问和无数其他参与者参与进来,你必须做好两件事:
- 1 在利益相关者和来自整个组织的成员(从营销到销售再到工程)之间搭建桥梁,在不同的理论和实践层面处理数据。
- 对最终目标的兴奋感:更好地做我们所做的事情,使用最佳软件实践来充分利用我们所做的事情,并使用最合适的技术来做这件事。
你处理这些问题的方式完全不同,而且它需要在最先进的技术方面(“我们能建立、维护和部署它吗?”、合理规模对我们意味着什么?”)和业务的人性一面(“从现在开始到接下来的几个月,会有多少职位轮换?”“我和我的团队需要什么,我们将如何成长?”)来设计一条清晰一致的路径,把你从现在的位置带到你想去的地方。
这就是为什么我们利用我们作为开发和管理团队一部分的多年经验以及几种方法中的最佳方法,开发了 架构画布:一个帮助组织推进其数据项目的框架。
Architecture canvas | Source: Author
空谈是廉价的(也是有用的)
无需深入细节,架构画布由两大阶段组成:
第一阶段:建筑
在这里,我们试图清楚地了解给定组织在数据和 ML 采用方面的技术、文化、和人员能力,善意地指出最薄弱的地方,诚实地提供合适的改进方案。
这是上图的下半部分,旨在从以下方面深入了解公司的状况:
- 1 价值主张
- 2 数据来源和版本控制
- 3 数据分析和实验
- 4 功能商店和工作流程
- 5 基础
- 6 ML 管道编排
- 7 模型注册和版本控制
- 8 车型部署
- 9 预测发球
- 10 数据和模型监控
- 11 元数据存储
阶段 2: ML 和 IA 成熟度量表
这种方法始于这样的假设:每个团队都可以在四个维度上进行分析:人员、技术、数据和流程。根据每一种可能的组合,你会得到六个方法轴:
- 1 学习:人+技术
- 2 领导:人员+流程
- 3 访问:人员+数据
- 4 规模:数据+技术
- 5 安全:数据+流程
- 自动化:技术+流程
这一阶段的目标是根据这六个轴在三个不同成熟度级别上的表现给团队打分:战术、战略和转型。
您可以看一下上图的上半部分,看看这些交叉点是如何在从 1(在数据采用方面完全不成熟的组织)到 5(在数据采用方面完全成熟、专业和先进的组织)的级别上结束的。
我们为人类同胞编码(并与之合作)
这个框架需要完全的诚实、透明和协作。为了获得所有这些信息,我们需要与团队的不同领域(科学家、工程师、QA、经理、高管,如果需要的话)进行会谈,以便充分了解每个人对项目的期望,并达成共识。
幸运的是,会议富有成效且充满乐趣:我们能够深入底层,设计出一个新的计划,使我们能够快速发展,并以季度的方式衡量它,为业务的每个领域提供价值和安心。
为了促进上述透明度和协作,在会议结束并制定计划后,我们的第一步是重新安排管理和跟进工具,使其适应我们的需求。
严肃地说:保持和维护一个严肃的跟踪工具,我们怎么强调都不为过。使用 Trello,Asana,或者你选择的任何方法,但是如果你想让每个人都在同一页上,保持每个人都在做的事情的完全可见性是至关重要的。
在这一点上,我们使用概念,我们认为它本身就是一个令人惊叹的工具,但我们的王牌是这个由 Thomas Frank 制作的令人惊叹的免费模板:开始使用它可能有点复杂和吓人,但一旦你掌握了窍门,它是一种非常直观的方式,通过看板和日历方法的最佳效果来组织工作。
我们还定义了新的 Slack 通道来加速一些事情,它们最终将成为自动通知中心的一个组成部分,用于监控整个系统(稍后将详细介绍!).
知道需要做什么和以什么顺序做(整个过程和管理【数据的 方面)经常被忽视,我们知道有时让每个人都了解最新情况以其自己的方式可能有点乏味,但是如果你能在睡梦中编排几十个步骤的管道,你肯定能花点时间写下你在做什么,对吗?
阶段 1—数据管道:让房子井然有序
一旦尘埃落定,我们就完成了架构画布,并且计划对参与的每个人都很清楚,下一步就是仔细看看架构。这就是通常发生的事情:
我们为 ML 模型而来,我们为 ETL 留下。
过去,主要的棘手问题是:
- 架构部署没有明确标记,有些部分严重依赖手动执行。
- 整个系统的入口点依赖于多个 web 套接字,这使得它很难扩展。
- SQS 的队伍很难维持。
盒子里有什么?
首先,数据的来源来自两个最大的交易所。但是,即使 ETL 是经过深思熟虑的,它们的方法也有点“过时”。由于他们主要是为了测试而进行概念验证,大部分架构是面向计算的:通过 ssh 在 EC2 中设置东西,没有 CI/CD,几乎没有使用 rds,一些丢失数据的问题,几乎没有容器化,等等。
我们很快意识到,虽然开发团队在 ML 的数据科学和工程方面(算法、ETL 以及如何使用它们来推动业务发展)非常出色,但他们缺乏关于如何从云服务和该领域新的最佳实践中获取最大价值的知识。
在这种情况下,我们在三件事上达成了一致:
- 1 慢慢转向更“过时”的架构(深入研究无服务器)。
- 2 教他们如何使用最适合他们的堆栈(主要关注 MLOps 和 AWS Sagemaker / Sagemaker Studio 的基础知识)。
- 3 重新设计和重写架构作为基础设施作为代码(使用 AWS Cloudformation)。
幸运的是,我们能够快速交付,并且在一个月内我们已经建立了一个全新的系统。
ETL 管道
ETL Pipeline | Source: Author
- 流水线由 Eventbridge 触发**,可以手动完成,也可以由 cron 完成。**
- 这触发了一系列初始化配对的 Lambda 函数:也就是说,一种加密货币与另一种加密货币(BTC/USDC、ETH/BTC 等)相比如何。).向 CTF 资本令人惊叹的数据工程团队大声欢呼吧,他们真的倾注了他们的心血和智慧!
- 我们决定一次做一个交换:首先,最大的一个,一旦一切正常,我们整合第二个。
- 这里的关键是做好数据的分区。在每个触发器上,我们检查每个触发器,看是否有新的数据,如果有,它就把数据转储到 S3。
阶段 2—ML 管道:现在,模型
最后,是时候开始研究 ML 管道了。耶!
我们注意到的第一件事是它不是“框架兼容的”:换句话说,每一个模型(一个. gz 文件)在执行一个手工过程之后都被存储在 S3。该模型没有在生产环境中使用,只在一些测试批次预测中使用。
我们推广了 Sagemaker Pipelines 的使用:在整洁的 UI 背景下,服务运行步骤功能,这些功能更容易与某些关键步骤所需的 Docker 映像和 AWS Lambdas 集成。此外,它使跟踪工件变得更简单,因为它为你处理了 S3 的许多来回。
CI/CD 对于防止意外事件如不必要的管道执行是至关重要的,我们实现了使用 GitHub 动作来触发一些任务,如数据管道部署。
当这方面的问题解决后,我们开始构建模型注册表。我们开始时的情况是,一些模型存储在 S3,用于做一些小批量预测,但因为他们想实时使用它,我们需要使用一个端点和一个模型注册表。
ML 培训渠道
考虑到我们将此框定为一个时间序列,下面是数据管道功能的简要概述:
ML training pipeline | Source: Author
- 第一阶段处理过滤、标记和特征生成,然后被分成训练集和测试集。
- 接下来是模型的 超参数调整 阶段。
- 接下来是非常详尽的评估阶段T3。我们在这一点上特别小心,因为我们需要对模型进行全面测试。我们将它们提交给五种不同的方法和一些特征重要性提取过程。
- 有了所有这些,模型用所有的数据重新训练,并存储在 Sagemaker 模型注册中心。
- 之后,一个选择的模型被部署并在模型管道中使用。
这是一个相对简单的过程,通过交叉验证、优化以及随后的完整数据集训练来处理训练。
ML 模型管道
模型管道也具有挑战性,因为我们正在从批量预测推理转变为事件驱动推理,这将允许我们达到实时。由于公开的原因,我们不能展示架构图,但是这条管道的作用是:
- 获取原始数据并执行一些特征工程,以获得一个被称为 OHLC (开盘-盘高-盘低-收盘)的通用指标。
- 值得一提的是,数据在整个过程中持续存储在分层指定的存储桶中(原始、青铜、白银和黄金)。
- 以此为输入,有一个建立特征的步骤**,然后是另一个过滤数据的步骤**,只有当数据从我们的科学和方法角度看起来有希望时,才允许该过程继续。
- 接下来,它建立了一个通用模型,该模型结合了一些算法的输出结果、业务规则以及一段时间内数据变化的程度,以便估计应该投入多少资金以及是做多还是做空。
- 该预测被提供给 BI 仪表板,交易员用它来决定在任何给定时间做什么。
最终,我们厌倦了看着控制台,等待任务结束。所以我们决定做一个小小的附带项目,编写一些“有趣但有用”的代码,然后我们为自己建了一个自动通知中心。
Notification center | Source: Author
这是一个非常简单但优雅的过程,它使用 Eventbridge 来监视给定作业何时失败,并触发一个带有概念和 Slack 客户端的 lambda 函数。
Event trigger
此时,我们正在实现它来通知处理作业的变化。从 Cloudformation 模板的这段摘录中,您可以看出我们正在寻找由 AWS Sagemaker 自动生成的事件,特别是处理作业状态变化。在 lambda 函数的上下文中,它执行以下操作之一:
- 在一个成功的作业中,一些关键参数被记录在一个概念表中(为了做到这一点,我们从概念 API 中榨取了最多的东西)。
- 如果出现问题,我们使用 Webhooks 向 Slack 通道发送通知,这样我们的工程师和科学家就可以查看。
好的和坏的
经过几个月的开发,我们终于开始生产了!
我们愿意分享我们喜欢的和不喜欢的东西,给你一些我们的看法,也许会有用。
坏事
- 让我们先从不太酷的开始。虽然 AWS Sagemaker 让事情变得简单了很多,但众所周知,并不是所有事情都像文档上看起来的那样。这方面的一个例子是多模型服务器库,这是 AWS 推荐团队在处理某些 DL 模型时使用的,但它已经多年没有维护了。
“On a fun note, you can easily tell the last update was forced due to the infamous log4j vulnerability in January 2022.” | Source: Author
正因为如此,我们不得不使用一些过时的 Python 和 Ubuntu 版本,这迫使我们做一些不必要的重构,以便使我们的工作流适应工具和 AWS 标准的需要(而实际上应该反过来)。
我们遇到了无服务器范例中的一些限制,主要归结为一些内存问题。我们知道 Pandas 不是性能最好的库,它可能会占用大量内存。尽管如此,我们真的不想切换到一些其他框架,除非它是必要的,以便使事情对数据科学家来说更容易一些。
幸运的是,我们能够解决这些问题,由于 Lambda 的限制最近已经扩大了(更多的正常运行时间和功率),这很可能只是一个时间问题,直到它变得更加完美。
使用定制库构建定制容器来执行推理并不像文档看起来那么简单。我们与它进行了艰苦的斗争(并取得了胜利),主要是在规模方面。
好人
毫无疑问,即使有我们发现的限制,如果你想尽可能提高效率,无服务器是一条可行之路。一开始,设置和技术上的领先总是有点颠簸,但是我们通过从基于资源的架构转移到事件驱动的架构,成功地将成本降低到三分之一。
路线图对参与的每个人来说都很清楚,职责定义得很好,任务也及时得到了正确的安排。正如我们之前提到的,我们再怎么强调让所有相关人员全面了解整个项目的重要性也不为过。
出于多种原因,转向基础设施即代码的方法被证明是最佳选择,但并非所有这些都是经济上的。这里有一个有趣的,非常典型的行业:逃避某些规定。
为了操作这些交换机,您必须非常小心,并仔细选择您尝试 ping 它们的位置,因为有几个国家的法规禁止一定级别的访问(我们被源 IP 地址明确标记)。这仅仅是一个改变 AWS 区域和去其他地方的问题,因为我们已经有了基础设施的模板,要改变它,我们只需要修改一行代码。越简单越好!
一起工作帮助团队真正提升了他们的编码水平。我们开始推广代码审查和 linters(在我们的例子中是 Pylint)的使用,我们做到了,所以首席数据科学家必须批准每一个 pull 请求。
CTF 资本 的人学到了很多关于云和基础设施的知识,并有机会以更加独立和一致的方式部署他们的许多开发成果,而我们在 deployr 学到了很多(我们非常重视)关于加密生态系统以及如何解决行业中某些特定问题的知识。
下一步是什么?
当然,我们还有很长的路要走(一如既往)。接下来最重要的步骤是:
- 我们以一种有点“土气和手工”的方式跟踪和监控实验。因为我们想让它更上一层楼,我们不想更多地依赖于一些 AWS 解决方案,下一个季度我们将深入研究像 neptune.ai 这样的工具,用它来跟踪我们的实验和元数据。
- 我们正在设置深入实时的东西:最终目的是自动化一些交易操作,为此,我们必须致力于预测管道。
- 我们正在为预测端点开发一个监控和记录系统,控制性能预测和基础设施。这包括模型质量漂移、特征重要性漂移和模型偏差漂移。
- 此外,我们正在研究自动通知中心的进一步开发,在此基础上,它可以在表现不佳或服务中断的情况下发出通知,并在需要时重新运行培训管道。
查看 neptune.ai 提供的实验跟踪功能。
如果你已经读到这里,谢谢你一直读到最后!如果您有任何疑问、问题或意见,请随时写信给我。**
具有全卷积残差网络的深度估计模型(FCRN)
估计和评估 2D 场景的深度是一项困难的计算机视觉任务。首先,你需要昂贵的设备来绘制深度图。像用于视觉、运动和光投影的 3D 立体传感器这样的庞大系统是当今使用的最可靠的技术,它们依赖于需要额外评估以产生精确渲染的外部因素。
如果你不想为这一项任务携带和操作一大套设备,还有另一个解决方案。大量的工作已经投入到构建紧凑的系统中,这些系统统一并处理由设备的每一部分单独提供的所有相关功能。一个很好的例子是 考虑全光成像失真的光场相机 。
深度估计具有广泛的用途,这就是在该领域进行大量研究的原因。深度估计的一些最公知的用途是:
- 3D 渲染和 3D 运动捕捉,
- 自动驾驶汽车,
- 机器人技术(包括机器人辅助手术),
- 2D 和 3D 电影转换,
- 计算机图形和游戏产业中的 3D 渲染和阴影映射。
Depth estimation rendering for a video | Source: Deep Learning approach to Depth prediction, Google AI
同一目标的不同方法
最近,为深度估计设计了几种方法。深度学习再次证明了它解决问题和应对各种挑战的能力。该方法集中于单个视点(2D 图像),并优化参考深度图上的回归。
已经测试了多种神经架构,一些主要的实现为未来的研究铺平了道路,这使它们成为该领域中最先进的技术。让我们来看看其中的一些。
利用全卷积残差网络进行更深的深度预测
这种方法通过利用从 RGB 图像返回 2D 场景的深度图的完全卷积架构来解决这个问题。
所提出的架构包括全卷积层、转置卷积和有效的残差上采样块,有助于跟踪高维回归问题。
揭露该模型的研究论文解释了这种原始架构如何使用残差学习来处理单目视觉和深度图之间的模糊映射。Huber 损失函数用于优化,并且该模型可以以 30 FPS 的稳定帧速率在图像和视频上运行。
*该网络由具有初始化的预训练权重的第一 ResNet50 块组成,并通过一系列卷积层和非卷积层前进,使网络学习其升级。然后,脱落图层被放置在生成预测结果的最终卷积图层旁边的末端。
关于整体架构的更多细节可以在官方研究论文中找到: 使用全卷积残差网络的更深深度预测 。
来自视频的深度和自我运动的无监督学习
这种特定的方法完全基于无监督的学习策略,将单视图深度 CNN(如之前所示)与在无标签视频序列上训练的相机姿势估计 CNN 相结合。
这种方法是独一无二的,也是同类方法中的首创。作者解释说,训练的整个监督管道是基于视图合成的。粗略地解释,网络被馈送以目标视图,并输出每像素深度图。给定每像素深度图以及来自原始图像的姿态和可见性附近视图,相应地合成目标视图。
因此,网络正确地管理使用 CNN 的图像合成和姿态估计模块之间的平衡。
注:对于这种特定架构背后的理论的详细解释可以在 2017 年发表的原始研究论文中查阅到: 来自视频的深度和自我运动的无监督学习 。
具有左右一致性的无监督单目深度估计
这种特定的架构是端到端的,并且在没有地面实况数据的情况下执行无监督的单目深度估计。如标题所示,该网络的训练损失加强了左右深度一致性,这意味着网络通过推断包裹左图像以匹配右图像的差异和差异来估计深度。
为网络提供动力的整个机制依赖于产生差异并在培训过程中不断纠正它们。通常,左输入图像用于推断从左到右和从右到左的差异。然后,网络使用双线性采样器通过反向映射生成预测的结果图像。
作者使用了与 DispNet 非常相似的卷积架构。它建立在编码器和解码器模式的基础上。解码器使用来自编码器激活模块的跳过连接来解析更高分辨率的细节。
最后,网络预测两个视差图:从左到右和从右到左。
FCRN:完全卷积剩余网络
FCRN 是设备上深度预测最常用的模型之一。当苹果公司为其 iPhone 系列的前置摄像头实现并集成深度传感器时,这种架构变得很有名。由于该模型基于 CNN (ResNet-50),移动部署的压缩和量化过程相对简单明了。
我们将讨论 FCRN 架构的一些重要组件和构建模块,并一瞥 Pytorch 中的实际实现。
实施和构建模块
有趣的是,整个 FCRN 架构受到了 U-Net 方案的高度启发。两者都使用固定滤波器 3×3 的三个下采样和三个上采样卷积块。最初,U-Net 在每个块中有两个卷积层,所有卷积层的滤波器数量保持不变。
相反,在 FCRN 实现中,作者增加了后续层的数量,以补偿由池化引起的高分辨率信息的损失。
Faster up-Convolutions. Illustration of what we’ve explained above. The common up-convolutional steps: unpooling doubles a fea- ture map’s size, filling the holes with zeros, and a 5 × 5 convolution filters this map | Source: official research paper
首先,让我们看一下 FRCN 网络的基本部分,即卷积块,由卷积层、批量归一化和激活函数组成。
def conv_block(channels: Tuple[int, int],
size: Tuple[int, int],
stride: Tuple[int, int]=(1, 1),
N: int=1):
"""
Create a block with N convolutional layers with ReLU activation function.
The first layer is IN x OUT, and all others - OUT x OUT.
Args:
channels: (IN, OUT) - no. of input and output channels
size: kernel size (fixed for all convolution in a block)
stride: stride (fixed for all convolution in a block)
N: no. of convolutional layers
Returns:
A sequential container of N convolutional layers.
"""
block = lambda in_channels: nn.Sequential(
nn.Conv2d(in_channels=in_channels,
out_channels=channels[1],
kernel_size=size,
stride=stride,
bias=False,
padding=(size[0] // 2, size[1] // 2)),
nn.BatchNorm2d(num_features=channels[1]),
nn.ReLU()
)
return nn.Sequential(*[block(channels[bool(i)]) for i in range(N)])
conv _ 块函数具有***【N】***个卷积层,具有 个 个滤波器,遵循 ReLU 激活和批量归一化。
整个 FCRN 架构可以通过将专门定义的块堆叠在一起而获得,例如上采样块、解转换块、上转换解码器和 FasterUpConv 解码器,这些是 pixelshuffle 的特定技术。
我不能详细说明每个模块实际上是如何实现的,因为它的理论和实用性是如此的密集,以至于仅仅介绍和解释它们的功能就需要一整篇文章。但是,总体框架可以描述如下:
self.model = nn.Sequential(
conv_block(channels=(input_filters, 32), size=(3, 3), N=N),
nn.MaxPool2d(2),
conv_block(channels=(32, 64), size=(3, 3), N=N),
nn.MaxPool2d(2),
conv_block(channels=(64, 128), size=(3, 3), N=N),
nn.MaxPool2d(2),
DeConv(channels=(128, 512), size=(3, 3), N=N),
nn.Upsample(scale_factor=2),
UpConv(channels=(512, 128), size=(3, 3), N=N),
nn.Upsample(scale_factor=2),
FasterUpConv(channels=(128, 64), size=(3, 3), N=N),
nn.Upsample(scale_factor=2),
conv_block(channels=(64, 1), size=(3, 3), N=N),
)
DeConv 和 UpConv 由 4 个卷积块模块组成,通道数量逐渐减少,特征映射尺寸逐渐增大。它们在 Pytorch 中的实现如下所示:
def convt(in_channels):
stride = 2
padding = (kernel_size - 1) // 2
output_padding = kernel_size % 2
assert -2 - 2 * padding + kernel_size + output_padding == 0, "deconv parameters incorrect"
module_name = "deconv{}".format(kernel_size)
return nn.Sequential(collections.OrderedDict([
(module_name, nn.ConvTranspose2d(in_channels, in_channels // 2, kernel_size,
stride, padding, output_padding, bias=False)),
('batchnorm', nn.BatchNorm2d(in_channels // 2)),
('relu', nn.ReLU(inplace=True)),
]))
self.layer1 = convt(in_channels)
self.layer2 = convt(in_channels // 2)
self.layer3 = convt(in_channels // (2 ** 2))
self.layer4 = convt(in_channels // (2 ** 3))
class UpConv(Decoder):
def upconv_module(self, in_channels):
upconv = nn.Sequential(collections.OrderedDict([
('unpool', Unpool(in_channels)),
('conv', nn.Conv2d(in_channels, in_channels // 2, kernel_size=5, stride=1, padding=2, bias=False)),
('batchnorm', nn.BatchNorm2d(in_channels // 2)),
('relu', nn.ReLU()),
]))
return upconv
def __init__(self, in_channels):
super(UpConv, self).__init__()
self.layer1 = self.upconv_module(in_channels)
self.layer2 = self.upconv_module(in_channels // 2)
self.layer3 = self.upconv_module(in_channels // 4)
self.layer4 = self.upconv_module(in_channels // 8)
如果你对整个基础设施感兴趣和好奇,有一个很好的 Github repo,它用 ResNet-50 实现了 FCRN 架构,并且完全遵循了研究论文的指示: FCRN Pytorch 实现。
NYU 深度 V2 数据集上的训练
该数据集由来自分割的元素组成,并支持来自 RGBD ( 、RGB 和深度 )图像的推断。它包含来自 Microsoft Kinect 的 RGB 和深度相机记录的各种 3D 场景的视频序列。
链接: NYU 深度数据集 V2
基本上,它的特点是:
- 1449 个密集标记的对齐 RGB 和深度图像对
- 来自 3 个城市的 464 个新场景
- 407024 新的无标签帧
数据集包含多种类型的数据:
- 用伴随着密集多类标签的视频数据子集来标记。
- 由微软 kinect 摄像头提供的原始 RGB、深度和加速度计数据。
为了开始调试模型,我们将依赖一个使用 Pytorch 的开源 Github 实现。实施是由王鸽翔(大喊着他出来的!),他提供了一个完全用 Pytorch 制作的替代版本,仔细遵循了关于模型架构和训练过程的官方文件指示。
用谢恩自己的话说 : 这是 PyTorch 利用全卷积残差网络实现的更深深度预测。它可以使用全卷积残差网络来实现单目深度预测。目前,我们可以使用 NYUDepthv2 和 Kitti 里程计数据集训练 FCRN。
安装指南
- 克隆 repo: git 克隆 git @ github . com:dontLoveBugs/FCRN _ pyo trch . git
- 安装所需的依赖项:pip 安装 matplotlib pillow tensorboard x torch torch vision
在 dataloaders 文件夹中配置数据集路径
下载 NYU 深度 V2 数据集,标注版本约为 2.8GB】此处下载。
让我们定义 nyu_dataloader 类,它从根目录加载数据集,并执行数据转换和数据扩充。
height, width = 480, 640
class NYUDataset(Dataloader):
def __init__(self, root, type, sparsifier=None, modality='rgb'):
super(NYUDataset, self).__init__(root, type, sparsifier, modality)
self.output_size = (228, 304)
def train_transform(self, rgb, depth):
s = np.random.uniform(1.0, 1.5)
depth_np = depth / s
angle = np.random.uniform(-5.0, 5.0)
do_flip = np.random.uniform(0.0, 1.0) < 0.5
transform = transforms.Compose([
transforms.Resize(250.0 / height),
transforms.Rotate(angle),
transforms.Resize(s),
transforms.CenterCrop(self.output_size),
transforms.HorizontalFlip(do_flip)
])
rgb_np = transform(rgb)
rgb_np = self.color_jitter(rgb_np)
rgb_np = np.asfarray(rgb_np, dtype='float') / 255
depth_np = transform(depth_np)
return rgb_np, depth_np
我们还在 Neptune 实验中记录了所有这些信息,以便跟踪数据集目录和应用的转换。
开始你的实验:
run = neptune.init(project='aymane.hachcham/FCRN, api_token='ANONYMOUS') # your credentials
run['config/dataset/path'] = 'Documents/FCRN/dataset'
run['config/dataset/size'] = 407024
run['config/dataset/transforms'] = {
'train': transforms.Compose([
transforms.Rotate(angle),
transforms.Resize(int(250 / height)),
transforms.CenterCrop((228, 304)),
transforms.RandomHorizontalFlip(p=0.5)
])
}
Neptune dataset configurations
在开始培训之前,让我们记录我们想要使用的模型的超参数。
hparams = {
'batch_size': 128,
'decoder':'upproj',
'epochs':10,
'lr':0.01,
'lr_patience':2,
'manual_seed':1,
'momentum':0.9,
'print_freq':10,
'resume':None,
'weight_decay':0.0005,
'workers':0
}
run["params"] = hparams
在记录了所有需要的超参数后,我们将启动 epochs 的培训课程。我们将把损失和所有指标记录到 Neptune,以跟踪进度。
def train(train_loader, model, criterion, optimizer, epoch, logger):
average_meter = AverageMeter()
model.train()
end = time.time()
batch_num = len(train_loader)
for i, (input, target) in enumerate(train_loader):
input, target = input.cuda(), target.cuda()
torch.cuda.synchronize()
data_time = time.time() - end
end = time.time()
pred = model(input)
loss = criterion(pred, target)
optimizer.zero_grad()
loss.backward()
optimizer.step()
torch.cuda.synchronize()
gpu_time = time.time() - end
result = Result()
result.evaluate(pred.data, target.data)
acc = result.evaluate(pred.data/target.data)
average_meter.update(result, gpu_time, data_time, input.size(0))
end = time.time()
run["training/batch/accuracy"].log(acc)
run["training/batch/loss"].log(loss)
if (i + 1) % args.print_freq == 0:
current_step = epoch * batch_num + i
logger.add_scalar('Train/RMSE', result.rmse, current_step)
logger.add_scalar('Train/rml', result.absrel, current_step)
logger.add_scalar('Train/Log10', result.lg10, current_step)
logger.add_scalar('Train/Delta1', result.delta1, current_step)
logger.add_scalar('Train/Delta2', result.delta2, current_step)
logger.add_scalar('Train/Delta3', result.delta3, current_step)
Neptune 中的精度和损耗设置
对于训练会话,我们清楚地观察到这两个指标运行良好,除了由数据插值引起的精度曲线的线性下降,其中上卷积层丢失深度信息,并被连续实时呈现的索引矩阵的比例淹没。
即使我们执行新的训练课程,改变历元数或稍微调整训练数据,变化也不会很大。
通过增加历元的数量和减少数据转换的数量,我们在准确度分数上获得了轻微的提高,并且还消除了由数据插值引起的差异。
一个很酷的提示 Shan 建议在训练时使用较低的历元数(< 100) is to decrease the 学习率 并增加 速率 _ 优化器 )。这样,梯度计算得更慢,反向计算更同步,从而为模型留出相应的适应空间。
因此,新运行的新超参数如下所示:
hparams = {
'batch_size': 128,
'decoder':'upproj',
'epochs':10,
'lr':0.002,
'lr_patience': 2.5,
'manual_seed':1,
'momentum':0.9,
'print_freq':10,
'resume':None,
'weight_decay':0.0005,
'workers':0
}
这是两次运行之间的比较:
Blue chart: previous accuracy, Red chart: the improved one | See in the app
我们清楚地注意到,超参数调整和选择 30 个周期的长时间训练极大地提高了准确度标准。
我会把海王星项目的链接留给你。快来看看吧: FCRN 实验
最终输出
一旦执行了训练,我们可以看看由模型基于来自验证集的看不见的室内图像生成的结果深度图。
为了加强和断言关于模型结果的确定性,Github repo 展示了我们在这里使用的相同模型的预训练版本,其中包含一系列令人满意的断言模型推理质量的指标。
结果
在成功完成训练后,作者给出了一些与错误相关的度量,以便评估他的实现与以前的实现相比的性能。
显然,他用 Pytorch 的实现通过略微改进定义为基于地面真实深度图值归一化的绝对误差的***【rel】(相对绝对误差),以及log10***(ABS(log10(gt)–log10(pred))(其中 gt 是地面真实深度图,pred 是预测深度图),击败了先前的尝试。
定性结果
*RGB images from validation set, their ground truth and final results generated by the model *
正如在官方论文中所解释的那样,全卷积残差网络提高了精度,这要归功于其使用增强型上投影模块和上采样技术的特定架构,上采样技术涉及使用连续 2×2 内核的去卷积。定性地说,与相同数据集上的其他不同的完全卷积变体相比,这种方法在输出中保留了更多的结构。
结论和展望
我们浏览了深度估计领域中使用的各种技术和架构。我们实践和训练了 FCRN 的一个现有实现,以展示和观察这种方法在定性结果方面的能力。
您可能想尝试的一个有趣的项目是实现 FCRN 模型的设备版本,并创建一个实时执行深度估计的小型 IOS 应用程序。MLCore 和 Apple Vision 已经提出了预训练 FCRN 模型的不同变体,这些模型可以快速用于涉及前置摄像头和深度传感器的任务。也许我可以在下一篇关于这个主题的文章中考虑这个问题。敬请期待!
一如既往,我将为您留下一些有用的资源,您可以查找关于该主题的深入知识:*
机器学习的降维
原文:https://web.archive.org/web/https://neptune.ai/blog/dimensionality-reduction
数据构成了任何机器学习算法的基础,没有它,数据科学就不可能发生。有时,它可能包含大量的特性,有些甚至不是必需的。这种冗余信息使得建模变得复杂。此外,由于高维度,通过可视化来解释和理解数据变得困难。这就是降维发挥作用的地方。
在本文中,您将了解到:
- 什么是降维?
- 什么是维度的诅咒?
- 用于降维的工具和库
- 用于降维的算法
- 应用程序
- 优点和缺点
什么是降维?
降维是减少数据集中要素数量的任务。在像回归或分类这样的机器学习任务中,经常有太多的变量需要处理。这些变量也被称为特性。特征数量越多,建模就越困难,这就是所谓的维度诅咒。这将在下一节详细讨论。
此外,这些特征中的一些可能非常多余,会向数据集添加噪声,并且在训练数据中包含它们是没有意义的。这就是需要减少特征空间的地方。
降维的过程实质上是将数据从高维特征空间转换到低维特征空间。同时,在转换过程中不丢失数据中存在的有意义的属性也很重要。
降维通常用于数据可视化以理解和解释数据,以及用于机器学习或深度学习技术以简化手头的任务。
维度的诅咒
众所周知,ML/DL 算法需要大量的数据来学习不变性、模式和表示。如果该数据包含大量特征,这可能会导致维数灾难。维数灾难首先由 Bellman 提出,描述了为了以一定的精度估计任意函数,估计所需的特征或维数呈指数增长。对于产生更多稀疏性的大数据来说尤其如此。
数据的稀疏性通常指的是具有零值的特征;这并不意味着缺少值。如果数据具有大量稀疏特征,则空间和计算复杂性会增加。OliverKuss【2002】表明在稀疏数据上训练的模型在测试数据集中表现不佳。换句话说,训练期间的模型学习噪声,并且它们不能很好地概括。因此他们过度适应。
当数据稀疏时,训练数据集中的观察值或样本很难聚类,因为高维数据会导致数据集中的每个观察值看起来彼此等距。如果数据是有意义的和非冗余的,那么将存在相似数据点聚集在一起的区域,此外,它们必须具有统计显著性。
高维数据带来的问题有:
- 冒着过度适应机器学习模型的风险。
- 相似特征聚类困难。
- 增加了空间和计算时间的复杂性。
另一方面,非稀疏数据或密集数据是具有非零特征的数据。除了包含非零特征之外,它们还包含有意义且非冗余的信息。
为了解决维数灾难,使用了降维等方法。降维技术对于将稀疏特征转换为密集特征非常有用。此外,降维还用于清洗数据和特征提取。
最流行的降维库是 scikit-learn (sklearn)。该库由三个主要的降维算法模块组成:
- 分解算法
- 主成分分析
- 核主成分分析
- 非负矩阵分解
- 奇异值分解
- 流形学习算法
- t 分布随机邻居嵌入
- 光谱嵌入
- 局部线性嵌入
- 判别分析
- 线性判别分析
当谈到深度学习时,可以构建像自动编码器这样的算法来降低维度,并学习特征和表示。Pytorch、Pytorch Lightning、Keras 和 TensorFlow 等框架用于创建自动编码器。
降维算法
先说第一类算法。
分解算法
scikit-learn 中的分解算法涉及维数约减算法。我们可以使用以下命令调用各种技术:
from sklearn.decomposition import PCA, KernelPCA, NMF
主成分分析
主成分分析(PCA)是一种降维方法,通过保留在高维输入空间中测量的方差来寻找低维空间。这是一种无监督的降维方法。
PCA 变换是线性变换。它包括寻找主成分的过程,即把特征矩阵分解成特征向量。这意味着当数据集的分布是非线性时,PCA 将是无效的。
让我们用 python 代码来理解 PCA。
def pca(X=np.array([]), no_dims=50):
print("Preprocessing the data using PCA...")
(n, d) = X.shape
Mean = np.tile(np.mean(X, 0), (n, 1))
X = X - Mean
(l, M) = np.linalg.eig(np.dot(X.T, X))
Y = np.dot(X, M[:, 0:no_dims])
return Y
PCA 的实现非常简单。我们可以将整个过程定义为四个步骤:
- 标准化:通过取原始数据集与整个数据集的平均值之间的差值,将数据转换到一个通用的标度。这将使分布 0 居中。
- 求协方差:协方差会帮助我们理解均值和原始数据之间的关系。
- 确定主成分:主成分可以通过计算特征向量和特征值来确定。特征向量是一组特殊的向量,帮助我们理解数据的结构和属性,这些数据将成为主要成分。另一方面,特征值帮助我们确定主成分。最高的特征值及其对应的特征向量构成了最重要的主分量。
- 最终输出:是标准化矩阵和特征向量的点积。请注意,列或特征的数量将会改变。
减少数据变量的数量不仅降低了复杂性,还降低了机器学习模型的准确性。然而,由于特征数量较少,因此易于探索、可视化和分析,这也使得机器学习算法的计算成本较低。简而言之,主成分分析的思想是减少数据集的变量数量,同时尽可能多地保留信息。
我们也来看看 sklearn 为 PCA 提供的模块和函数。
我们可以从加载最多的数据集开始:
from sklearn.datasets import load_digits
digits = load_digits()
digits.data.shape
(1797, 64)
数据由 8×8 像素图像组成,这意味着它们是 64 维的。为了了解这些点之间的关系,我们可以使用 PCA 将它们投影到更低的维度,如 2-D:
from sklearn.decomposition import PCA
pca = PCA(2)
projected = pca.fit_transform(digits.data)
print(digits.data.shape)
print(projected.shape)
(1797, 64)
(1797, 2)
现在,让我们画出前两个主要成分。
plt.scatter(projected[:, 0], projected[:, 1],
c=digits.target, edgecolor='none', alpha=0.5,
cmap=plt.cm.get_cmap('spectral', 10))
plt.xlabel('component 1')
plt.ylabel('component 2')
plt.colorbar();
Dimensionality reduction technique: PCA | Source: Author
我们可以看到,在大多数情况下,PCA 最优地找到了可以非常有效地聚类相似分布的主成分。
内核 PCA (KPCA)
我们之前描述的 PCA 变换是线性变换,对于非线性分布无效。要处理非线性分布,基本思想是使用核技巧。
内核技巧只是一种将非线性数据投影到更高维度空间并分离不同数据分布的方法。一旦分布被分离,我们可以使用主成分分析来线性分离它们。
Dimensionality reduction technique: KPCA | Source: Author
核 PCA 使用核函数ϕ来计算非线性映射的数据的点积。换句话说,函数ϕ通过创建原始特征的非线性组合,将原始 d 维特征映射到更大的 k 维特征空间。
假设数据集 x 包含两个特征 x1 和 x2:
应用内核技巧后,我们得到:
为了更直观地理解内核 PCA,让我们定义一个不能线性分离的特征空间。
from sklearn.datasets import make_circles
from sklearn.decomposition import KernelPCA
np.random.seed(0)
X, y = make_circles(n_samples=400, factor=.3, noise=.05)
现在,让我们绘制并查看我们的数据集。
plt.figure(figsize=(15,10))
plt.subplot(1, 2, 1, aspect='equal')
plt.title("Original space")
reds = y == 0
blues = y == 1
plt.scatter(X[reds, 0], X[reds, 1], c="red",
s=20, edgecolor='k')
plt.scatter(X[blues, 0], X[blues, 1], c="blue",
s=20, edgecolor='k')
plt.xlabel("$x_1$")
plt.ylabel("$x_2$")
Dimensionality reduction technique: KPCA | Source: Author
正如您在该数据集中看到的,这两个类不能线性分离。现在,让我们定义内核 PCA,看看它是如何分离这个特征空间的。
kpca = KernelPCA(kernel="rbf", fit_inverse_transform=True, gamma=10, )
X_kpca = kpca.fit_transform(X)
plt.subplot(1, 2, 2, aspect='equal')
plt.scatter(X_kpca[reds, 0], X_kpca[reds, 1], c="red",
s=20, edgecolor='k')
plt.scatter(X_kpca[blues, 0], X_kpca[blues, 1], c="blue",
s=20, edgecolor='k')
plt.title("Projection by KPCA")
plt.xlabel(r"1st principal component in space induced by $phi$")
plt.ylabel("2nd component")
Dimensionality reduction technique: KPCA | Source: Author
应用 KPCA 后,它能够线性分离数据集中的两个类。
奇异值分解
奇异值分解或 SVD 是实矩阵或复矩阵的因式分解方法。当处理稀疏数据集时,它是有效的;有许多零条目的数据集。这种类型的数据集通常出现在推荐系统、评级和评论数据集中,等等。
SVD 的思想是将形状 nXp 的每个矩阵分解成 A = USV T ,其中 U 是正交矩阵,S 是对角矩阵,(V^T也是正交矩阵。)
SVD 的优点是正交矩阵捕获了原始矩阵 A 的结构,这意味着当乘以其他数时,它们的属性不会改变。这可以帮助我们近似 a。
现在让我们用代码来理解 SVD。为了更好地理解该算法,我们将使用 scikit-learn 提供的人脸数据集。
from sklearn.datasets import fetch_lfw_people
lfw_people = fetch_lfw_people(min_faces_per_person=70, resize=0.4)
绘制图像以了解我们正在处理的内容。
X = lfw_people.images.reshape(img_count, img_width * img_height)
X0_img = X[0].reshape(img_height, img_width)
plt.imshow(X0_img, cmap=plt.cm.gray)
创建一个函数,以便于图像的可视化。
def draw_img(img_vector, h=img_height, w=img_width):
plt.imshow( img_vector.reshape((h,w)), cmap=plt.cm.gray)
plt.xticks(())
plt.yticks(())
draw_img(X[49])
在应用 SVD 之前,最好将数据标准化。
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler(with_std=False)
Xstd = scaler.fit_transform(X)
标准化后,这就是图像的外观。
值得注意的是,我们总是可以通过执行逆变换来恢复原始图像。
Xorig = scaler.inverse_transform(Xstd)
draw_img(Xorig[49])
现在,我们可以应用 NumPy 中的 SVD 函数,并将矩阵分解为三个矩阵。
from numpy.linalg import svd
U, S, VT = svd(Xstd)
为了检查这个函数是否有效,我们总是可以执行三个矩阵的矩阵乘法。
US = U*S
Xhat = US @ VT[0:1288,:]
Xhat_orig = scaler.inverse_transform(Xhat)
draw_img(Xhat_orig[49])
现在,让我们进行降维。为此,我们只需减少正交矩阵的特征数量。
Xhat_500 = US[:, 0:500] @ VT[0:500, :]
Xhat_500_orig = scaler.inverse_transform(Xhat_500)
draw_img(Xhat_500_orig[49])
我们可以进一步减少更多的功能,看看结果。
Xhat_100 = US[:, 0:100] @ VT[0:100, :]
Xhat_100_orig = scaler.inverse_transform(Xhat_100)
draw_img(Xhat_100_orig[49])
现在,让我们创建一个函数,允许我们减少图像的尺寸。
def dim_reduce(US_, VT_, dim=100):
Xhat_ = US_[:, 0:dim] @ VT_[0:dim, :]
return scaler.inverse_transform(Xhat_)
用不同数量的特征绘制图像。
dim_vec = [50, 100, 200, 400, 800]
plt.figure(figsize=(1.8 * len(dim_vec), 2.4))
for i, d in enumerate(dim_vec):
plt.subplot(1, len(dim_vec), i + 1)
draw_img(dim_reduce(US, VT, d)[49])
Dimensionality reduction technique: SVD | Source: Author
如你所见,第一幅图像包含最少数量的特征,但它仍然可以构建图像的抽象版本,随着我们增加特征,我们最终获得原始图像。这证明了 SVD 可以保留数据的基本结构。
非负矩阵分解(NMF)
NMF 是一种无监督的机器学习算法。当一个维数为 mXn 的非负输入矩阵 X 被提供给算法时,它被分解成两个非负矩阵 W 和 H 的乘积。W 的维数为 mXp,而 H 的维数为 pXn。
其中 Y = W.H
从上面的等式可以看出,要分解矩阵,我们需要最小化距离。最广泛使用的距离函数是平方 Frobenius 范数;这是欧几里德范数在矩阵上的扩展。
同样值得注意的是,这个问题通常是不可解的,这就是为什么它是近似的。事实证明,NMF 有利于数据集的基于部件的表示,即 NMF 提供了一种高效的、分布式表示、,并且可以帮助发现数据中感兴趣的结构。
让我们用代码来理解 NMF。我们将使用在 SVD 中使用的相同数据。
首先,我们将使模型符合数据。
from sklearn.decomposition import NMF
model = NMF(n_components=200, init='nndsvd', random_state=0)
W = model.fit_transform(X)
V = model.components_
NMF 需要一点时间来分解数据。一旦数据被分解,我们就可以可视化分解的组件。
num_faces = 20
plt.figure(figsize=(1.8 * 5, 2.4 * 4))
for i in range(0, num_faces):
plt.subplot(4, 5, i + 1)
draw_img(V[i])
Dimensionality reduction technique: NMF | Source: Author
从上图我们可以看出,NMF 捕捉数据底层结构的效率非常高。同样值得一提的是,NMF 只获取了线性属性。
NMF 的优势:
- 数据压缩和可视化
- 对噪声的鲁棒性
- 更容易理解
流形学习
到目前为止,我们已经看到了只涉及线性变换的方法。但是,当我们有一个非线性数据集时,我们该怎么办呢?
流形学习是一种无监督学习,旨在对非线性数据集进行降维。同样,scikit-learn 提供了一个由各种非线性降维技术组成的模块。我们可以通过这个命令调用这些类或技术:
from sklearn.manifold import TSNE, LocallyLinearEmbedding, SpectralEmbedding
t 分布随机邻居嵌入(t-SNE)
t-分布式随机邻居嵌入或 t-SNE 是一种非常适合数据可视化的降维技术。与简单地最大化方差的 PCA 不同,t-SNE 最小化两个分布之间的差异。本质上,它在低维空间中重建了高维空间的分布,而不是最大化方差,甚至没有使用核技巧。
我们可以通过三个简单的步骤对 SNE 霸王龙有一个高层次的了解:
- 它首先为高维样本创建一个概率分布。
- 然后,它为低维嵌入中的点定义了类似的分布。
- 最后,它试图最小化两个分布之间的 KL-散度。
现在我们用代码来理解一下。对于 SNE 霸王龙,我们将再次使用 MNIST 数据集。首先,我们导入 TSNE,然后导入数据。
from sklearn.manifold import TSNE
from sklearn.datasets import load_digits
digits = load_digits()
print(digits.data.shape)
for i in range(0,5):
plt.figure(figsize=(5,5))
plt.imshow(digits.images[i])
plt.show()
Dimensionality reduction technique: t-SNE | Source: Author
然后我们将使用 np.vstack 按顺序存储这些数字。
X = np.vstack([digits.data[digits.target==i] for i in range(10)])
Y = np.hstack([digits.target[digits.target==i] for i in range(10)])
我们将对数据集应用 t-SNE。
digits_final = TSNE(perplexity=30).fit_transform(X)
我们现在将创建一个函数来可视化数据。
def plot(x, colors):
palette = np.array(sb.color_palette("hls", 10))
f = plt.figure(figsize=(8, 8))
ax = plt.subplot(aspect='equal')
sc = ax.scatter(x[:,0], x[:,1], lw=0, s=40,c=palette[colors.astype(np.int)])
txts = []
for i in range(10):
xtext, ytext = np.median(x[colors == i, :], axis=0)
txt = ax.text(xtext, ytext, str(i), fontsize=24)
txt.set_path_effects([pe.Stroke(linewidth=5, foreground="w"),
pe.Normal()])
txts.append(txt)
return f, ax, txts
现在,我们对转换后的数据集执行数据可视化。
plot(digits_final,Y)
Dimensionality reduction technique: t-SNE | Source: Author
可以看出,SNE 霸王龙对数据进行了完美的聚类。与 PCA 相比,t-SNE 在非线性数据上表现良好。t-SNE 的缺点是,当数据很大时,它会消耗大量的时间。所以最好先进行主成分分析,然后再进行 t-SNE。
局部线性嵌入(LLE)
局部线性嵌入或 LLE 是一种非线性和无监督的降维机器学习方法。LLE 利用数据的局部结构或拓扑,并将其保存在低维特征空间中。
LLE 优化速度更快,但在噪音数据上失败。
让我们将整个过程分成三个简单的步骤:
- 找到数据点的最近邻。
- 通过将每个数据点近似为其 k 个最近邻点的加权线性组合并最小化它们与其线性表示之间的平方距离来构建权重矩阵。
- 通过使用基于特征向量的优化技术将权重映射到低维空间。
Dimensionality reduction technique: LLE | Source: S. T. Roweis and L. K. Saul, Nonlinear dimensionality reduction by locally linear embedding
Dimensionality reduction technique: LLE | Source: Scikit Learn
光谱嵌入
谱嵌入是另一种非线性降维技术,也是一种无监督的机器学习算法。谱嵌入旨在基于低维表示找到不同类别的聚类。
我们可以再次将整个过程分成三个简单的步骤:
- 预处理:构建数据或图形的拉普拉斯矩阵表示。
- 分解:计算构造好的矩阵的特征值和特征向量,然后将每个点映射到一个更低维的表示上。谱嵌入利用了第二小特征值及其对应的特征向量。
- 聚类:根据表示法,将点分配给两个或多个聚类。聚类通常使用 k-means 聚类来完成。
应用:光谱嵌入在图像分割中得到应用。
判别分析
判别分析是 scikit-learn 提供的另一个模块。可以使用以下命令调用它:
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
线性判别分析(LDA)
LDA 是一种算法,用于查找数据集中要素的线性组合。像 PCA 一样,LDA 也是一种基于线性变换的技术。但与 PCA 不同,它是一种监督学习算法。
LDA 计算方向,即可以创建决策边界并最大化多个类之间的分离的线性判别式。对于多类分类任务也非常有效。
为了对 LDA 有一个更直观的理解,考虑绘制两个类的关系,如下图所示。
解决这个问题的一种方法是将所有数据点投影到 x 轴上。
这种方法会导致信息丢失,而且是多余的。
更好的方法是计算数据中所有点之间的距离,并拟合一条穿过这些点的新直线。这条新线现在可以用来投影所有的点。
这条新线最小化了方差,并通过最大化两个类之间的距离来有效地对它们进行分类。
LDA 也可以用于多元数据。它使数据推断变得非常简单。可以使用以下 5 个步骤计算 LDA:
- 计算数据集中不同类别的 d 维均值向量。
- 计算散布矩阵(类间和类内散布矩阵)。散布矩阵用于估计协方差矩阵。当协方差矩阵难以计算或者两个随机变量的联合可变性难以计算时,就要这样做。
- 计算散布矩阵的特征向量(e1,e2,e3…ed)和相应的特征值(λ1,λ2,…,λd)。
- 将特征向量按特征值递减排序,选择 k 个特征值最大的特征向量,形成 d×k 维矩阵 W(其中每列代表一个特征向量)。
- 使用这个 d×k 特征向量矩阵将样本变换到新的子空间上。这可以通过矩阵乘法来概括:Y=X×W(其中 X 是表示 n 个样本的 n×d 维矩阵,Y 是新子空间中的变换后的 n×k 维样本)。
要了解 LDA,你可以看看这篇文章。
降维的应用
降维在许多实际应用中都有应用,其中包括:
- 客户关系管理
- 文本分类
- 图像检索
- 入侵检测
- 医学图像分割
降维的利与弊
降维的优势:
- 它通过减少特征来帮助数据压缩。
- 它减少了存储。
- 它使机器学习算法在计算上高效。
- 它还有助于移除多余的特征和噪声。
- 它解决了维度的诅咒
降维的缺点:
- 这可能会导致一些数据丢失。
- 准确性大打折扣。
最后的想法
在本文中,我们学习了降维以及维数灾难。我们通过数学细节和代码讨论了降维中使用的不同算法。
值得一提的是,这些算法应该根据手头的任务来使用。例如,如果你的数据是线性的,那么使用分解方法,否则使用流形学习技术。
首先将数据可视化,然后决定使用哪种方法,这被认为是一种良好的做法。此外,不要把自己局限在一种方法上,而是探索不同的方法,看看哪一种是最合适的。
我希望你从这篇文章中学到了一些东西。快乐学习。
参考
- 降维介绍–GeeksforGeeks
- 机器学习降维介绍
- 主成分分析:回顾与最新进展
- Python 中的线性判别分析|作者 Cory Maklin
- 在机器学习模型中使用稀疏特征
- 必知:什么是维度的诅咒?
- 维数灾难和初学者应该如何克服它
- Python 的 6 种降维算法
- 硬化 API 参考
- t 分布随机邻居嵌入
- 特征选择和提取
分布式培训:要避免的错误
原文:https://web.archive.org/web/https://neptune.ai/blog/distributed-training-errors
在这个大型语言模型(LLM)、整体基础模型和日益庞大的数据集的时代,分布式训练是必须的,因为数据和模型权重很少适合单台机器。然而,ML 中的分布式训练是复杂且容易出错的,有许多隐藏的陷阱,会在模型训练过程中引起巨大的问题。幸运的是,机器学习框架,如 PyTorch 分布式数据并行和 Ray,已经抽象出了许多混乱的细节,但分布式训练仍然很有可能出错。
本文将触及分布式模型训练中十个最常见的错误,并对每个错误提出解决方案。
不是流水线
问题
在模型并行分布式训练设置中,每个阶段(除了正向训练中的第一阶段)都依赖于位于单独机器上的层的输出,反向训练也是如此,只是顺序相反。这可能不是最有效的方法。PipeDream 论文中的下图说明了这一点。该示意图中的所有灰色方框代表机器处于闲置状态且不执行任何有用功的时间单位。
Model parallel distributed training setup with 4 machines | Source
解决方案
流水线背后的思想是通过让每台机器在将输出发送到下一台机器后立即在一个新的迷你批处理上开始计算来减少浪费的工作量。这意味着,在更新权重之前,将并行训练多个小批量,这可能会影响算法的收敛性,但正如第一节中所讨论的,权重堆叠等技术可以减少这种影响。
在一定数量的小批量进入流水线进行训练后,流水线将达到所谓的稳定状态,在该状态下,所有机器在每个时间单位内都在工作。下图显示了流水线如何显著提高计算资源的利用率。显然,不流水线化会导致利用不足和更长的分布式训练时间。
An example distributed pipeline with 4 machines | Source
不平衡的管道阶段
问题
基于对流水线的讨论,确保你的流水线是平衡的很重要。这些图表是在作出天真的假设之前显示的,假设每台机器在完全相同的时间内对一批数据执行其模型分区的向前/向后传递。实际上,这种情况从来不会发生,因此会有一段短暂的时间,要么一台机器处于空闲状态,等待来自前一台机器的下一个微批处理,要么比其他机器花费更长的时间来执行其计算,从而降低流水线的速度。
解决方案
理想情况下,您应该构建您的管道,使每台机器尽可能执行相同的计算量。这意味着确定数据通过模型中不同层所需的时间,确定每个模型分区向前和向后传播所需的时间,并确保小批量数据的大小大致相等。这对于优化管道效率至关重要。
重量陈旧
问题
权重陈旧用于描述深度学习模型流水线训练中出现的一种现象。当模型训练在多台机器上流水线化时,在对数据进行正向计算的时间和基于该计算的梯度被反向传播以更新模型权重的时间之间会发生延迟。实际上,在一些训练步骤之后,使用比通过管道向后传递的梯度老一定数量周期的权重来计算模型正向预测。这种延迟被称为“重量老化”。。
解决方案
有几种方法可以解决体重老化的问题。第一种是通过在每一定数量的步骤后相互传递梯度来简单地同步机器。这限制了权重变得陈旧的程度。然而,它降低了硬件效率,因为同步机器导致某些机器必须等待其他机器到达相同的状态。所以对于减少训练时间并不理想。
或者,在一个名为*PipeDream的方法中,研究人员引入了一种称为重量存储的技术,其中一个系统“维护模型重量的多个版本,每个迷你批次一个”。?每次向前传递完成后,系统可以将模型的重量存储为与该微型批次相关的状态的一部分。当到了反向传播的时候,与该小批相关联的权重被从存储中检索并用于梯度计算。这确保了在流水线级内的单个数据小批上的前向和后向传递使用相同版本的权重,并且改善了统计收敛。*
*## 需要数据并行时使用模型并行(反之亦然)
问题
分布式训练的两种主要范式是模型并行和数据并行。在模型并行中,大型模型分布在多台机器上。例如,您可以将模型的第 1-4 层放在机器 1 上,第 5-8 层放在机器 2 上,第 9-12 层放在机器 3 上,依此类推。这种训练模式正变得越来越普遍,因为大型语言模型,如具有数十亿模型参数的 GPT-3,开始超过可以在商用硬件上存储完整模型的大小。在训练期间,数据和梯度在机器之间进行通信。
相反,在数据并行范例中,完整的模型存储在每台机器上,但是每台机器被分配来仅在完整数据集的子集上训练该模型。当您的完整数据集不适合一台机器时,或者如果您有多台机器都适合您的单一模型并希望减少您的训练时间,这将非常有用。模型权重和梯度在训练期间被传达。还存在混合模式类型的训练,其中数据和模型并行被串联使用以获得两个世界的最佳效果。
解决方案
显然,选择模型或数据并行对于使正确的培训方法适合您的环境是很重要的。如果您正在训练一个无法在单台机器上安装的非常大的模型,您将需要选择一个并行模型。如果您有一个非常大的训练集,可以很容易地跨计算机进行分区,请选择数据并行。最后,如果您的模型和数据集都太大而无法在一台机器上运行,您应该考虑使用混合模式的训练范例。
机器之间的驱动程序和库不一致
问题
在理想情况下,分布式训练脚本可以在同类机器上完美运行,但现实并非如此。当机器被设置为使用不兼容版本的硬件、驱动程序和库时,经常会出现意外错误。例如,如果您的分布式训练机器学习脚本是使用 PyTorch 实现的,那么您应该确保每台机器都安装了相同版本的 PyTorch。类似地,您可能希望每台机器都使用 CUDA 的兼容版本,尽管这并不是一个严格的要求,因为大多数分布式培训库都能够与不同的 CUDA 版本进行接口。
解决方案
在所有机器上标准化您的培训环境的一个简单方法是使用一个容器化解决方案,例如 Docker 。Docker 将您的分布式培训脚本与运行它所需的所有操作系统定义、库、工具和文件打包在一起。容器也是轻量级的,这意味着一旦构建了容器映像,运行它们就不需要太多的开销。使用容器或类似的虚拟化解决方案,您可以确保您的运行时环境在不同的机器上是一致的,并避免许多可能来自软件设置不兼容的麻烦和摩擦。
使用错误类型的 SGD
大多数机器学习模型使用优化算法进行训练,通常是随机梯度下降的某种变体。在分布式设置中,有两种主要的方法来制定 SGD,同步或异步。
问题
在同步 SGD 中,每台机器一前一后地执行其权重更新。这意味着每台机器计算其数据部分的梯度,将它们传输到其他机器,然后等待所有其他机器发送它们的梯度。只有在从所有其他机器接收到梯度之后,每台机器才执行其反向传播并更新其权重。这样,每台机器上的重量保持同步,防止重量过时。然而,这样做需要在每个小批量训练结束时强加一个硬屏障,这会导致速度变慢,特别是如果有一些落后的机器比其他机器花费更长的时间来执行它们的计算。
解决方案
实际上,异步 SGD 对于分布式培训来说是一个非常好的选择。也许最著名的异步 SGD 是 HogWild ,它表明 SGD 可以并行运行,没有锁,并且对算法收敛没有太大影响。异步 SGD 允许重量更新继续进行,而无需每台机器等待另一台机器发送梯度。实际上,这意味着仅使用部分信息进行权重更新,因为每台机器只能访问从其训练数据子集导出的梯度。然而,在实践中,可以使用简单的策略来确保算法仍然收敛。
网络问题、防火墙、端口和通信错误
问题#1
计算机之间的通信,尤其是通过网络的通信,是分布式训练的核心。当然,网络通信也带来了许多潜在的问题,如丢包、网络攻击等。
分布式训练脚本的核心是被称为等级的机器的枚举。机器的等级是它在模型训练过程中涉及的所有机器的序列中的编号。通常,一台机器被分配等级 0,并负责处理其他机器之间的通信协调、发送数据和梯度的聚合等。其他机器通过网络将数据和梯度传递给等级不同的所有其他机器。如果某些事情没有处理好,这很容易出错。
解决方案
当向不同级别的机器发送数据时,一个进程必须指定 IP 地址和端口号,通过这些地址和端口号来传输该信息。本规范中的任何错误都将明显导致培训过程中的失败。类似地,如果防火墙或其他网络配置设置阻止指定端口上的通信,那么接收机器将永远无法获得必要的数据。因此,确保网络被正确配置并且在训练脚本中被正确指定是运行分布式训练机器学习设置的先决条件。
问题二
NCCL 和 Gloo 是 PyTorch 分布式包使用的两个库,用于在分布式训练期间在机器之间传递数据和模型参数。机器之间定期共享重量和数据对于完全训练功能模型至关重要。不幸的是,当在分布式环境中工作时,单机故障是常见的,并且经常在没有任何明显原因的情况下发生。例如,一台(或多台)机器可能会耗尽 RAM,其硬盘可能会自动出现故障,或者可能会受到网络或电源中断的影响。
在这些情况下,当另一台机器试图从故障机器接收数据时,NCCL 或 GLOO 可能会显示神秘的错误消息。这些错误是如此普遍和令人困惑,以至于 Github 的整个问题都致力于解决它们。
解决方案
有一些参数设置可以帮助提高错误的可读性(例如,设置 NCCL _ 调试=警告),但无论如何,这并不能完全解决问题。
不幸的是,这类问题是分布式系统编程的一部分。用于解决这类错误的分布式培训最佳实践包括在培训期间进行频繁备份(定期保存模型权重的快照)、编写可用于追踪错误来源的详细日志,以及确保硬件得到良好维护(在当前的云计算时代,这不是什么问题)。
慢速数据传输
问题
RPC 或远程过程调用是跨网络通信的基本元素。在分布式训练 ML 设置中,当在网络上运行强化学习代理时,可能会产生RPC。类似地,当在机器之间发送梯度和层输出时,进行网络传输。一般来说,您希望尽可能避免创建 RPC 或通过网络发送它们,因为网络通信可能会很慢且成本很高,尤其是在您有大量数据要传输的情况下。许多分布式训练错误也源于网络问题,因此减少对网络的依赖也可以减少遇到的错误数量。当然,你不能完全避免使用网络,但要注意不要轻率地使用网络。
解决方案
在您绝对需要在机器之间传输数据的情况下,您可以做许多事情来加速这个过程。首先,您可以使用专用硬件来促进网络传输。这可以包括使用通过高速互连连接的工作机,以及使用 Nvlink 在 Nvidia GPUs 之间传输数据。
您还可以降低传输的渐变的浮点精度,以减少传输的数据量。从 fp32 到 fp16 甚至 fp8 会对速度产生重大影响。但是要小心,它也会影响算法的收敛,所以要明智地使用它!
最后,一旦计算出梯度的子集(即发送单个层的梯度),就可以传输它们,同时在后续层上执行反向传播。将数据传输与反向传播重叠是另一种形式的流水线操作,可以确保网络得到更有效的利用。这可以加快整体梯度传输时间,并防止网络饱和。
日志记录不足
问题
当在分布式设置中训练时,记录数据对于调试尤其重要。因为在分布式训练设置中有如此多的潜在故障点,所以在训练过程中的多个阶段应该小心地写详细的日志,以便当错误确实发生时,它们可以被定位并容易地追溯到源头。特别是,应该记录所有主要的分布式操作,例如当数据在机器之间通信时,当执行重量更新时,等等。最后,日志应该是可搜索的和容易访问的。做所有这些确保了当分布式训练错误发生时,可以容易地追溯到源头,并且可以最小化系统的停机时间。
解决方案
MLOps 工具,比如 neptune.ai ,可以让你自动记录所有相关的元数据,比如指标、参数、学习率和分布式训练设置中的变量。由于灵活的元数据结构,您可以登录到四个不同的对象:运行、模型、模型版本和项目,并根据需要组织元数据。
你可以稍后查看你在 Neptune web 应用中记录的所有内容,例如,在仪表板中,如下图所示。
查看本教程,了解如何使用 Neptune 跟踪分布式培训工作。它包括:
- 跟踪单节点多 GPU 作业
- 跟踪多节点 DDP 作业
您还可以查看关于使用带有流水线库的 Neptune 的文档。
云计算超支
问题
分布式培训通常涉及使用云提供商,如 AWS 或 GCP。如果你不小心,使用这些云服务很容易每月产生数百甚至数千美元的账单。
解决方案
为了降低成本,你可以做的第一件事就是使用 spot 或可抢占实例。简而言之,这些例子通常要便宜得多,因为你考虑到了你的工作在培训期间被抢占或中断的可能性。如果您确实使用了 spot 实例,那么定期检查您的训练或者使用诸如 Elastic Horovod 之类的容错解决方案以防您的实例在训练过程中关闭是非常重要的。
同样重要的是,不要选择超出您需要的计算资源。例如,如果您为每个实例分配一个 64GB 的 GPU,这可能是多余的,因为您已经在分布式设置中工作了。使用更少的资源使用更多的实例可能比使用两到三个使用非常昂贵的 GPU 的大型实例更便宜。事先执行这种成本效益分析可以缩短您的培训时间,并降低与您想要的云提供商一起完成培训所需的成本。
结论和要点
分布式模型训练具有挑战性,并且涉及到管理各种各样的错误。虽然有些错误是不可避免的,但最好避免在分布式环境中训练时出现的陷阱和常见的机器学习陷阱。
与流水线相关的问题,例如不平衡的阶段或模型或数据并行的不正确选择,或者根本没有流水线,可以否定分布式训练的优势。类似地,网络相关的问题也会出现,当生成太多的 RPC,以及不正确地配置防火墙或 IP 地址时,培训会大大减慢速度。同时,其他问题,如权重过时或选择错误类型的分布式 SGD 会对算法收敛性产生负面影响。
通过避免这些常见的分布式训练错误,您可以确保通过利用分布式训练的力量,朝着训练非常大和复杂的机器学习模型的正确方向开始。
参考
https://arxiv.org/pdf/1806.03377.pdf
- https://towards data science . com/a-guide-to-highly-distributed-dnn-training-9e 4814 FB 8 BD 3
- https://towardsdatascience.com/a-guide-to-highly-distributed-dnn-training-9e4814fb8bd3*
分布式培训:框架和工具
原文:https://web.archive.org/web/https://neptune.ai/blog/distributed-training-frameworks-and-tools
深度学习的最新发展已经带来了一些令人着迷的最新成果,特别是在自然语言处理和计算机视觉等领域。成功的几个原因通常来自于大量数据的可用性和不断增长的深度学习(DL)模型。这些算法能够提取有意义的模式,并推导出输入和输出之间的相关性。但开发和训练这些复杂的算法可能需要几天,有时甚至几周,这也是事实。
为了解决这个问题,需要一种快速有效的方法来设计和开发新的模型。人们不能在单个 GPU 上训练这些模型,因为这将导致信息瓶颈。为了解决单核 GPU 上的信息瓶颈问题,我们需要使用多核 GPU。这就是分布式培训的想法出现的地方。
在本文中,我们将研究一些用于分布式培训的最佳框架和工具。但在此之前,让我们快速了解一下分布式培训本身。
分布式培训
DL 训练通常依赖于可伸缩性,可伸缩性简单地意味着 DL 算法学习或处理任意数量数据的能力。本质上,任何 DL 算法的可扩展性取决于三个因素:
- 1 深度学习模型的规模和复杂性
- 2 训练数据量
- 3 包括 GPU 和存储单元等硬件在内的基础设施的可用性,以及这些设备之间的平稳集成
分布式训练满足所有三个要素。它负责模型的大小和复杂性,批量处理训练数据,并在称为节点的多个处理器中拆分和分布训练过程。更重要的是,它大大减少了训练时间,使得迭代时间更短,从而使得实验和部署更快。
分布式培训有两种类型:
1 数据并行训练
2 模型-平行训练
Distributed training model parallelism vs data parallelism | Source
在数据并行训练中,数据根据可用于训练的节点数量划分为子集。并且在所有可用节点中共享相同的模型架构。在训练过程中,所有节点必须相互通信,以确保每个节点的训练相互同步。这是训练模型最有效的方法,也是最常见的做法。
在模型并行训练中,DL 模型根据可用节点的数量被分割成多个部分。每个节点都被馈送相同的数据。在模型并行训练中,DL 模型本身被分成不同的段,然后每个段被馈送到不同的节点。如果 DL 模型具有可以单独训练的独立组件,则这种类型的训练是可能的。请记住,每个节点必须在模型不同部分的共享权重和偏差方面保持同步。
在这两种类型的培训中,数据并行性是非常常用的,当我们发现分布式培训的框架时,您会发现无论模型并行性如何,它们都提供数据并行性。
为分布式培训选择正确框架的标准
在我们深入研究框架之前,在选择正确的框架和工具时,有几点需要考虑:
- **计算图类型:**整个深度学习社区主要分为两派,一派使用 PyTorch 或动态计算图,另一派使用 TensorFlow 或静态计算图。因此,大多数分布式框架都建立在这两个库之上已经不是什么新闻了。所以,如果你喜欢其中一个,那么你已经做了一半的决定。
- 培训成本:当您处理分布式计算时,负担能力是一个关键问题,例如,一个涉及 BigGAN 培训的项目可能需要大量的 GPU,成本可能会随着数量的增加而成比例增加。因此,价格适中的工具总是正确的选择。
- 培训类型:根据您的培训需求,即数据并行或模型并行,您可以选择其中一种工具。
- 效率:这个基本上是指你需要写多少行才能启用分布式训练,越少越好。
- 灵活性:你选择的框架可以跨平台使用吗?尤其是当你需要在内部或者云平台上进行培训的时候。
分布式培训框架
现在,让我们讨论一些提供分布式培训的图书馆。
在 Neptune 中,你可以跟踪来自许多进程的数据,特别是在不同机器上运行的数据。
1. PyTorch
Distributed training: PyTorch | Source
PyTorch 是脸书开发的最流行的深度学习框架之一。它是最灵活、最容易学习的框架之一。PyTorch 允许您非常有效地创建和实现神经网络模块,通过其分布式训练模块,您可以用几行代码轻松实现并行训练。
PyTorch 提供了多种执行分布式培训的方法:
- nn。DataParallel : 这个包可以让你在一台有多个 GPU 的机器上进行并行训练。一个优点是它需要最少的代码。
- nn。DistributedDataParallel :这个包允许你在多台机器内跨多个 GPU 进行并行训练。配置培训流程还需要一些额外的步骤。
- torch . distributed . RPC**:**这个包允许你执行模型并行策略。如果您的模型很大,并且不适合单个 GPU,这将非常有效。
优势
- 很容易实现。
- PyTorch 非常用户友好。
- 提供现成的数据并行和模型并行方法。
- 大多数云计算平台都支持 PyTorch。
什么时候用 PyTorch?
在以下情况下,您应该选择 PyTorch:
- 你有大量的数据,因为数据并行很容易实现。
Distributed training: DeepSpeed | Source
PyTorch 分布式培训专门研究数据并行。DeepSpeed 构建于 PyTorch 之上,目标是其他方面,即模型并行性。DeepSpeed 由微软开发,旨在为大规模模型提供分布式训练。
当训练具有数万亿个参数的模型时,DeepSpeed 可以有效地应对内存挑战。它减少了内存占用,同时保持了计算和通信效率。有趣的是,DeepSpeed 提供了 3D 并行性,通过它你可以分发数据、模型和管道,这基本上意味着现在你可以训练一个大型的、消耗大量数据的模型,就像 GPT-3 或图灵 NLG 一样。
优势
- 模型扩展到数万亿个参数。
- 训练速度提高 10 倍。
- 民主化人工智能,这意味着用户可以在单个 GPU 上运行更大的模型,而不会耗尽内存。
- 压缩训练允许用户通过减少计算注意力操作所需的内存来训练注意力模型。
- 易学易用。
何时使用 DeepSpeed?
在以下情况下,您应该选择 DeepSpeed:
- 你想做数据和模型并行。
- 如果你的代码库是基于 PyTorch 的。
Distributed training: TensorFlow | Source
TensorFlow 由 Google 开发,它支持分布式训练。它使用数据并行技术进行训练。您可以通过使用 tf.distribute API 来利用 TensorFlow 上的分布式培训。该 API 允许您根据自己的需求配置培训。默认情况下,TensorFlow 只使用一个 GPU,但 tf.distribute 允许您使用多个 GPU。
TensorFlow 提供了三种主要类型的分布式培训策略:
TF . distribute . mirroredstrategy():这个简单的策略允许你在一台机器上的多个 GPU 之间分配训练。这种方法也称为同步数据并行。值得注意的是,每个工人节点将有自己的一套梯度。这些梯度然后被平均并用于更新模型参数。
TF . distribute . multiworkermirroredstrategy():这个策略允许你将训练分布到多台机器和单台机器上的多个 GPU 上。所有操作都类似于 tf.distribute.MirroredStrategy()。这也是一种同步数据并行方法。
TF . distribute . experimental . parameter server strategy():这是一种异步数据并行方法,在多台机器上按比例放大模型训练是常见的做法。在这种策略中,参数存储在参数服务器中,工人相互独立。这种策略可以很好地扩展,因为工作节点不需要等待彼此的参数更新。
优势
- 巨大的社区支持。
- 这是一个静态的编程范例。
- 与谷歌云和其他基于云的服务非常好地集成。
什么时候使用分布式张量流?
您应该使用分布式张量流:
- 如果要做数据并行。
- 如果你喜欢与动态相比的静态编程范式。
- 如果你在谷歌云生态系统中,因为 TensorFlow 针对 TPU 进行了很好的优化。
- 最后,如果您有大量数据并且需要高处理能力。
Distributed training: TensorFlow | Source
Mesh Tensorflow 也是 Tensorflow 分布式训练的扩展,但专门设计用于在张量处理单元(TPUs)上训练大型 DL 模型,AI 加速类似于 GPU,但速度更快。虽然 Mesh TensorFlow 可以执行数据并行,但它旨在解决参数无法在一台设备上安装的大型模型的分布式训练。
Mesh TensorFlow 受同步数据并行方法的启发,即每个工人都参与每个操作。除此之外,所有的工人将有相同的程序,它使用像 Allreduce 集体沟通。
优势
- 它可以训练具有数百万和数十亿参数的大型模型,如:GPT-3,GPT-2,伯特,等等。
- 工作人员潜在的低延迟。
- 良好的 TensorFlow 社区支持。
- 谷歌 TPU 豆荚的可用性。
什么时候使用网格张量流?
应该使用网格张量流:
- 如果你想做模型并行。
- 如果你想开发巨大的模型和实践快速成型。
- 如果您特别是在处理大量数据的自然语言处理领域工作。
Distributed training: TensorFlow | Source
Apache Spark 是最知名的开源大数据处理平台之一。它允许用户进行各种与数据相关的工作,如数据工程、数据科学和机器学习。我们已经知道张量流是什么了。但是如果你想在 Apache Spark 上使用 TensorFlow,那么你必须使用 TensorFlowOnSpark。
TensorFlowOnSpark 是一个机器学习框架,允许您在 Apache Spark 集群和 Apache Hadoop 上执行分布式训练。它是由雅虎开发的。该框架允许分布式训练和推理,对共享网格上的现有 TensorFlow 代码进行最小的代码改变。
优势
- 允许使用现有 TensorFlow 程序轻松迁移到 Spark 集群。
- 代码中的更改更少。
- 所有 TensorFlow 功能都可用。
- Spark 和 TensorFlow 可以分别高效地推送和拉取数据集。
- 云开发在 CPU 或 GPU 上简单高效。
- 可以轻松创建培训管道。
何时使用 TensorFlowOnSpark?
您应该使用 TensorflowOnSpark:
- 如果您的工作流基于 Apache Spark,或者您更喜欢 Apache Spark。
- 如果你的首选框架是 TensorFlow。
Distributed training: BigDL | Source
BigDL 也是 Apache Spark 分布式培训的开源框架。它是由英特尔开发的,允许 DL 算法运行 Hadoop 和 Spark 集群。BigDL 的一大优势是,它可以帮助您轻松地构建和处理端到端管道中的生产数据,用于数据分析和深度学习应用程序。
BigDL 提供了两个选项:
- 您可以像使用 Apache Spark 为数据工程、数据分析等提供的任何其他库一样直接使用 BigDL。
- 您可以在 Spark 生态系统中横向扩展 python 库,如 PyTorch、TensorFlow 和 Keras。
优势
- 端到端管道:如果您的大数据杂乱而复杂,这通常是在实时数据流的情况下,那么采用 BigDL 是合适的,因为它在端到端管道中集成了数据分析和深度学习。
- 效率:Spark BigDL 采用跨不同组件的集成方法,使得所有组件的开发、部署和运营直接、无缝且高效。
- 通信和计算:由于所有的硬件和软件都是缝合在一起的,所以它们运行流畅,没有任何中断,使得不同工作流之间的通信清晰,计算速度更快。
什么时候使用 BigDL?
您应该使用 BigDL:
- 如果您想开发一个 Apache Spark 工作流,
- 如果您的首选框架是 PyTorch。
- 如果你想持续集成所有组件,如数据挖掘、数据分析、机器学习等等。
Distributed training: Horovod | Source
Horovod 是优步在 2017 年推出的。这是一个开源项目,专门用于分布式培训。它是米开朗基罗的内部组件,米开朗基罗是优步用来实现其 DL 算法的深度学习工具包。Horovod 利用数据并行分布式培训,这使得扩展变得非常容易和高效。它还可以在大约 5 行 python 代码中扩展到数百个 GPU。这个想法是为单个 GPU 编写一个训练脚本,Horovod 可以将其扩展到多个并行的 GPU 上进行训练。
Horovod 是为 Tensorflow、Keras、Pytorch 和 Apache MXNet 等框架构建的。这是易于使用和快速。
优势
- 如果熟悉 Tensorflow、Keras、Pytorch 和 Apache MXNet,很容易学习和实现。
- 如果您使用 Apache Spark,那么您可以在一个管道上统一所有的进程。
- 良好的社区支持。
- 它很快。
何时使用 Horovod?
您应该使用 Horovod:
- 如果您希望在多个 GPU 之间快速扩展单个 GPU 脚本。
- 如果你使用微软 Azure 作为你的云计算平台。
Distributed training: Ray | Source
Ray 是构建在 Pytorch 之上的另一个用于分布式培训的开源框架。它提供了在任何云提供商上启动 GPU 集群的工具。与我们迄今为止讨论的任何其他库不同,Ray 非常灵活,可以在任何地方工作,如 Azure、GCD、AWS Apache Spark 和 Kubernetes。
Ray 在其捆绑包中提供了以下库,用于超参数调整、强化学习、深度学习、缩放等等:
- 调优:可伸缩超参数调优。
- RLlib :分布式强化学习。
- Train :分布式深度学习,目前测试版。
- 数据集:分布式数据加载和计算,目前处于测试版。
- 发球:可伸缩可编程发球。
- 工作流程:快速、持久的应用流程。
除了这些库之外,Ray 还集成了第三方库和框架,允许您以最少的代码更改来开发、培训和扩展您的工作负载。下面给出了集成库的列表:
- 气流
- 课堂视觉
- 达斯克
- 弗兰贝
- 霍罗沃德
- 拥抱面部变形金刚
- 英特尔分析动物园
- 约翰·斯诺实验室
- 莱特格姆
- 路德维希艾
- 三月
- 莫丁(莫丁)
- 插入记号
- PyTorch 闪电
- RayDP
- scikit 很少学习不在场证明
- XGBoost
- 优势
- 它支持 Jupyter 笔记本
它使您的代码在单台和多台机器上并行运行
- 它集成了多个框架和库。
- 它适用于所有主要的云计算平台
- 什么时候用雷?
- 你应该用雷:
如果你想进行分布式强化学习
如果您想要执行分布式超参数调整
- 如果您想在不同的机器上使用分布式数据加载和计算。
- 如果你想为你的应用服务。
- 分布式培训的云平台
- 到目前为止,我们已经讨论了可用于支持分布式培训的框架和库。现在,让我们来讨论和探索云平台,在这里您可以使用硬件来高效地训练您的 DL 模型。但在此之前,让我们列出一些标准,让您能够根据自己的需求选择最佳的云平台。
**硬件和软件支持:**学习和理解这些平台提供的硬件(如 GPU、TPU、存储单元等)非常重要。除此之外,你还应该看到他们提供的 API,这样(取决于你的项目)你就可以访问托管设施、容器、数据分析工具等等。
可用性区域:可用性区域是云计算中的一个重要因素,它为用户提供了在世界任何地方建立和部署项目的灵活性。用户也可以随时转移他们的项目。
- **定价:**平台是根据你的使用情况收费,还是提供基于订阅的模式。
- 现在,让我们讨论云计算选项。我们将讨论两个极其可行的即用型实验笔记本平台和三个最流行的云计算服务。
- Google Colab 是中小型项目中最可靠和最容易使用平台之一。Google Colab 的一个好处是,你可以轻松地连接到 Google Cloud,并且可以使用上面提到的任何 python 库。它提供三种型号:
Google Colab 是免费的,它可以让你访问 GPU 和 TPU。但是你可以使用有限的存储和内存。一旦其中任何一个超过,程序就会停止。
Magic quadrant for cloud infrastructure as a service | Source
Distributed training: Google Colab | Source
Google Colab Pro 是 Google Colab 的订阅版本,在这里你有额外的内存和存储空间。你可以运行一个很重的模型,但是它也是有限的。
- Google Colab Pro + 是一种基于订阅模式的新服务,也很贵。它提供了更快的 GPU 和 TPU 以及额外的内存,因此您可以在相当大的数据集上运行相当大的模型。
- 下面给出的是三者的官方对比。
- AWS SageMaker 是最受欢迎和最古老的分布式培训云计算平台之一。它与 Apache MXNet、Pytorch 和 TensorFlow 非常好地集成在一起,允许您轻松部署深度学习算法,并减少代码修改。SageMaker API 有 18+机器学习算法,其中一些算法是从零开始重写的,使整个过程变得可扩展和简单。这些内置算法经过优化,可以充分利用硬件。
SageMaker 还有一个集成的 Jupyter 笔记本,允许数据科学家和机器学习工程师在旅途中构建和开发管道算法,并允许您直接在托管环境中部署它们。您可以从 SageMaker Studio 或 SageMaker 控制台根据您的需求和偏好配置硬件和环境。所有的托管和开发都按照每分钟的使用量计费。
Distributed training: AWS SageMaker | Source
AWS SageMaker 提供数据并行和模型并行分布式培训。事实上,SageMaker 还提供了一种混合训练策略,在这种策略中,您可以同时使用模型和数据并行性。
谷歌云计算是谷歌在 2010 年开发的,旨在加强他们自己的平台,如谷歌搜索引擎和 Youtube。渐渐地,他们开始向公众开放源代码。谷歌云计算提供了所有谷歌平台使用的相同基础设施。
Google 云计算为 TensorFlow、Pytorch、Scikit-Learn 等库提供内置支持。此外,除了在工作流程中配置 GPU 之外,您还可以添加 TPU 来加快培训过程。就像我之前提到的,你可以将你的谷歌实验室连接到谷歌云平台,并访问它提供的所有功能。
Distributed training: AWS SageMaker | Source
Distributed training: Google Cloud Computing | Source
它提供的一些功能有:
计算(虚拟硬件,如 GPU 和 TPU)
储物桶,
- 数据库
- 建立工作关系网
- 管理工具
- 安全性
- 物联网
- API 平台
- 托管服务
- 值得注意的是,与 AWS 相比,GCP 的可用性区域较少,但成本也较低。
- 微软 Azure 是另一个非常受欢迎的云计算平台。OpenAI 的一个流行语言模型 GPT-3 就是在 Azure 中训练出来的。它还提供了数据并行和模型并行方法,并支持 TensorFlow 和 Pytorch。事实上,如果你想优化计算速度,你也可以利用优步的 Horovod。
Azure 机器学习服务面向编码人员和非编码人员。它只是提供了一个拖放方法,可以优化您的工作流程。它还通过自动机器学习减少了手动工作,可以帮助您开发更智能的工作原型。
Distributed training: Google Cloud Computing | Source: Author
Distributed training: Microsoft Azure | Source
Azure Python SDK 还允许您在任何 Python 环境中进行交互,如 Jupyter 笔记本、Visual Studio 代码等等。在提供服务方面,它与 AWS 和 GCP 非常相似。这些是 Azure 提供的服务:
人工智能、机器学习和深度学习
计算能力(GPU)
- 分析学
- 区块链
- 容器
- 数据库
- 开发者工具
- DevOps
- 物联网
- 混合现实
- 移动的
- 网络等等
- 让我们一起来比较一下这三个主要工具,让你在选择时有一个更好的视角。
- 云平台对照表
Distributed training: Microsoft Azure | Source
最后的想法
在本文中,我们看到了不同的库和工具,它们可以帮助您为自己的深度学习应用程序实现分布式培训。请记住,所有的库都是好的,并且在它们所做的事情上非常有效,最终,这一切都归结于您的偏好和需求。
Comparison table for cloud platform | Source
您一定已经注意到,所有讨论的框架都主要以某种方式集成了 Pytorch 和 TensorFlow。这个特质很容易帮你隔离选择的框架。一旦你的框架确定下来,你就可以看看它的优势,决定哪种分布式培训工具最适合你。
我希望你喜欢这篇文章。如果你想尝试我们讨论过的所有框架,那么请点击教程链接。
感谢阅读!
参考
Thanks for reading!