面向数据科学与新一代人工智能的 K8S

数据科学家和软件工程师有许多相同的关注点:可重复的实验(比如可重复的构建);可移植和可复制的环境(如在开发、过渡和生产环境中具有相同的设置);凭证管理;跟踪和监控生产环境中的指标;灵活的路由;轻松扩展。不难看出,应用程序开发人员使用 Kubernetes 所做的事情与数据科学家可能想做的事之间有一些类似之处:

  • 可重复的批处理作业,如 CI/CD 管道,类似于机器学习管道,多个协同阶段在其中以可重复的方式一起处理数据、提取特征、训练、测试和部署模型;
  • 描述服务之间连接的声明性配置有助于创建跨平台的可重复学习管道和模型;
  • 微服务架构支持在管道中对机器学习模型进行简单地调试,并帮助数据科学家和他们团队中的其他成员进行协作。

数据科学家与应用程序开发人员面临许多相同的挑战,但他们也面临一些独特的挑战,这些挑战与数据科学家的工作方式以及机器学习模型比传统服务更难测试和监控这一事实有关。我们将重点讨论一个与工作流相关的问题。

大多数数据科学家使用交互式笔记本(interactive notebooks)工作,这是一个笔记本环境,通常由 Project Jupyter 开发,提供一种交互式 迭代编程环境,用户可以在其中混合说明性本文和代码、运行并更改代码、检查其输出。

这些特性使得该环境对探索性分析非常灵活。然而,它们并不是用于协作或发布的理想软件工件——想象一下,如果软件开发人员发布工作的主要方式是将来自交互式 REPL 脚本发布到 pastebin 服务。

与同事分享交互式笔记本就像分享实体笔记本一样——里面有一些很好的信息,但是必须仔细查找才能找到。由于笔记本的脆弱性和对环境的依赖性,同事在运行笔记本时可能会看到不同的输出——甚至更糟:它可能会崩溃。

数据科学家可能不想成为 Kubernetes 专家——这很好!Kubernetes 的优点之一就是构建更高级工具的强大框架。

Binder 服务 就是其中一个工具,采用一个 Jupyter 笔记本的 Git 存储库,构建容器镜像来提供服务,然后在路由公开的 Kubernetes 集群中启动镜像,这样就可以从公网访问。由于笔记本的一大缺点是其正确性和功能可能依赖于其环境,因此,如果有一个高级工具可用来构建不可变环境为 Kubernetes 上的笔记本提供服务的话,就可以避免许多让人头疼的事。

你可以使用托管的 Binder 服务或 运行自己的 Binder 实例,但是,如果你想在这个过程中获得更大的灵活性,你还可以使用 Source-To-Image(S2I)工作流和工具,以及 Graham Dumpleton 提供的 Jupyter S2I 镜像 上线自己的笔记本服务。事实上,对于基础设施专家或打包专家来说,Source-To-Image 工作流是构建可供主题专家使用的高级工具的良好起点。例如,Seldon 项目 使用 S2I 来简化模型服务发布——只要向构建器提供一个模型对象,它将构建一个容器并将其作为服务公开。

Source-To-Image 工作流的一个优点是,它支持在构建映像之前对源存储库进行任意操作和转换。有个例子可以说明这个工作流有多强大,我们 创建了一个 S2I 构建器镜像,该镜像以一个 Jupyter 笔记本作为输入,该笔记本展示了如何训练模型。然后,它处理这个笔记本以确定它的依赖关系,并提取 Python 脚本来训练和序列化模型。有了这些,构建器就会安装必要的依赖项并运行脚本来训练模型。构建器的最终输出是一个 REST Web 服务,它为由笔记本构建的模型提供服务。你可以看下 notebook-to-model-service S2I 的运行 视频。同样,这不是数据科学家必须开发的工具,但是,创建这样的工具是 Kubernetes 专家和打包专家与数据科学家合作的绝佳机会。

机器学习项目完整工作流程

1. 抽象成数学问题

明确问题是进行机器学习的第一步。机器学习的训练过程通常都是一件非常耗时的事情,胡乱尝试时间成本是非常高的。这里的抽象成数学问题,指的我们明确我们可以获得什么样的数据,目标是一个分类还是回归或者是聚类的问题,如果都不是的话,如果划归为其中的某类问题。

2. 获取数据

数据决定了机器学习结果的上限,而算法只是尽可能逼近这个上限。数据要有代表性,否则必然会过拟合。而且对于分类问题,数据偏斜不能过于严重,不同类别的数据数量不要有数个数量级的差距。还要对数据的量级有一个评估,多少个样本,多少个特征,可以估算出其对内存的消耗程度,判断训练过程中内存是否能够放得下。如果放不下就得考虑改进算法或者使用一些降维的技巧了。如果数据量实在太大,那就要考虑分布式了。

3. 特征预处理与特征选择

良好的数据要能够提取出良好的特征才能真正发挥效力。特征预处理、数据清洗是很关键的步骤,往往能够使得算法的效果和性能得到显著提高。归一化、离散化、因子化、缺失值处理、去除共线性等,数据挖掘过程中很多时间就花在它们上面。这些工作简单可复制,收益稳定可预期,是机器学习的基础必备步骤。筛选出显著特征、摒弃非显著特征,需要机器学习工程师反复理解业务。这对很多结果有决定性的影响。特征选择好了,非常简单的算法也能得出良好、稳定的结果。这需要运用特征有效性分析的相关技术,如相关系数、卡方检验、平均互信息、条件熵、后验概率、逻辑回归权重等方法。

4. 训练模型与调优

直到这一步才用到我们上面说的算法进行训练。现在很多算法都能够封装成黑盒供人使用。但是真正考验水平的是调整这些算法的(超)参数,使得结果变得更加优良。这需要我们对算法的原理有深入的理解。理解越深入,就越能发现问题的症结,提出良好的调优方案。

5. 模型诊断

如何确定模型调优的方向与思路呢?这就需要对模型进行诊断的技术。过拟合、欠拟合判断是模型诊断中至关重要的一步。常见的方法如交叉验证,绘制学习曲线等。过拟合的基本调优思路是增加数据量,降低模型复杂度。欠拟合的基本调优思路是提高特征数量和质量,增加模型复杂度。误差分析也是机器学习至关重要的步骤。通过观察误差样本,全面分析误差产生误差的原因:是参数的问题还是算法选择的问题,是特征的问题还是数据本身的问题 …… 诊断后的模型需要进行调优,调优后的新模型需要重新进行诊断,这是一个反复迭代不断逼近的过程,需要不断地尝试,进而达到最优状态。

6. 模型融合

一般来说,模型融合后都能使得效果有一定提升。而且效果很好。工程上,主要提升算法准确度的方法是分别在模型的前端(特征清洗和预处理,不同的采样模式)与后端(模型融合)上下功夫。因为他们比较标准可复制,效果比较稳定。而直接调参的工作不会很多,毕竟大量数据训练起来太慢了,而且效果难以保证。

7. 上线运行

这一部分内容主要跟工程实现的相关性比较大。工程上是结果导向,模型在线上运行的效果直接决定模型的成败。不单纯包括其准确程度、误差等情况,还包括其运行的速度(时间复杂度)、资源消耗程度(空间复杂度)、稳定性是否可接受。

这些工作流程主要是工程实践上总结出的一些经验。并不是每个项目都包含完整的一个流程。这里的部分只是一个指导性的说明,只有大家自己多实践,多积累项目经验,才会有自己 。

MIT 全面解读 2019 深度学习最前沿课程

MIT 正在进行中的深度学习课程就全面描绘了当下的状态。最近一节课,Lex Fridman 老师展现了深度学习各方向的最领先状态,也回顾了过去两年间通往前沿的一步步进展。涉及自然语言处理、深度强化学习、训练和推断的加速等等。

这节课涉及的重大进展,共 12 个方面,分别是:

  • BERT 和自然语言处理(NLP
  • 特斯拉 Autopilot 二代(以上)硬件:规模化神经网络
  • AdaNet:可集成学习的 AutoML
  • AutoAugment:用强化学习做数据增强
  • 用合成数据训练深度神经网络
  • 用 Polygon-RNN++ 做图像分割自动标注
  • DAWNBench:寻找快速便宜的训练方法
  • BigGAN:最领先的图像合成研究
  • 视频到视频合成
  • 语义分割
  • AlphaZero 和 OpenAI Five
  • 深度学习框架

跨象乘云™ 提供 PPT 本地下载。

高效数据清洗 Python 代码

数据清洗,是进行数据分析和使用数据训练模型的必经之路,也是最耗费数据科学家/程序员精力的地方。大数据工程师 Kin Lim Lee 在 Medium 上发表了一篇文章,介绍了8个用于数据清洗的Python代码。这些用于数据清洗的代码有两个优点:一是由函数编写而成,不用改参数就可以直接使用。二是非常简单,加上注释最长的也不过 11 行。

1. 删除多列

在进行数据分析时,并非所有的列都有用,用 df.drop 可以方便地删除你指定的列。

def drop_multiple_col(col_names_list, df):
'''
AIM    -> Drop multiple columns based on their column names
INPUT -> List of column names, df
OUTPUT -> updated df with dropped columns
------
'''

df.drop(col_names_list, axis=1, inplace=True)
return df

2. 转换数据类型

当数据集变大时,需要转换数据类型来节省内存。

def change_dtypes(col_int, col_float, df):
'''
AIM    -> Changing dtypes to save memory
INPUT -> List of column names (int, float), df
OUTPUT -> updated df with smaller memory
------
'''

df[col_int] = df[col_int].astype('int32')
df[col_float] = df[col_float].astype('float32')

3. 将分类变量转换为数值变量

一些机器学习模型要求变量采用数值格式。这需要先将分类变量转换为数值变量。同时,你也可以保留分类变量,以便进行数据可视化。

def convert_cat2num(df):
# Convert categorical variable to numerical variable
num_encode = {'col_1' : {'YES':1, 'NO':0},
'col_2'  : {'WON':1, 'LOSE':0, 'DRAW':0}}
df.replace(num_encode, inplace=True)

4. 检查缺失数据

如果你要检查每列缺失数据的数量,使用下列代码是最快的方法。可以让你更好地了解哪些列缺失的数据更多,从而确定怎么进行下一步的数据清洗和分析操作。

def check_missing_data(df):
# check for any missing data in the df (display in descending order)
return df.isnull().sum().sort_values(ascending=False)

5. 删除列中的字符串

有时候,会有新的字符或者其他奇怪的符号出现在字符串列中,这可以使用df[‘col_1’].replace很简单地把它们处理掉。

def remove_col_str(df):
# remove a portion of string in a dataframe column - col_1
df['col_1'].replace('\n', '', regex=True, inplace=True)
# remove all the characters after &# (including &#) for column - col_1
df['col_1'].replace(' &#.*', '', regex=True, inplace=True)

6. 删除列中的空格

数据混乱的时候,什么情况都有可能发生。字符串开头经常会有一些空格。在删除列中字符串开头的空格时,下面的代码非常有用。

def remove_col_white_space(df):
# remove white space at the beginning of string
df[col] = df[col].str.lstrip()

7. 用字符串连接两列(带条件)

当你想要有条件地用字符串将两列连接在一起时,这段代码很有帮助。比如,你可以在第一列结尾处设定某些字母,然后用它们与第二列连接在一起。根据需要,结尾处的字母也可以在连接完成后删除。

def concat_col_str_condition(df):
# concat 2 columns with strings if the last 3 letters of the first column are 'pil'
mask = df['col_1'].str.endswith('pil', na=False)
col_new = df[mask]['col_1'] + df[mask]['col_2']
col_new.replace('pil', ' ', regex=True, inplace=True)  # replace the 'pil' with emtpy space

8. 转换时间戳(从字符串到日期时间格式)

在处理时间序列数据时,我们很可能会遇到字符串格式的时间戳列。这意味着要将字符串格式转换为日期时间格式(或者其他根据我们的需求指定的格式) ,以便对数据进行有意义的分析。

def convert_str_datetime(df):
'''
AIM    -> Convert datetime(String) to datetime(format we want)
INPUT -> df
OUTPUT -> updated df with new datetime format
------
'''

df.insert(loc=2, column='timestamp', value=pd.to_datetime(df.transdate, format='%Y-%m-%d %H:%M:%S.%f'))

Google 机器学习数据库:SageDB

近日,Google 联合 MIT、布朗大学的研究人员共同推出了新型数据库系统 SageDB,并撰写了一篇论文详述 SageDB 的设计原理和性能表现。他们在论文中提出了一个观点:学习模型可以渗透到数据库系统的各个方面 ——

基于机器学习的组件可以完全取代数据库系统的核心组件,例如索引结构、排序算法,甚至是查询执行器。

在 17 年的论文中,谷歌研究团队尝试通过实验论证:与基于缓存优化的 B-tree 结构相比,使用神经网络在速度上可以提高 70%,并且大大节省了内存。“机器学习模型有可能比目前最先进的数据库索引有更显著的好处”。而今天我们要介绍的 SageDB,就是研究团队在该研究基础之上得出的更进一步的成果。

SageDB 背后的核心思想是构建一个或多个关于数据和工作负载分布的模型,并基于它们自动为数据库系统的所有组件构建最佳数据结构和算法。我们称之为『数据库融合』的这种方法,将使我们能够通过将每个数据库组件的实现专门化到特定的数据库、查询工作负载和执行环境来实现前所未有的性能。

SageDB Overview
SageDB Overview