在 Python 类中构建“工厂”和“工具”
图片由 arturo meza olivares 从 Pixabay 拍摄
三个内置的 Python 类装饰器
如果您曾经使用过其他面向对象的编程语言,如 Java 或 C++,您可能对“静态方法”、“类方法”、“getter”和“setter”等概念很熟悉。事实上,Python 也有所有这些概念。
在本文中,我将介绍 Python 类的三个内置装饰器。他们会帮助我们
- 创建类范围的实用工具方法
- 为我们的类创建工厂设计模式
- 保护类中的重要属性
现在我们应该开始了。
1.静态法
图片来自 Pixabay
让我们跳过所有概念性的干货,直接从例子开始。假设我们需要定义一个名为“Employee”的类。我们应该保留员工的姓名,以及这个人是什么时候加入我们公司的。此外,我们希望通过显示该员工为我们工作的年数来检查资历。
最初,我们可以这样写。
这里我们仅有的逻辑是calc_year()
方法。它获取当前年份并减去该员工加入的年份。这应该是大于或等于零的整数。如果为零,则输出“不到一年”,而不是确切的年数。
declaration:这个逻辑很不理想,只是作为一个例子。不要误会:)
它会把工作做好的。
e1 = Employee('Chris', 2020)
e1.seniority()
然而,这是一个小问题。您注意到了吗,calc_year()
方法实际上并不需要类的实例才能工作。这也意味着“自我”作为一个论点是不必要的,因为它不需要这样的依赖。
因此,我们可以将函数从类中取出,如下所示。
这个也很好用。
好的。如果calc_year()
方法甚至可以被重用用于其他目的,那就更好了。然而,如果我们不需要它做其他用途呢?还有,在类之外有这样的函数是很难看的,如果它只服务于这个类的话。
因此,该方法被认为是该类的“实用方法”。换句话说,它应该被定义为一个静态方法。
如上面的代码所示,在 Python 中定义一个静态方法非常容易。当我们向方法添加装饰符@staticmethod
时,我们不再需要添加self
参数,因为静态方法不需要现有的实例起作用。
使用静态方法,我们可以在一个类中定义我们的实用方法,并保持代码整洁。
2.分类方法
那么,Python 中的类方法是什么?同样,比起解释概念,我更喜欢用例子来演示。
你用过 Python 中的datetime
模块吗?通常,我们可以使用datetime.datetime()
来创建一个datetime
对象。然而,还有更多不同的方法可以创建这样一个带有不同参数的对象。
- 日期时间.今天()
- datetime.now()
- datetime.utcnow()
- datetime.fromtimestamp()
- datetime.utcfromtimestamp()
- datetime.strptime()
- …
为什么它们可以接受不同的参数,但像__init__()
构造函数那样返回一个 datetime 对象?那是因为它们是类方法。类方法可以将当前类的引用作为参数,这样它就可以调用__init__()
构造函数。
让我们用一个例子来证明这一点。假设我们想用一个字符串来创建一个雇员对象。该字符串必须是固定的模式,因此我们可以使用 regex 提取雇员的姓名和加入年份。然后,我们使用构造函数创建一个 employee 对象并返回它。
代码如下。
如上面的代码所示,我们已经将装饰器@classmethod
添加到方法from_string()
中,并将变量cls
传递给该方法。所以,我们可以使用变量cls
来创建一个当前类的对象。
该方法提取雇员的姓名和加入年份,然后利用构造函数__init__()
创建对象。
让我们试一试。
e1 = Employee.from_string('I am Chris and I joined in 2020.')
e1.seniority()
这种方法就像一个“工厂”,可以使用不同的“组件”来生产相同的产品。这也是为什么称之为“工厂法”的原因。工厂方法是使用类方法装饰器的非常典型的用例。
3.类别属性
Python 类的最后一个重要装饰是属性。
Python 是一种动态语言,它给予开发者最大的灵活性去做他们想做的事情。然而,有时,一些限制是必要的。
例如,更改员工的加入年份是没有意义的,因为那应该是固定的。这条需求与大多数其他编程语言中的“私有属性”概念相匹配。如何在 Python 类中保护一个属性?装潢师会帮忙的。
让我们简化前面的例子,因为这些静态/类方法在这种情况下无关紧要。在下面的代码中,我们使用@property
装饰器将year_joined
定义为 Python 中的一个属性。
class Employee:
def __init__(self, name, year_joined):
self.name = name
self._year_joined = year_joined @property
def year_joined(self):
return self._year_joined
现在,如果我们创建一个对象并试图设置属性,它不允许我们这样做。
e1 = Employee('Chris', 2020)
e1.year_joined = 2021
这是因为@property
装饰器保护属性不被修改。
你可能也知道我在变量前面加了下划线,所以它变成了_year_joined
。这里没有什么神奇的,但是按照 Python 的惯例,为了可读性,我们应该为任何私有属性加上下划线。如果你想知道更多,请查看我以前的一篇文章,如下所示。
那么,现在如果我们想实现 setter 和 getter 呢?使用@property
装饰器,我们可以很容易地将它们定义如下。
class Employee:
def __init__(self, name):
self.name = name @property
def year_joined(self):
print('getting year_joined...')
return self._year_joined @year_joined.setter
def year_joined(self, value):
print('setting year_joined...')
self._year_joined = value @year_joined.deleter
def year_joined(self):
print('deleting year_joined...')
del self._year_joined
如图所示,我们只是继续使用装饰器
- Getter:带有
@property
装饰的方法将成为 getter - 设定者:
@<attr_name>.setter
- 删除者:
@<attr_name>.deleter
删除器在 Python 中是非常独特的。这是因为 Python 允许我们在运行时从对象中移除属性。因此,删除器将使我们能够对一个受保护的属性这样做。
当然,在 getter 和 setter 中,当属性被获取或设置时,我们可以做其他事情。我刚刚添加了一个打印的消息来通知这一点。
删除程序将删除该属性。因此,在我们删除属性后,它将不再存在于对象中。
摘要
在本文中,我介绍了 Python 面向对象编程中使用的三个重要的装饰器:类。我们通常将静态方法用于类中的实用程序,将类方法用于工厂设计模式,将属性用于我们希望防止被随机修改的任何属性。
https://medium.com/@qiuyujx/membership
如果你觉得我的文章有帮助,请考虑加入灵媒会员来支持我和成千上万的其他作家!(点击上面的链接)
使用 Flask 和 D3.js 构建交互式图表
为电子商务销售分析设计交互式 D3.js 可视化,并支持业务决策
劳拉·乔伊特在 Unsplash 上拍摄的照片
可视化的力量
失意的天才
您是一位自豪的数据科学家,展示了您使用优化代码、花哨的库、高级线性代数和复杂的统计概念设计的新解决方案。
和[…]
与前一天新实习生展示的简单 PowerBI 仪表板相比,您的解决方案没有得到管理层的兴趣、认可或热情。
你遇到过这种挫折吗?
你需要发展你的视觉化技能
简单花哨的可视化比非常复杂的模型更有影响力,尤其是对非技术观众而言。
本文将给你一个在没有 javascript (或者很轻)的先验知识的情况下,使用 D3.js 设计花式可视化的菜谱。
先决条件
- HTML 的基础知识
- Python 中级知识,包括烧瓶框架
- 找到一个你想要设计的可视化的例子
💌新文章直接免费放入你的收件箱:时事通讯
从 D3.js 的例子中获得灵感
示例:悲惨世界人物矩阵图
你正在浏览http://bl.ocks.org*/,*一个很棒的网站来获取 D3.js 的教程,你看着迈克·博斯托克的这个矩阵图找到了灵感。
《悲惨世界》同现,迈克·博斯托克&让·丹尼尔·费科特,链接
《悲惨世界》是法国著名历史小说,作者维克多·雨果,出版于 1862 年。
这个矩阵显示了字符的共现
- 1 个彩色单元格=同一章中出现的两个字符
- 深色单元格:出现频率高的字符
- 浅色单元格:出现频率低的字符
将这种可视化应用到您的业务案例中
您有一个订单行级别的奢侈品化妆品在线销售的数据集。
你想要建立一个矩阵来显示品牌的共现
- 1 个彩色单元格=两个品牌出现在同一个客户订单中
- 深色单元格:与许多其他品牌一起出现的品牌
- 光细胞:与其他品牌很少出现的品牌
使用 Flask 构建您的解决方案
在用 Flask 渲染的模板上复制这个例子
让我们先通过渲染一个例子发现 b.locks (链接) 下面的结构
app.py
/templates
index.html
/static
/data
miserables.json
/js
/Libs
matrix.js
/css
- /templates:index.html 仪表板页面的 HTML 源代码(链接)
- /js/libs:用于呈现 D3.js 的 javascript 库
- /js/matrix.js:用于使用 miserables.json 呈现您的仪表板的脚本
- /static/Miserables . json:matrix . js 用来渲染 (L 墨迹 ) 的 JSON 文件
- /CSS:用于呈现页面的 CSS 文件
全部代码上传在我的 Github 资源库( 链接 )使用过
- 将 Github 资源库复制到您的本地文件夹中
- 下载 requirements.txt 中列出的库
- 启动 app.py
您的示例使用 Flask (链接)——(图片由作者提供)
现在,您已经使用 Flask 和 D3.js 构建了第一个可视化解决方案。
接下来的步骤是
- 用你的数据集替换Miserables . JSON
- 改编 matrix.js 以显示品牌共现
- 改编 HTML 页面代码以
**http://samirsaci.com **
将原始数据集处理成最终的 JSON
从 miserables.json 开始
第一步是分析 miserables.json
**1\. Nodes: Characters distributed in different groups**"nodes": {"name" : Character Name,
"group" : Group Number}2\. Links: Listing pairs of characters"nodes": {"source" : Character Name 1,
"target" : Character Name 2,
"value" : Number of Co-occurence}
获取 brands.json
我们想要什么?
**1\. Nodes: Brands are distributed in groups depending on the number of different brands that are ordered with it**"nodes": {"name" : Brand Name,
"group" : Group Number}2\. Links: Listing pairs of brands that with number of orders they appear together"nodes": {"source" : Brand Name 1,
"target" : Character_name2,
"value" : Number of Orders they appear together}
构建节点
第一个函数 order_brand 将为 create_nodes 函数准备所需的数据帧和列表,该函数将构建您的节点字典。
评论
- n_groups :将要拆分的品牌组数
- ****第 35 行:降序
{第 1 组:与许多其他品牌一起订购的品牌,
第 n 组:与少数其他品牌一起出现的品牌}
建立链接
导出 JSON 中的所有内容
决赛成绩
评论
- json_to :该函数将返回 json,通过向页面’/get-json '发送 get 请求来检索该 JSON
你的 JSON 已经可以被 matrix.js 使用了(经过一些调整)。
**http://samirsaci.com **
调整 Matrix.js 以适应您的品牌
添加工具提示以显示悬停时选择的品牌对
品牌对与订单数量一起显示在左上角—(图片由作者提供)
我在 mouseover 函数中添加了这几行来显示所选择的品牌对。
下载 JSON 文件
该函数将向 flask 页面’/get-json '发送一个 GET 请求,该页面将使用 create_json 函数返回 json_to 。
最后一击
改编 HTML 代码以添加标题
最终渲染
- /CSS: bootstrap 和 styles.css 来改进页面的呈现
您的奢侈品牌在线销售矩阵的最终效果图—(图片由作者提供)
结论
关注我的 medium,了解更多与供应链数据科学相关的见解。
你可以在我的作品集里找到这个矩阵图的静态版本:矩阵图
这是一个简单的 4 步过程
- 找到一个你想用于你的商业案例的好的可视化
- 下载 HTML 代码、javascript、CSS、JSON 文件和所有构建页面所需的文件
- 用烧瓶在本地渲染该页面
- 分析 JSON 格式并构建函数来适应你的输入数据
- 调整 javascript 以适应您的数据框格式
- 自定义 HTML 页面以添加有关数据集的信息
关于我
让我们连接上 Linkedin 和 Twitter ,我是一名供应链工程师,正在使用数据分析来改善物流运营和降低成本。
如果你对数据分析和供应链感兴趣,可以看看我的网站
参考
*【1】—*迈克·博斯托克&让-丹尼尔·费科特,《悲惨世界》共现,链接
【4】—小萨奇 ,我的作品集中一个最终渲染的例子, 最终渲染**
轻松构建多个机器学习模型
使用 lazy predict 仅用 2 行代码创建多个机器学习模型
由 Unsplash 上的 Pietro Jeng 拍摄
创建机器学习模型并找出最佳模型是一项令人厌倦的任务,因为这将花费大量的时间和精力。Lazy predict 有助于在短短两行代码中构建多个机器学习模型。
它不仅创建多个模型,而且有助于了解哪些模型适用于给定的数据。以便我们可以使用该模型并执行超参数调整以使其更加精确。它易于使用并且是开源的。它创建了大部分用于回归和分类的机器学习模型。
在本文中,我们将学习如何使用 lazy predict 并使用它创建多个机器学习模型。
让我们开始吧…
安装所需的库
我们将从使用 pip 安装来安装 lazy predict 开始。下面给出的命令将使用 pip 安装 lazy predict。
pip install lazypredict
导入所需的库
在本文中,我们将讨论分类和回归问题。在这一步中,我们将加载所需的库。我们将使用著名的糖尿病数据集进行分类,使用波士顿数据集进行回归分析。
from lazypredict.Supervised import LazyClassifier
from sklearn.datasets import load_diabetes
from sklearn.model_selection import train_test_split
from lazypredict.Supervised import LazyRegressor
from sklearn import datasets
from sklearn.utils import shuffle
import numpy as np
创建机器学习模型
这是最后一步,我们将对数据进行预处理,并创建多个机器学习模型。
1.分类
data = load_breast_cancer()
X = data.data
y= data.targetX_train, X_test, y_train, y_test = train_test_split(X, y,test_size=.5,random_state =123)clf = LazyClassifier(verbose=0,ignore_warnings=True, custom_metric=None)
models,predictions = clf.fit(X_train, X_test, y_train, y_test)print(models)
模特表演(来源:作者)
在这里,我们可以清楚地分析不同的分类模型以及它们的性能,这仅仅是由两行代码创建的。
2.回归
boston = datasets.load_boston()
X, y = shuffle(boston.data, boston.target, random_state=13)
X = X.astype(np.float32)offset = int(X.shape[0] * 0.9)X_train, y_train = X[:offset], y[:offset]
X_test, y_test = X[offset:], y[offset:]reg = LazyRegressor(verbose=0, ignore_warnings=False, custom_metric=None)
models, predictions = reg.fit(X_train, X_test, y_train, y_test)print(models)
模特表演(来源:作者)
在这里,我们可以分析不同的模型及其对回归数据集的性能。
这就是我们如何使用 Lazy Predict 轻松、毫不费力地创建多个机器学习模型。
继续尝试不同的数据集,并让我知道您在回复部分的评论。
本文是与皮尤什·英加尔合作完成的。
在你走之前
感谢 的阅读!如果你想与我取得联系,请随时通过 hmix13@gmail.com 联系我或我的 LinkedIn 个人资料 。可以查看我的Github简介针对不同的数据科学项目和包教程。还有,随意探索 我的简介 ,阅读我写过的与数据科学相关的不同文章。
使用 HuggingFace 数据集构建 NLP 管道
NLP 实践者的宝库和无与伦比的管道工具
作者图片
H F Datasets 是 NLP 从业者的必备工具——托管超过 1.4K *(主要是)*高质量的以语言为中心的数据集和易于使用的函数宝库,用于构建高效的预处理管道。
本文将研究可用的大规模数据集存储库,并探索该库出色的数据处理能力。
数据集
我们将从探索数据集开始。正如我们所说的——有大量的数据集可用,其中许多是由社区上传的。我经常使用的两个数据集是 OSCAR 和 SQuAD 数据集。
SQuAD 是一个用于训练问答变压器模型的出色数据集,通常无与伦比。HF 数据集实际上允许我们从跨越几种语言的几个不同的队数据集中进行选择:
当微调问答的 transformer 模型时,我们只需要这些数据集中的一个。
另一个数据集 OSCAR 可能是现有的最令人印象深刻的语言数据集之一。它由超过 166 种不同的语言数据集组成,包含从网络上搜集的非结构化文本。
其中一些数据集很小,如 11KB 的 Nahuatl 语言,但其他数据集很大,如 106GB 的日语或 1.2TB 的英语。这使得 OSCAR 成为预训练 transformer 模型的理想选择。
访问和查看数据集
在查看哪些数据集可用时,我们可以采用两种方法。使用在线数据集查看器应用或直接使用 Python。
在线数据集查看器相当简单,因此我建议您点击了解它是如何工作的。在这里,我们将重点放在 Python 方面。
我们希望从导入和查看所有可用的数据集开始。有很多,所以如果你在寻找一个特定的数据集——比如squad
——提前知道会很有帮助。
为了加载数据集,我们使用了datasets.load_dataset
函数。默认情况下,这会将整个数据集下载到文件中,这对于小队来说是可以的。但如果我们考虑到 1.2TB 大小的英语奥斯卡,这可能是一个糟糕的想法…😅
因此,我们可以不使用默认行为,而是通过设置streaming=True
,在需要时迭代下载数据集的大块内容。
我们可以看到,squad
数据集包含两个子集,train
和validation
。如果愿意,我们可以指定只使用其中的一个:
尽管我们将坚持使用整个数据集。要查看数据集的大小、描述和特性,我们可以分别访问dataset_size
、description
和features
属性。
如果使用streaming=False
,可以使用像dataset['train'][0]
这样的语法来访问数据集中的特定记录——但是因为我们有streaming=True
,所以我们必须遍历数据集。
这意味着,如果我们想查看记录以了解内容的类型(除了由dataset['train'].features
显示的内容之外),我们可以写:
这样,我们对可用的数据集有了一个很好的概念,并理解了它们的目的和内容。在下一节中,我们将继续讨论datasets
提供的处理方法。
数据集预处理
而datasets
值得使用,因为它可以方便地访问如此多的高质量数据集。它还附带了许多令人惊叹的预处理功能。当使用streaming=True
时,这些变得更加有用,因为我们可以迭代地转换我们的数据,而不需要下载所有东西。
修改特征
我们将从修改队伍数据中的answers
特征开始。在 Q & A 中,我们通常需要一个答案起始位置和结束位置。小队已经包含了answer_start
,但是我们必须使用这个和答案text
长度来创建我们自己在answers
特征中的answer_end
值。
修改现有特征(和创建新特征)最常用的方法是map
功能。
请注意,当
streaming=True
时,我们必须将中的每个特征都包含在map
中,否则它们会在映射后消失。当*streaming=False*
时情况并非如此,我们将在后面看到。
当我们定义这个转换时,它不会立即执行。相反,它是作为调用数据集时要执行的*‘指令’*添加的。这意味着我们仍然没有在内存中存储任何数据集。
该指令用于在需要时仅转换数据集样本*——也称为惰性加载(一个通用术语,不特定于 HF 甚至 ML) 。如果我们再次遍历几个样本,我们会看到转换得到了应用。*
我们还可以看到,如果我们故意在map
函数中创建一个错误,这是延迟加载的,因为在我们遍历数据集之前,错误不会出现。
我们将在后面介绍filter
w 方法,它只能在streaming=False
时使用——所以我们将在没有流的情况下重新加载我们的数据,并在本文的剩余部分使用它。**
使用
streaming=False
,我们可以使用列表索引直接访问数据集中的记录。
我们不再需要在map
函数中包含每一个特性。当streaming=False
时,我们只包括我们正在修改(或创建)的特征。
定量
我们几乎总是会执行的另一个操作是将文本标记化为标记 id。对于 SQuAD,这要求我们将question
和context
字符串传递给一个记号赋予器,记号赋予器将输出三个张量(对于 Bert)——input_ids
、token_type_ids
和attention_mask
。
一般来说,这个过程在批量执行时要快得多。幸运的是,map
方法允许我们使用batched=True
批量转换,甚至指定batch_size
。
重命名功能
有时我们可能需要重命名特性,通常是为了将特性名称与模型所期望的输入名称对齐。
在这种情况下,我们只是迂腐。我想将主题功能从title
重命名为topic
。
过滤
这是一个非常漂亮的特性。我们可以根据样本是否满足某种条件来过滤掉数据集中的样本。
我们已经返回了数据集的前几个样本,都是关于University_of_Notre_Dame
的主题——假设我们不想在我们的数据集中包含University_of_Notre_Dame
样本。
我们需要做的就是把它们拿出来:
这样,我们只保留了中topic
不等于和University_of_Notre_Dame
的样本。另外需要注意的是,我们不能用* *filter*
当 *streaming=True*
。*
删除功能
我们已经完成了处理,并且我们决定——实际上——我们不需要大多数特性。事实上,对于问答推理,我们只需要input_ids
、token_type_ids
、attention_mask
。
因此,对于我们的最终转换,让我们继续前进,并删除所有这三个功能。
我们到了。我们已经学会了如何找到并下载(或流式传输)一些在线可用的最佳数据集。然后,我们探索了 HF 的datasets
中打包的一些最重要的数据处理功能。
我希望你喜欢它!如果你有任何问题,请通过推特或者在下面的评论中告诉我。如果你想要更多这样的内容,我也会在 YouTube 上发布。
感谢阅读!
*所有图片均由作者提供,除非另有说明
使用 Python 和 Flask-RESTful 为机器学习模型构建 REST API
数据科学家可以遵循的最小工作示例
Marcin Jozwiak 在 Unsplash 上拍摄的照片
1。简介
2。环境设置
∘ 2.1 使用 conda
∘ 2.2 使用 pip
∘ 2.3 为它创建一个 conda 环境
3 .培养一个最小 ML 模型
4。构建 REST API
∘ 4.1 理解代码
∘ 4.2 旋起 REST API
5 .测试 API
结论
关于我
参考文献
注:本帖提到的所有代码和结果都可以从我的 GitHub 页面访问。
1。简介
作为数据科学家,我们不仅需要构建模型,还需要部署它们,并使它们在完整的系统中有用。在许多情况下,我们需要与其他开发人员合作,将模型保存在单独的位置并使用 API 将模型提供给其他应用程序几乎总是一个好主意。
应用程序编程接口(API)是一种 web 服务,它允许访问其他应用程序可以通过标准 HTTP 协议访问的特定数据和方法,而表述性状态转移(REST)是 web 服务最流行的 API 架构风格之一。另一方面,Python 是数据科学家最喜欢的语言,有两种流行的 web 框架:Django 和 Flask。与 Django 相比,Flask 以轻量级和快速开发著称。它也有许多扩展来为 vanilla Flask 应用程序添加特定的功能,Flask-RESTful 是一个完美的选择,可以让构建一个功能完整的 REST API 变得非常容易。
在这里,我将带你通过一个例子和你需要遵循的所有代码,来了解如何使用 Flask-RESTful 构建一个最小可行的 REST API。这篇文章有三个主要部分:
- 制作一个 ML 模型:一个使用玩具数据集的简单模型
- **构建一个 REST API:**post 的主要部分。为刚做好的 ML 模型服务
- 测试 API :通过调用 API 使用模型进行预测
2.环境设置
因为这是一个最小的例子,所以不需要很多包。可以用conda
也可以用pip
。对于下面的 2.1 到 2.3,选择任何一种你感兴趣的方法。完成这些之后,你可以直接跳到第三部分。
2.1 使用 conda
如果您安装了 conda,您可以运行:
conda install -c conda-forge numpy scikit-learn flask-restful requests
2.2 使用画中画
如果没有安装 conda,pip
也可以通过运行:
pip install numpy scikit-learn flask-restful requests
2.3 为 it 创造康达环境
有时,为不同的项目保留不同的环境是有益的,因此如果您想创建另一个虚拟环境,可以运行以下命令:
conda create --name flask_api -c conda-forge numpy scikit-learn flask-restful requests
它将创建另一个名为flask_api
的环境,安装了这些软件包,您可以通过运行以下命令切换到新环境:
conda activate flask_api
你也可以使用pip
创建虚拟环境,但是我将跳过这一步,因为你可以很容易地在网上找到教程。
3.训练最小 ML 模型
东西摆好之后,我们先来搭建一个玩具 ML 模型。要获得更完整的代码和结果,请参考 Jupyter 笔记本,但以下是该部分的最低可行代码,也可以从这里下载。我们把它命名为train_model.py
,你可以使用python train_model.py
来运行
如果你熟悉机器学习,并且有过一些使用scikit-learn
的实践经验,那么代码应该对你有意义。
基本上,我们首先加载一个玩具数据集iris
,如下所示:
有 150 条记录。它们中的每一种都有 4 个特征,并被标记为 3 类中的一类(刚毛藻、杂色藻和海滨藻)。
在此示例中,我们直接训练模型并跳过微调部分,然后使用模型对测试集进行预测:
[0 2 0 1 2 2 2 0 2 0 1 0 0 0 1 2 2 1 0 1 0 1 2 1 0 2 2 1 0 0 0 1 2 0 2 0 1 1]
其中数字代表 3 类中的每一类。通过与真实标签比较,我们发现准确率为 97%,混淆矩阵如下所示:
图 1:测试集上模型预测的混淆矩阵(直接来自模型对象)
我们的表现已经足够好了(可能现实生活中太好了)。然后,我们通过在 pickle 文件中序列化来保存训练好的模型。
4.构建 REST API
4.1 理解代码
现在,一个简单的模型已经准备好了,让我们构建一个 REST API。同样,下面是代码,我会一步一步地解释它。也可以从我的 GitHub 下载。我们把这个命名为api.py
app = Flask(__name__)
api = Api(app)
首先,我们导入模块,上面的两行应该几乎总是存在于代码的顶部,以初始化 flask app 和 API。
*# Create parser for the payload data* parser = reqparse.RequestParser()
parser.add_argument(**'data'**)
上面的代码块创建了一个请求解析器来解析将随请求一起发送的参数。在我们的例子中,由于我们服务于 ML 模型,我们通常以 JSON 序列化格式发送数据,并将键命名为data
,因此我们要求解析器查找请求中包含的数据。
*# Define how the api will respond to the post requests* class IrisClassifier(Resource):
def post(self):
args = parser.parse_args()
X = np.array(json.loads(args[**'data'**]))
prediction = model.predict(X)
return jsonify(prediction.tolist())
api.add_resource(IrisClassifier, **'/iris'**)
然后我们通过继承从flask-restful
导入的Resource
类来创建一个名为IrisClassifier
的类,它已经定义了处理不同类型请求的各种方法,包括get
post
put
delete
等等。我们的目标是重写post
方法,告诉它如何使用模型对给定数据进行预测。因为我们的 API 的目的是服务于 ML 模型,我们只需要post
方法,不用担心其他的。
在post
方法中,我们首先调用刚刚定义的解析器来获取参数。数据(最初是 np.array)在 JSON 中被序列化为字符串格式,所以我们使用json.loads
将其反序列化为一个列表,然后返回到一个 NumPy 数组。预测部分和scikit-learn
模型一直做的一样。在最后一步,我们需要将预测的标签(np.array)放回列表,并调用从flask
导入的jsonify
函数再次序列化它,以便它们以正确的格式返回给应用程序。
在定义了类之后,我们将我们的IrisClassifier
(本质上是一个修改过的resource
类)连同访问它的相对路径一起添加到我们的 API 中,在我们的例子中是/iris
。如果我们只是在本地运行 flask,那么 ML 模型的整个 URL 将类似于[http://127.0.0.1:5000/iris](http://127.0.0.1:5000/iris)
。
if __name__ == **'__main__'**:
*# Load model* with open(**'model.pickle'**, **'rb'**) as f:
model = pickle.load(f)
app.run(debug=True)
在api.py
代码的最后一部分,我们加载从上一节保存的模型,以便应用程序知道如果需要任何预测,从哪里获取模型。然后,我们在调试模式下运行 flask 应用程序,如果发生任何错误,它只允许在浏览器中直接执行任意代码。
4.2 启动 REST API
如果您有保存为api.py
的代码,您可以使用:
python api.py
将会出现如下信息:
* Serving Flask app "api" (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: on
* Running on [http://127.0.0.1:5000/](http://127.0.0.1:5000/) (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 117-609-315
那你就可以走了!
5.测试 API
如果您遵循了前面的章节,那么您应该已经在本地机器上运行了 REST API。现在是测试的时候了,看看是否有效。同样,下面是您需要复制、粘贴和运行的所有代码(最少)。更多完整的代码和结果,请参见 Jupyter 笔记本,或者下面的代码,您可以在这里访问。
然后我会一步一步地解释代码。我们把它命名为test_api.py
,你可以通过调用python test_api.py
来运行它
*# Load data* iris = load_iris()
*# Split into train and test sets using the same random state* X_train, X_test, y_train, y_test = \
train_test_split(iris[**'data'**], iris[**'target'**], random_state=12)
导入相关模块后,首先要做的是获取一个数据子集(仅特性)来测试 API 返回的预测。为了便于比较,我们可以使用我们在第 3 节中拆分的相同测试集。我们可以加载 iris 数据集,并使用相同的随机状态(12)来获得数据的确切子集X_test
。
*# Serialize the data into json and send the request to the model* payload = {**'data'**: json.dumps(X_test.tolist())}
y_predict = requests.post(**'http://127.0.0.1:5000/iris'**, data=payload).json()
然后,我们创建一个payload
变量,将X_test
的列表序列化为 JSON 格式,key 为data
,就像我们在api.py
中定义的那样,这样我们的 API 就知道在哪里可以找到输入数据。然后,我们将有效负载发送到我们定义的端点,并获得预测结果。
*# Make array from the list* y_predict = np.array(y_predict)
print(y_predict)
最后一步是可选的,但是我们可以将数据返回到 NumPy 数组并打印出预测,这与我们之前在第 3 节中创建模型时得到的结果完全相同。混淆矩阵也完全相同:
[0 2 0 1 2 2 2 0 2 0 1 0 0 0 1 2 2 1 0 1 0 1 2 1 0 2 2 1 0 0 0 1 2 0 2 0 1 1]
图 1:测试集上模型预测的混淆矩阵(来自 REST API)
在 REST API 端,在使用了post
方法之后,我们可以看到显示响应为 200 的消息,这意味着请求已经被成功处理:
127.0.0.1 - - [01/Nov/2021 17:01:42] "POST /iris HTTP/1.1" 200 -
因此,我们已经测试了刚刚构建的 REST API,并获得了与原始模型对象返回的结果完全相同的结果。我们的 API 管用!
结论
我们刚刚介绍了使用 Python 和 Flask-RESTFul 构建一个全功能 REST API 所需的基本知识和步骤。如果我们只看 API 构建部分(第 4 节),它确实非常简单——不到 30 行代码,其中大多数只是标准语句。修改代码也非常容易:您所需要做的就是替换您想要使用的模型,指定post
方法如何工作,并给出访问 API 的正确路径。
为了进一步利用我们刚刚构建的 REST API 来为其他应用程序提供我们的机器学习模型,我们可以将它部署在服务器上,或者使用任何流行的云 web 托管服务:AWS、Google Cloud、Heroku 等。通过适当的配置,任何获得许可的人都可以从世界上的任何地方访问我们的模型。
感谢您的阅读!如果你喜欢这篇文章,请关注我的频道和/或 成为我今天的推荐会员 (非常感谢🙏).我会继续写下去,分享我关于数据科学的想法和项目。如果你有任何问题,请随时联系我。
https://zhouxu-ds.medium.com/membership
关于我
我是赛诺菲的数据科学家。我拥抱技术,每天都在学习新技能。欢迎您通过媒体博客、 LinkedIn 或 GitHub 联系我。我的观点是我自己的,而不是我雇主的观点。
请看我的其他文章:
- 利用空气质量传感器数据进行时间序列模式识别
- 理解分类问题中的 Sigmoid、Logistic、Softmax 函数和交叉熵损失(对数损失)
- 使用 Elasticsearch (AWS OpenSearch)进行实时类型预测搜索
- 利润最大化的贷款违约预测
- 使用 Berka 数据集进行贷款违约预测
参考
[1]如何将 Python 请求模块与 REST API 一起使用:https://www . nylas . com/blog/Use-Python-Requests-Module-REST-API/
[2] Python REST API 教程—构建 Flask REST API:https://www.youtube.com/watch?v=GMppyAPbLYk&t = 3769s&ab _ channel = TechWithTim
用 Python 构建健壮的 Google BigQuery 管道:第一部分
谷歌云平台
Apache Beam 与 Google BigQuery API
弗兰基·查马基在 Unsplash 上拍摄的照片
这是关于在 Python 中与 BigQuery 交互以构建数据管道的三篇文章系列的第 1 部分。
- 第一部分. Apache Beam 与 Google BigQuery API
- 第二部分。Python 中的 BigQuery 结构
- 第三部分。BigQuery 和 Google Sheet:隐藏的复杂性
摘要
在 Spotify,我们有许多软件工程师和数据工程师团队,他们使用 Scala 或 Java 来帮助将大量数据带入我们的谷歌云平台(GCP)生态系统,供用户和研究人员使用。然而,大部分数据还不能立即使用。为了正确地进行分析,需要进行清洁和整形步骤。对于我们来说,重要的是拥有一个强大的管道,可以处理日常的数据清理需求,同时应用业务逻辑和机器学习方法。Python 有一个独特的优势,即既敏捷又强大。这就是为什么我在过去的一年里投入了大量的时间和精力来提出一个优化的解决方案,用 Python 构建 BigQuery 数据管道。感谢开源社区,那里有很多资源提供了很好的提示和指导。然而,经过几轮反复试验,我还是花了一些时间找到了正确的信息。因此,我希望这篇文章能让你的生活变得更简单,如果你也想在 Python 中使用 BigQuery 的话。
在这篇文章中,我将简要介绍 BigQuery,并讨论可以与 BigQuery 交互的两个最常用的 Python APIs。
目录
- BigQuery 概述
- Apache Beam BigQuery Python I/O:实现、利弊
- Python 中的 Google BigQuery API:实现、优缺点
BigQuery 概述
BigQuery 是一个完全托管的、无服务器的数据仓库,能够对数 Pb 的数据进行可扩展的分析。它是一个平台即服务,支持使用 ANSI SQL 进行查询。它还内置了机器学习功能。BigQuery 于 2010 年 5 月发布,并于 2011 年 11 月正式发布。(维基百科)
在 GCP,两个最常见的存储数据的地方是 BigQuery 和 GCP 桶。GCP 桶更像一个存储场所,而 BigQuery 允许用户在 UI 上立即进行分析。有许多方法可以与 BigQuery 交互。最简单和最明显的方法是通过 BigQuery 的交互式 UI 控制台。BigQuery 控制台允许用户使用标准 SQL 或遗留 SQL 来查询表。在云控制台和客户端库中,标准 SQL 是默认的。在bq
命令行工具和 REST API 中,遗留 SQL 是默认的。您可以在查询设置中或者通过在 API 调用中传递参数来轻松地在两者之间切换。
谷歌最近发布了一个新的视图,增加了一些功能,比如允许多个标签供编辑使用,这是一个受用户欢迎的变化。但是,有几个 bug 需要修复。首先,对于每日分区,只能查看最新的模式——早期分区的模式和预览功能不起作用。再比如 delete table 函数只允许用户删除最近的分区,看起来会像是用户删除了数据集中的所有东西!幸运的是,事实并非如此;刷新将显示只有最新的分区被删除。
BigQuery 控制台当前视图
BigQuery 控制台旧视图
Apache Beam BigQuery Python I/O
我最初是通过其 Google BigQuery I/O 连接器使用 Apache Beam 解决方案开始旅程的。当我了解到 Spotify 数据工程师在 Scala 中使用 Apache Beam 进行大部分管道工作时,我认为它也适用于我的管道。事实证明并非如此,但我并不后悔,因为一路上我学到了很多关于 Apache Beam 的知识。
Beam SDKs 包含内置函数,可以从 Google BigQuery 表中读取数据和向其中写入数据。要安装,请在您的终端中运行pip install apache-beam[gcp]
。
导入包
import apache_beam as beam
import json
from apache_beam.io.gcp.bigquery_tools import parse_table_schema_from_json
从 BigQuery 读取
要从 BigQuery 读取数据,您可以选择。Apache Beam 不是我最喜欢的从 BigQuery 读取数据的方法。我更喜欢使用 Google BigQuery API 客户端,因为它可以下载数据并将其转换为 Pandas 数据框架。但作为参考,您可以直接从表中读取:
*# project-id:dataset_id.table_id*
table_spec **=** 'YOUR_PROJECT:YOUR_DATASET.YOUR_TABLE_ID'my_column = (
p
| ‘ReadTable’ >> beam.io.ReadFromBigQuery(table=table_spec)
# Each row is a dictionary where the keys are the BigQuery columns
| beam.Map(lambda elem: elem[‘my_column’]))
或者传递一个 SQL 查询:
my_column = (
p
| ‘QueryTableStdSQL’ >> beam.io.ReadFromBigQuery(
query=’SELECT my_column FROM ‘\
‘`YOUR_PROJECT.YOUR_DATASET.YOUR_TABLE_ID`’,
use_standard_sql=True)
# Each row is a dictionary where the keys are the BigQuery columns
| beam.Map(lambda elem: elem[‘my_column’]))
数据格式编排
现在您已经检索了数据,您可以用 Python 对它们做各种有趣的事情。你可以操作数据,应用 ML 模型等。但是在将这个表上传到 BQ 之前,这里有一些最终处理的指针。
- 时间戳 格式时间戳列如下:
my_table[‘my_timestamp’] = my_table[‘my_timestamp’].apply(lambda x: x.strftime(‘%Y-%m-%d %H:%M:%S’)))
- 数据类型 将 Float 、 Integer 、 Timestamp 或 Date 数据类型转换为 String 首先在 Beam 中传递,然后在 schema 文件中指定数据类型。请注意时间戳/日期数据类型不接受空字符串。
my_table = my_table.applymap(str)
- 数据结构这使得 beam 能够分离列表,如果是一个巨大的数据集,就将数据传回。
my_table = my_table.to_dict("records")
- 空值
None (Null)类型不能作为除了 ApacheBeam 中的字符串之外的任何内容传递。当作为字符串类型传递时,您将在 BigQuery 中看到一个实际的‘None’字符串,这是 Python 中的 NULL 值。尽管令人困惑,但将其转换为空字符串将解决问题,并在 BigQuery 中获得实际的空值。
一旦为数据类型准备好数据框,并根据需要将其转换为字典列表,就可以将对象上传到 BigQuery 了。
上传到 BigQuery
为了将数据上传到 BigQuery,我们需要首先定义模式。下面是一个用 JSON 生成模式文件的模板。
def make_sink_schema():
mapping = {
"string": ["STRING", "This is my string."],
"timestamp": ["TIMESTAMP", "This is my timestamp."],
"numeric": ["FLOAT", "This is my float."],
} mapping_list = [{"mode": "NULLABLE", "name": k, "type": mapping[k][0], "description": mapping[k][1]} for k in mapping.keys()]
return json.JSONEncoder(sort_keys=True).encode({"fields": mapping_list})
你也可以在 Avro 中生成模式文件。但是这里我们以 JSON 为例。一旦准备好模式,就可以使用下面的模板将表上传到 BigQuery。
def run_beam(my_table, table_name, dataset_name, project_name, my_schema):
argv = [
'--project={0}'.format('YOUR_PROJECT'),
'--job_name=YOUR_JOB_NAME',
'--staging_location=gs://{0}/staging/'.format('YOUR_BUCKET'),
'--temp_location=gs://{0}/temp/'.format('YOUR_BUCKET'),
'--region=YOUR_REGION',
'--service_account = YOUR_SERVICE_ACCOUNT'
'--runner=DataflowRunner'
]
p = beam.Pipeline(argv=argv)
# write table to BigQuery
(p
| 'Create Data' >> beam.Create(my_table)
| 'Write to BigQuery' >> beam.io.Write(
beam.io.WriteToBigQuery(
# The table name is a required argument for the BigQuery sink.
# In this case we use the value passed in from the command line.
table=table_name, dataset=dataset_name, project=project_name,
# JSON schema created from make_sink_schema function
schema=parse_table_schema_from_json(my_schema),
# Creates the table in BigQuery if it does not yet exist.
create_disposition=beam.io.BigQueryDisposition.CREATE_IF_NEEDED,
# Deletes all data in the BigQuery table before writing.
write_disposition=beam.io.BigQueryDisposition.WRITE_TRUNCATE))
)
return pp = run_beam(my_table, table_name, dataset_name, project_name, my_schema)p.run().wait_until_finish()
赞成的意见
在处理大量数据时,ApacheBeam 的优势是显而易见的。因为它在行级别处理数据,所以数据集可以分成多个部分,以便不同的工作人员可以并行处理它们。
骗局
对我来说,Apache Beam 的最大问题是它在数据类型和空值方面的不灵活性。有太多的细微差别,没有太多的变通办法。
Python 中的 Google BigQuery API
当我在应对 Apache Beam 的缺点时,我决定尝试一下 Google BigQuery API ,我很高兴我这么做了!如果你不想运行一个有大量数据的大任务,Google BigQuery API 是一个很好的选择。要安装,请在您的终端中运行pip install — upgrade google-cloud-bigquery
。
导入包
from google.cloud import bigquery
import pandas as pd
从 BigQuery 读取
要从 BigQuery 读取数据,您可以决定是使用自己的凭据还是使用服务帐户凭据来读取。如果您想使用自己的凭证,第一步是通过在您的终端中运行gcloud auth login command
来授权您的 Google 帐户。然后,您可以继续使用您最喜欢的 Python 编辑器:
# Construct a BigQuery client object.
client = bigquery.Client(project=YOUR_PROJECT)query = """
SELECT name, SUM(number) as total_people
FROM `bigquery-public-data.usa_names.usa_1910_2013`
WHERE state = 'TX'
GROUP BY name, state
ORDER BY total_people DESC
LIMIT 20
"""
query_job = client.query(query).result().to_dataframe() # Make an API request and convert the result to a Pandas dataframe.
如果您选择使用服务帐户凭证,首先将其保存为本地 JSON 文件,然后按如下方式构造客户端对象:
client = bigquery.Client.from_service_account_json(
json_credentials_path=PATH_TO_YOUR_JSON,
project=YOUR_PROJECT)
数据格式编排
Google BigQuery API 在数据类型上也有一些怪癖,但我喜欢的是它更好地处理 NULL 值,并且允许所有数据类型中的 NULL 值。以下是一些额外的提示:
- 时间戳
格式时间戳列如下:
my_table[‘my_timestamp’] = my_table[‘my_timestamp’].apply(lambda x: x.strftime(‘%Y-%m-%dT%H:%M:%S’)))
- 日期
格式日期列如下:
my_table['my_date'] = pd.to_datetime(my_table['my_date'], format='%Y-%m-%d', errors='coerce').dt.date
- String
空字符串在 BigQuery 上将作为空字符串返回。所以用np.nan
来代替他们。
my_table = my_table.replace(r'^\s*$', np.nan, regex=True)
上传到 BigQuery
您可以选择在将数据上传到 BigQuery 时自动检测模式,也可以使用下面的函数定义您自己的模式。请注意,列的顺序无关紧要。BigQuery 客户端将按名称查找列。
def make_schema():
schema = [
bigquery.SchemaField(name="string", field_type="STRING", description="This is my string."),
bigquery.SchemaField(name="numeric", field_type="FLOAT", description="This is my float."),
]
return schema
一旦准备好模式,就可以使用下面的模板将表上传到 BigQuery。
def run_bigquery(my_table, table_id, project_name, my_schema, table_description = None):
*"""
Upload a dataframe to BigQuery
"""* client = bigquery.Client(project=project_name)
job_config = bigquery.LoadJobConfig(schema=my_schema, destination_table_description=table_description,
write_disposition='WRITE_TRUNCATE')
job = client.load_table_from_dataframe(
my_table, table_id, job_config=job_config)
return jobjob = run_bigquery(YOUR_TABLE, table_id, project_name, make_schema(), table_description)
job.result()
赞成的意见
Google BigQuery API 比 Apache Beam 更容易实现。它在数据类型方面也更加灵活,并且可以更好地处理 Python 中的空值。
骗局
如果数据量很大,这不是一个合适的解决方案。在这种情况下,考虑 Apache Beam。
所以给你!我希望这篇文章能给你一些关于在 Python 中使用 BigQuery 的想法。本系列的下一篇文章将讨论 BigQuery 中的一个特定结构——Struct,以及 Python 环境中由于当前限制而产生的变通方法。回头见!😃
用 Python 构建健壮的 Google BigQuery 管道:第二部分
谷歌云平台
Python 中的 BigQuery STRUCT
由 Joseph Barrientos 在 Unsplash 上拍摄的照片
这是关于在 Python 中与 BigQuery 交互以构建数据管道的三篇文章系列的第二部分。
- 第一部分:Apache Beam 与 Google BigQuery API
- 第二部分。Python 中的 BigQuery
STRUCT
- 第三部分。BigQuery 和 Google Sheet:隐藏的复杂性
什么是 STRUCT?
STRUCT
是有序字段的容器,每个字段都有一个类型(必需的)和字段名称(可选的)。—谷歌云
在 BigQuery 中,一个STRUCT
就像一个数据帧,因此它可以包含多个具有不同列名和数据类型的子列。相比之下,一个ARRAY
就像 Python 中的一个LIST
,你可以在一个ARRAY
中嵌套一个STRUCT
,也可以在一个STRUCT
中嵌套一个ARRAY
。
STRUCT
使用尖括号(<
和>
)声明类型。STRUCT
的元素类型为所需的,可以任意复杂。字段名可选,允许重复字段名。当缺少字段名时,该字段被认为是匿名的。
使用STRUCT
的好处是在连接表时减少了重复的麻烦。然而,它确实增加了访问的难度——特别是对于那些不太懂技术的用户。
要阅读更多关于构建STRUCT
的内容,Google Cloud 有一个非常好的关于这个主题的文档。
查询结构
DOT
注释将允许您查询包含在STRUCT
中的项目。UNNEST
是在需要展平嵌套结构时使用的函数,例如 BigQuery 中的STRUCT
或ARRAY
。
SELECT
user.user_id, -- ARRAY
user.gender, -- STRING
user.is_active, -- BOOLEAN
FROM
`my-project.my_dataset.user_info`,
UNNEST(user) user
值得一提的几个怪癖:
- 当字段是嵌套在
STRUCT
中的ARRAY
时,NOT NULL
功能不起作用(即WHERE user.user_id IS NOT NULL
)。NULL
仍将返回值行。在WHERE
子句中使用LENGTH(user.user_id) > 0
——这将达到目的! - 有时
UNNEST
函数会导致重复行。这是因为UNNEST
正在对表中的所有字段执行CROSS JOIN
。为了避免这种情况,可以考虑在STRUCT
中创建一个ARRAY
,或者仅对子查询中需要的字段使用UNNEST
。
用 Python 下载STRUCT
当一个STRUCT
在 Python 中没有任何UNNEST
被下载时,它将在DataFrame
中被呈现为DICTIONARY
的一个LIST
。
将结构下载到数据帧中
用 Python 将结构上传到 BigQuery
由于Pyarrow
中的序列化限制,BigQuery I/O 不支持将STRUCT
结构上传到 Pandas DataFrame
中的 BQ。据我所知,在Pyarrow 2.0
发布后,这仍然是一个正在进行的问题(见这个线程)。但我建议定期检查这个问题,因为这个问题是由谷歌云工程师提出的,看起来他们正在解决这个问题。
解决方法是将表转换成基于行的数据结构,比如JSON
或 Python DICTIONARY
。我可以使用JSON
上传带有STRUCT
的表格。如果您想将一个数据类型为STRUCT
的表上传到 BigQuery,这里有一个例子,希望对您有所帮助。
导入包
from google.cloud import bigquery
import pandas as pd
数据结构
为了上传一个STRUCT
到 BigQuery,该列的数据结构需要是DICTIONARY
的LIST
。想象一下,你正在建造一个DICTIONARY
的LIST
来转换成一个DataFrame
。
data = pd.DataFrame([
{‘item’: ‘album’,
‘user’: [{‘user_id’: [‘50’, ‘25’], ‘gender’: ‘M’, ‘is_active’: True},]
}, {‘item’: ‘jacket’,
‘user’: [{‘user_id’:[‘20’, ‘30’, ‘35’], ‘gender’: ‘F’, ‘is_active’: False}]
},])# convert DataFrame to the list of dict format
data_json = data.to_dict('records')
一旦您准备好了DataFrame
,这里有一个STRUCT
的模式示例:
schema = [
bigquery.SchemaField(name="item", field_type="STRING", description="an item user purchased"),
bigquery.SchemaField(
"user",
"STRUCT",
fields=[
bigquery.SchemaField("user_id", "STRING", mode="REPEATED", description="User's internal user_id; users can have e multiple ids"),
bigquery.SchemaField("gender", "STRING", mode="NULLABLE", description="User's gender"),
bigquery.SchemaField("is_active", "BOOLEAN", mode="NULLABLE", description="User's active status. True if user logged in in the past 7 days, else False"),
],
mode="REPEATED",),
]
在 BigQuery 控制台上,你会看到 a STRUCT
有类型 ’ RECORD
’,而 aARRAY
有模式 ’ REPEATED
’。
如果STRUCT
中有类型为ARRAY
的字段,则将STRUCT
的模式标记为REPEATED
。如果没有,您可以将模式保留为“NULLABLE
”。
BQ 控制台上的结构模式
现在我们已经准备好了模式,我们可以通过使用来自client
对象的load_table_from_json
函数来上传表。
client = bigquery.Client(project=your_project_name)
job_config = bigquery.LoadJobConfig(
schema=your_schema,
destination_table_description=your_table_description,
write_disposition='WRITE_TRUNCATE'
)job = client.load_table_from_json(
data_json, table_id, job_config=job_config
)job.result()
这是表上传到 BigQuery 后的样子。
具有嵌套数组的结构示例
希望这个关于使用 BigQuery STRUCT
的简单例子对您有所帮助。如果您有任何问题,请随时评论或联系我:)
参考:
- 在表模式中指定嵌套和重复的列
- 数据类型—
[STRUCT](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type)
用 Python 构建健壮的 Google BigQuery 管道:第三部分
谷歌云平台
BigQuery 和 Google Sheet 隐藏的复杂性
由 Ashkan Forouzani 在 Unsplash 拍摄
这是关于在 Python 中与 BigQuery 交互以构建数据管道的三篇文章系列的第三部分。
- 第一部分:Apache Beam 与 Google BigQuery API
- 第二部分。Python 中的 big query
[STRUCT](/build-robust-google-bigquery-pipelines-with-python-part-ii-2883423a1c8a)
- 第三部分。BigQuery 和 Google Sheet 隐藏的复杂性
在 Spotify,Google Sheet 是一款非常受欢迎的办公工具。BigQuery 的优势之一是它能够与存储在 Google Sheet 中的数据进行交互。您可以使用新的 BigQuery 数据连接器 Connected Sheets 访问、分析、可视化和共享电子表格中的数十亿行数据。当数据科学家或工程师与不太懂技术的用户合作时,这非常方便。然而,当涉及到 Google Sheet 时,BigQuery 中有一些意想不到的行为,起初它们可能看起来并不直观。本文旨在深入探讨 BigQuery 中 Google Sheet 的不同用例,并帮助避免由于这些意外行为而造成的混淆,尤其是在 Python 管道环境中。
I .从 Google Sheet 到 BigQuery 创建表格
在这种情况下,“创建表”一词会产生误导,更准确的说法应该是“创建表连接”BigQuery 正在建立一个活动连接,而不是将数据集实际导入 BigQuery。但是 BigQuery console 使用这个术语,所以我们现在坚持使用它。
以下是从 Google Sheet 创建表格需要做的工作概述:
- 为
Create table from
选择“驱动” - 将 URI 工作表复制并粘贴到下一个框中
- 为
File format
选择谷歌表单 - 记下表的元数据,如项目、数据集和表名。为表定义模式—我建议手动输入模式,因为自动检测并不总是正确的
- 定义
Header rows to skip
,如果没有标题,则为 0,如果有 n 个标题行要跳过,则为 n
从 Google 工作表创建表格
一旦创建了表,您将能够在 BigQuery 中查询它。然而,一个常见的错误是认为数据现在作为一个单独的副本存储在 BigQuery 中。事实并非如此。BigQuery 在这里所做的仅仅是创建一个到 Google Sheet 的活动连接,其含义如下:
- 如果在 Google Sheet 上放置任何过滤器,BigQuery 将无法显示整个数据集;Google Sheet 中的过滤器实际上会立即反映出来,并影响数据在 BigQuery 中的外观。因此,如果您想访问 BigQuery 中的所有数据,请始终对单个视图使用过滤器。
- 如果有任何模式更改,如列名更改、列类型更改,则不能在 BigQuery 中编辑现有模式。删除当前的 BigQuery 表并重做
Create table
过程。
二。用 Python 阅读 BigQuery Google Sheet 数据
如果您尝试使用服务帐户来运行作业,请确保您将服务帐户添加为 Google Sheet 的编辑器。
将 Google 工作表设置为 BigQuery 表的最重要步骤是在 Python BigQuery API 中修改 BigQuery 客户机的范围。
import pandas as pd
from google.cloud import bigqueryscopes = (
'https://www.googleapis.com/auth/drive',
'https://www.googleapis.com/auth/drive.file',
'https://www.googleapis.com/auth/spreadsheets',
)
bigquery.Client.SCOPE += scopesclient = bigquery.Client()
然后,这里有一行代码将您的查询结果转换成 pandas dataframe
。
gs = client.query("""SELECT * FROM `YOUR_PROJECT.YOUR_DATASET.{table}`""".format(table=table_name)).result().to_dataframe()
三。用 Python 写 Google Sheet
有几个包可以让你用 Python 写 Google Sheet。我将以pygsheets
为例。如果您不打算在管道中运行作业,这个包非常简单。但是,如果您计划在管道中使用包,则需要一个变通方法;出于安全原因,我们不能在我们的云服务器中存储任何服务帐户密钥文件,因此常规功能将不起作用。让我们看看这两个场景中的一些例子。
假设您计划为此作业使用服务帐户密钥。这里是服务帐户的快速介绍。
服务帐户是与电子邮件相关联的帐户。该帐户使用一对公钥/私钥进行身份验证,这比其他选项更安全——只要私钥保持私有。— Pysheets
要创建服务帐户,请按照下列步骤操作:
- 转到“凭据”选项卡并选择“创建凭据>服务帐户密钥”。
- 接下来选择服务帐户为“App Engine default ”,密钥类型为 JSON,然后单击创建:
3.接下来点击下载按钮下载client_secret[…].json
文件;请务必记住您将它保存为本地json
文件的位置:
现在我们已经准备好了服务帐户密钥文件,让我们导入所需的包:
import requests
import json
import pygsheets
import styx_secrets
from google.oauth2 import service_account
from google.cloud import bigquery
import pandas as pd
import numpy as np
授权过程很简单:
gc = pygsheets.authorize(client_secret='path/to/client_secret[...].json')
然而,如果您有一个管道作业,这个过程会稍微复杂一些,因为我们需要使用一个字典作为我们的解决方法。
首先,我们需要加密我们的服务帐户密钥。在 Spotify,我们有一个名为styx-secrets
的包用于加密。请注意,为了让pygsheets
识别这个密钥,需要对utf-8
进行解码。
import styx_secretskey1 = styx_secrets.decrypt("FIRST_HALF_OF_ENCRYPTED_KEY_STRING").decode("utf-8")
key2 = styx_secrets.decrypt("SECOND_HALF_OF_ENCRYPTED_KEY_STRING").decode("utf-8")
我不得不把密匙分解成两串,因为原来的密匙串太长了,styx-secrets
不接受。
然后我们可以在一个dictionary
中准备密钥文件,这基本上是json
密钥文件的一个copy
和paste
,除了用你的加密字符串交换真实的密钥(注意解密后还需要做一些格式上的改变):
sc_key = {
"type": "service_account",
"project_id": "YOUR_PROJECT",
"private_key_id": "YOUR_PRIVATE_KEY_ID",
"private_key": ("-----BEGIN PRIVATE KEY-----" + key1 + key2 + "-----END PRIVATE KEY-----\n").replace("\\n", "\n"),
"client_email": "YOUR_SERVICE ACCOUNT_EMAIL",
"client_id": "SERVICE_ACCOUNT_CLIENT_ID",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/xxxxxxxx"
}credentials = service_account.Credentials.from_service_account_info(
sc_key,
scopes=[
'https://www.googleapis.com/auth/spreadsheets',
'https://www.googleapis.com/auth/drive',
'https://www.googleapis.com/auth/drive.file', ])gc = pygsheets.authorize(custom_credentials=credentials)
现在我们完成了授权,我们可以玩一玩了!要写入 Google 工作表,这里有一个例子。
假设您有一个跟踪管道事件的 Google Sheet,这样您的团队就可以轻松地分析数据:
# open the google spreadsheet
sh = gc.open('Data Incident Tracker')
# select the first sheet
wks = sh[0]# import previous events
track_prev = client.query("""SELECT * FROM `YOUR_PROJECT.YOUR_DATASET.{table}`""".format(table=table_name)).result().to_dataframe()
# current event
track_now = [{
'incident_date': date_param,
'num_of_tables': len(missing_list),
'table_list': ', '.join(missing_list),
'alert': True,
'root_cause': root_cause}, ]
# create new data frame with all incidents
tracker_df = pd.concat([track_prev, pd.DataFrame(track_now)])
# update the first sheet with tracker_df
wks.set_dataframe(tracker_df.replace(np.nan, '', regex=True), 'A1')
最后,请注意,如果您的表中有任何None
值,它们实际上将作为“NaN”字符串上传到 Google Sheet 中。为了避免这种情况,使用replace(np.nan, ‘’, regex=True)
将它们替换为空字符串,单元格将作为实际的Null
上传到 Google 工作表中。
这是 Python 系列中 Google BigQuery 的最后一篇文章。我希望它们对你有用。如果您有任何问题,请随时联系我们或发表评论。干杯!
使用 Vespa 从 python 构建句子/段落级问答应用程序
使用稀疏和密集排序功能检索段落和句子级别的信息
我们将通过必要的步骤来创建一个问答(QA)应用程序,它可以基于语义和/或基于术语的搜索的组合来检索句子或段落级别的答案。我们首先讨论使用的数据集和为语义搜索生成的问题和句子嵌入。然后,我们将介绍创建和部署 Vespa 应用程序以提供答案的必要步骤。我们将所有需要的数据提供给应用程序,并展示如何结合语义和基于术语的搜索来查询句子和段落级别的答案。
布雷特·乔丹在 Unsplash 上拍摄的照片
本教程基于 Vespa 团队的早期工作来复制 Ahmad 等人的论文 ReQA:端到端答案检索模型的评估的结果。使用斯坦福问答数据集(SQuAD)1.1 版数据集。
关于数据
我们将使用斯坦福问答数据集(SQuAD)1.1 版数据集。数据包含段落(这里表示为上下文),每个段落都有问题,这些问题在相关的段落中有答案。我们已经解析了数据集,并组织了将在本教程中使用的数据,以使其更容易理解。
段落
每个context
数据点包含一个唯一标识段落的context_id
、一个保存段落字符串的text
字段和一个保存问题 id 列表的questions
字段,这些问题 id 可以从段落文本中得到回答。如果我们想在应用程序中索引多个数据集,我们还包括一个dataset
字段来标识数据源。
{'text': 'Architecturally, the school has a Catholic character. Atop the Main Building\'s gold dome is a golden statue of the Virgin Mary. Immediately in front of the Main Building and facing it, is a copper statue of Christ with arms upraised with the legend "Venite Ad Me Omnes". Next to the Main Building is the Basilica of the Sacred Heart. Immediately behind the basilica is the Grotto, a Marian place of prayer and reflection. It is a replica of the grotto at Lourdes, France where the Virgin Mary reputedly appeared to Saint Bernadette Soubirous in 1858\. At the end of the main drive (and in a direct line that connects through 3 statues and the Gold Dome), is a simple, modern stone statue of Mary.',
'dataset': 'squad',
'questions': [0, 1, 2, 3, 4],
'context_id': 0}
问题
根据上面的数据点,可以用context_id = 0
来回答带id = [0, 1, 2, 3, 4]
的问题。我们可以加载包含问题的文件,并显示前五个问题。
段落句子
为了构建更精确的应用程序,我们可以将段落分解成句子。比如下面第一句话来自带context_id = 0
的段落,可以用question_id = 4
回答问题。
{'text': "Atop the Main Building's gold dome is a golden statue of the Virgin Mary.",
'dataset': 'squad',
'questions': [4],
'context_id': 0}
嵌入
我们希望结合语义(密集)和基于术语(稀疏)的信号来回答发送给我们的应用程序的问题。我们已经为问题和句子生成了嵌入以实现语义搜索,每个嵌入的大小等于 512。
[-0.005731593817472458,
0.007575507741421461,
-0.06413306295871735,
-0.007967847399413586,
-0.06464996933937073]
这里是脚本,包含我们用来生成句子和问题嵌入的代码。我们当时使用了 Google 的通用句子编码器,但是可以随意用您喜欢的模型生成的嵌入来替换它。
创建和部署应用程序
我们现在可以基于上述数据构建一个句子级的问答应用。
保存上下文信息的模式
context
模式将有一个包含数据部分描述的四个相关字段的文档。我们为text
字段创建一个索引,并使用enable-bm25
来预先计算加速使用 BM25 进行排名所需的数据。summary
索引指示所有字段都将包含在所请求的上下文文档中。attribute
索引将字段存储在内存中,作为排序、查询和分组的属性。
默认字段集意味着默认情况下查询标记将与text
字段匹配。我们定义了两个等级配置文件(bm25
和nativeRank
)来说明我们可以定义和试验尽可能多的等级配置文件。您可以使用可用的等级表达式和功能创建不同的等级。
保存句子信息的模式
sentence
模式的文档将继承context
文档中定义的字段,以避免相同字段类型的不必要的重复。此外,我们添加了定义用来保存大小为 512 的浮点数的一维张量的sentence_embedding
字段。我们将把字段作为属性存储在内存中,并使用HNSW
(分层可导航小世界)算法构建一个 ANN index
。阅读这篇博文以了解更多关于 Vespa 实现 ANN 搜索的历程,以及文档以了解更多关于 HNSW 参数的信息。
对于sentence
模式,我们定义了三个等级配置文件。semantic-similarity
使用 Vespa closeness
排名功能,该功能被定义为1/(1 + distance)
,因此嵌入问题嵌入更近的句子将比相距较远的句子排名更高。bm25
是基于术语的等级配置文件的示例,而bm25-semantic-similarity
结合了基于术语和基于语义的信号,作为混合方法的示例。
构建应用程序包
我们现在可以通过创建一个应用程序包来定义我们的qa
应用程序,这个应用程序包包含了我们上面定义的context_schema
和sentence_schema
。此外,我们需要通知 Vespa,我们计划发送一个名为query_embedding
的查询排名特性,其类型与我们用来定义sentence_embedding
字段的类型相同。
部署应用程序
我们可以在 Docker 容器中部署app_package
(或者部署到 Vespa Cloud ):
Waiting for configuration server.
Waiting for configuration server.
Waiting for configuration server.
Waiting for configuration server.
Waiting for configuration server.
Waiting for application status.
Waiting for application status.
Finished deployment.
输入数据
部署完成后,我们可以使用Vespa
实例app
与应用程序进行交互。我们可以从输入上下文和句子数据开始。
句子级检索
下面的查询通过ranking.features.query(query_embedding)
参数发送第一个问题嵌入(questions.loc[0, "embedding"]
),并使用nearestNeighbor
搜索操作符检索嵌入空间中最近的 100 个句子,使用HNSW
设置中配置的欧几里德距离。返回的句子将按照在sentence
模式中定义的semantic-similarity
等级配置文件进行排序。
{'id': 'id:sentence:sentence::2',
'relevance': 0.5540203635649571,
'source': 'qa_content',
'fields': {'sddocname': 'sentence',
'documentid': 'id:sentence:sentence::2',
'questions': [0],
'dataset': 'squad',
'context_id': 0,
'text': 'It is a replica of the grotto at Lourdes, France where the Virgin Mary reputedly appeared to Saint Bernadette Soubirous in 1858.'}}
句子级混合检索
除了发送查询嵌入之外,我们可以通过query
参数发送问题字符串(questions.loc[0, "question"]
),并使用or
操作符检索满足语义操作符nearestNeighbor
或基于术语的操作符userQuery
的文档。选择type
等于any
意味着基于术语的操作符将检索至少匹配一个查询标记的所有文档。检索到的文档将按照混合等级-配置文件bm25-semantic-similarity
进行分级。
{'id': 'id:sentence:sentence::2',
'relevance': 44.46252359752296,
'source': 'qa_content',
'fields': {'sddocname': 'sentence',
'documentid': 'id:sentence:sentence::2',
'questions': [0],
'dataset': 'squad',
'context_id': 0,
'text': 'It is a replica of the grotto at Lourdes, France where the Virgin Mary reputedly appeared to Saint Bernadette Soubirous in 1858.'}}
段落级检索
对于段落级检索,我们使用 Vespa 的分组特性来检索段落而不是句子。在下面的示例查询中,我们按context_id
分组,并使用段落的最大句子分数来表示段落级别分数。我们将返回的段落数限制为 3,每段最多包含两句话。我们返回每个句子的所有概要特征。所有这些配置都可以更改,以适应不同的使用情况。
{'id': 'group:long:0',
'relevance': 1.0,
'value': '0',
'children': [{'id': 'hitlist:sentences',
'relevance': 1.0,
'label': 'sentences',
'continuation': {'next': 'BKAAAAABGBEBC'},
'children': [{'id': 'id:sentence:sentence::2',
'relevance': 0.5540203635649571,
'source': 'qa_content',
'fields': {'sddocname': 'sentence',
'documentid': 'id:sentence:sentence::2',
'questions': [0],
'dataset': 'squad',
'context_id': 0,
'text': 'It is a replica of the grotto at Lourdes, France where the Virgin Mary reputedly appeared to Saint Bernadette Soubirous in 1858.'}},
{'id': 'id:sentence:sentence::0',
'relevance': 0.4668025534074384,
'source': 'qa_content',
'fields': {'sddocname': 'sentence',
'documentid': 'id:sentence:sentence::0',
'questions': [4],
'dataset': 'squad',
'context_id': 0,
'text': "Atop the Main Building's gold dome is a golden statue of the Virgin Mary."}}]}]}
{'id': 'group:long:28',
'relevance': 0.6666666666666666,
'value': '28',
'children': [{'id': 'hitlist:sentences',
'relevance': 1.0,
'label': 'sentences',
'continuation': {'next': 'BKAAABCABGBEBC'},
'children': [{'id': 'id:sentence:sentence::188',
'relevance': 0.5209270028414069,
'source': 'qa_content',
'fields': {'sddocname': 'sentence',
'documentid': 'id:sentence:sentence::188',
'questions': [142],
'dataset': 'squad',
'context_id': 28,
'text': 'The Grotto of Our Lady of Lourdes, which was built in 1896, is a replica of the original in Lourdes, France.'}},
{'id': 'id:sentence:sentence::184',
'relevance': 0.4590959251360276,
'source': 'qa_content',
'fields': {'sddocname': 'sentence',
'documentid': 'id:sentence:sentence::184',
'questions': [140],
'dataset': 'squad',
'context_id': 28,
'text': 'It is built in French Revival style and it is decorated by stained glass windows imported directly from France.'}}]}]}
结论和未来工作
这项工作使用谷歌的通用句子编码器来生成嵌入。将评估指标与最新的脸书密集段落检索方法生成的嵌入进行比较会很好。这篇 Vespa 博文使用 DPR 在一个可扩展的生产就绪型应用程序中重现了基于检索的问答系统的最新基线。
建立正确的机器学习团队,而不是最好的
了解在建立一个通过机器学习提供高级分析能力的团队时的陷阱
商业问题解决高级分析。图由照片混合而成。
由机器学习(ML)驱动的高级分析正在风靡一时。大大小小的公司都在提出预测、推荐、分类等等。并创建团队,在不同的问题领域解决这些概念。
需要回答的一个关键问题是如何建立这样一个团队。通常,团队的目标是开发和/或管理软件系统和围绕系统的过程。在他们的核心,他们管理数据、代码、模型和洞察力。我已经看到团队一有机会就跳起来解决高度专业化的问题。因此,他们需要多名数据科学家、机器学习工程师、数据分析师等。,尽快加入这个团队。这是解决未知问题和建立团队的正确方法吗?
我们生活在一个没有两个相同挑战的环境中。对于在同一个国家经营的两家食品连锁店来说,试图为他们的产品找到合适的折扣价格可能不是同样的挑战。一个食品杂货渠道可能会吸引富裕的顾客,而另一个渠道可能更适合寻找便宜货的人。对于同一家杂货店,长期货架产品的优化订购经验可能不容易转化为季节性产品。可能很容易想到技能,如零售、数据分析、算法、数据和建模管道等方面的经验。,就足够了。事实上,拥有这样的专业人士是一个优势,但还不够。交付价值超越了做技术工作的技能。弄清楚如何在正确的时间以正确的方式将这些经历联系起来是很重要的。
就我个人而言,我觉得我正处于学习如何做的初级阶段。然而,我已经学到了一些东西,我想与社区分享。在本文中,我将解释团队在交付高级分析时所经历的阶段。每个阶段都有独特的需求,团队需要解决这些需求来交付期望的结果。正确处理需求是建立正确团队的核心。
机器学习团队的阶段
图 1:ML 产品团队的阶段。作者图。
图 1 展示了 ML 产品团队的五个主要阶段。我们在下面描述了这些阶段和技能要求。
- 探索:在这个阶段,团队需要隔离要解决的关键问题。与此同时,团队需要找出可以提供更多关于近似问题场景的洞察力的数据,这将激发解决方案的设计。在这个阶段,重要的是扫描和保持广度,而不是深入。此外,每天在团队中交流发现和后续想法以及定期与涉众交流也很重要,但不要太频繁。这一阶段的结果是,团队已经对已识别的问题提出了一些数据驱动的公式。这个阶段需要的技能包括问题领域的知识、与问题领域相关的数据知识、数据分析和可视化、需求分析、设计思维、沟通等。请注意,这些技能中有一些是在创业环境中应用的企业家技能,可能来自产品所有者或项目经理以及数据或业务分析师。
- 测试:在这个阶段,团队应该专注于实现公式化问题的解决方案,允许他们测试一些关键的假设。显然,测试开发应该与解决方案开发并行,这样就可以立即识别错误。一旦解决方案在测试环境中运行,它就可以在目标市场的有限范围内进行测试。随着时间的推移,范围可以分阶段扩大。一个阶段中成功的测试应该加强下一个测试阶段的解决方案的改进。一个阶段中测试的失败应该鼓励对问题的形成进行更深入的研究,并对解决方案和测试场景进行可能的调整。此阶段的结果是团队已经确定了应该用于常规价值交付的解决方案。除了探索阶段的技能,一个团队至少需要几个有经验的数据科学家和一个数据工程师才能正常工作。这个团队还需要一些假设检验和实验方面的知识和经验。在这个阶段,重要的是技术解决者要紧密合作并保持广阔的视野。
- 工业化:在这一阶段,团队应该集中精力改进主要解决方案,以达到适当的效率和自动化水平。目标是获得足够的技术深度,以确保定期向中小型目标区域投放。在这个阶段,解决方案可能会遇到在运行过程中出现的边缘情况。因此,解决方案的假设和设计应该到处都有。因此,解决方案的技术复杂性不应妨碍对解决方案进行实验的能力。除了前两个阶段的技能,团队还需要用软件和机器学习工程师来补充数据工程师。团队中每个数据科学家或分析师至少要有两名工程师,这一点很重要。团队也可以有一些没有经验的成员。团队认真对待运营责任是很重要的,即,为即将到来的运行做好充分准备,并愿意放下手头的任何事情以使运行畅通无阻。此外,重要的是将任务委派给个人贡献者,强烈鼓励偶尔的联合工作。为了确保有人需要站出来成为一名技术领导者,他将促进架构和算法设计和实现以及团队文化的讨论。在这个阶段,技术角色需要保持宽泛,然后深入挖掘。
- 扩展:在这个阶段,所有的一切都是为了将系统的能力增强到一个更大的范围,以支持业务的大部分份额。解决方案设计的一部分可能需要重新构思,以便与秤配合使用。此外,在自动化、效率和透明度方面,解决方案的技术复杂性需要非常高。同样重要的是,开发、测试和生产环境应该相似,以便于转移解决方案。一旦一个团队在这个阶段成熟了,开发活动相对于运营支持应该会减少很多。除了早期阶段需要的技能,团队需要增加所有角色的人数。此外,团队应该专注于获得大数据、云、数学建模、软件开发等领域的一些专家。,至少是兼职。
理想情况下,团队会线性地经历这些阶段。然而,我们并不是生活在一个理想的世界中,因此,这样的叙述并不真正合适。业务设置将会发生变化,这将会导致解决方案不断地发生变化。实际上,随着一个团队的成熟,它在不同的阶段会有不同的工作流。
组建合适团队的十项实践
一直招到有特定资质的人是很难的。团队和组织争夺同一个人才库,从而蚕食市场。此外,团队成熟度越低,他们在招聘方面就越差。最后,招聘预算总是落后于候选人的期望。当团队被招募时,开始考虑 ML 系统交付类似于交付一部几十年的肥皂剧。你需要很多人做更多的工作。你需要晋升的人。你经常需要新面孔。你需要多个人来承担大量的责任并协调这个过程。除了技能和经验,获得正确的心态是必须的。
虽然分享什么是应该的方式是很诱人的,但让我分享一些让我和我的团队进入正确心态的技巧。
- 早点招几个忍者通才:刚招的几个需要自己做所有的事情。这几个人必须有能力与整个堆栈一起工作。这几个人将成为团队的核心,因此需要高度协作。
- **招聘喜欢指导和/或良好文化的专家:**雇佣躲在角落里做自己的事的专家是不好的。这个人应该激励和帮助他人在他们的技能领域做得更好。重要的是,这些人推动重大的有影响力的事业,例如,减少技术债务、增加透明度、进行实验等。
- 碰碰运气:招聘要求通常与潜在雇员不完全匹配。在这种情况下,只要有足够的态度和愿望来弥补差距,就要抓住机会。例如,如果这个职位是 Python 软件开发人员,但是候选人有 Java 经验并且愿意学习其他语言,那就去争取吧。
- 目标多样化:避免让你的团队充满超级资深的志同道合者。机器学习是关于优化的,这通常发生在考虑全局或大范围的时候。在这种情况下,如果解决方案不够健壮,那么它再复杂也没用。重要的是,除了大众需求之外,它还有能力覆盖利基市场。当一个团队保持同质的时间太长时,它可能会很难转向,而一个多样化的团队可能会因为其思维的多样性而朝着正确的方向前进。试着把招聘看成一个拼图,需要不同颜色的积木来代表经验水平、教育程度、性别、种族等等。
- **鼓励敏捷:**实现敏捷需要自由思考、学习和反应的时间。交付时,团队必须为提升技能和惊喜留出空间。计划不超过团队能力的百分之七十,鼓励团队花更多的时间结对编程、学习和讨论。鼓励低年级学生从事更有雄心的工作,鼓励高年级学生领导,鼓励人们超越自己的典型职责。最终,这将使个人对自己的工作拥有更多的自主权,从而获得更快反应的心态和能力。
- **减少部落知识:**总是不停地问我们能不能在容错的同时做我们做的事情。否则,无论工作有多复杂,都要减少对个人的高度依赖。一旦团队找到了稳定的解决方案,轮换以增加知识,将责任交给一个团队而不是个人,使文档和演示成为强制性的。
- **追求一个良好的生态系统:**避免仅仅运行一个交付成果的团队。走充分的弯路,比如参加团队内外的黑客马拉松,加入论坛,支持实习生,跑边项目,拯救其他团队。我们不可能一直通过花钱来摆脱危机。为此,我们需要社会化,让社区解决社区的问题。从生态系统的角度考虑挑战,而不是你的团队。如果你有意识或无意识地受益于另一个团队,你应该有意识地回报。
- **为分享建立一个安全的空间:**分享和奖励成就对我们来说很常见。这样的事情激励我们做得更好。然而,这还不够好。通过积极的反馈来奖励和鼓励好习惯也很重要。例如,如果有人写了很好的文档或者用大量的测试覆盖了代码,在代码评审期间公开表扬这个人。此外,团队应该强调从错误中学习,并真正尝试找到根本原因,而不是责怪个人。例如,如果有人因为缺乏知识而犯了错误,这是团队的失败,因为他们没有考虑到团队成员的教育。犯错误是常见的,不应该受到惩罚。重要的是团队在发现错误后会做什么。分享根本原因并建议补救过程不仅对团队有益,对其他团队也有益。
- **努力成为学习型组织:**鼓励主动学习和分享。为人们从事各种学习活动提供足够的空间、预算和手段,如上课、探索新技术和方法、组建学习小组、组建学习委员会、鼓励认证和学位。能力成长具有滚雪球效应,这种效应来自于友好的环境和临界质量。尽管没有立竿见影的效果,但有必要从早期阶段就朝着这个方向努力。
- **创造一个轻松的氛围:**最重要的是,采取行善,善良,减少不良行为。创造一个稳定的地方,在那里大部分时间都不会有压力。诱发事件,使之容易做到这一点。在我工作的瑞典文化中,鼓励人们每天喝咖啡、喝茶、吃面包、吃香蕉,一天几次随意闲聊。我强烈推荐给大家。
备注
我已经试着以某种能力处理每一项实践,并观察到了改进。我不是这方面的研究者,也没有数据来支持我的观点。如果你有更有力的证据支持或反对我的论点,请分享。我会感激这些知识。如果你有其他建议,也请分享。
用 PyCaret 构建,用 FastAPI 部署
这是一个循序渐进、初学者友好的教程,介绍如何使用 PyCaret 构建端到端的机器学习管道,并将其作为 API 进行部署。
py caret——Python 中的开源、低代码机器学习库
👉介绍
这是一个循序渐进、初学者友好的教程,介绍如何使用 PyCaret 构建端到端的机器学习管道,并使用 FastAPI 将其作为 web API 部署到生产中。
本教程的学习目标
- 使用 PyCaret 构建端到端的机器学习管道
- 什么是部署?我们为什么要部署机器学习模型
- 使用 FastAPI 开发一个 API 来生成对未知数据的预测
- 使用 Python 向 API 发送以编程方式生成预测的请求。
本教程将在较高层次上涵盖整个机器学习生命周期,分为以下几个部分:
PyCaret —机器学习高级工作流
💻在本教程中,我们将使用哪些工具?
👉PyCaret
PyCaret 是一个开源的低代码机器学习库和端到端的模型管理工具,内置于 Python 中,用于自动化机器学习工作流。它因其易用性、简单性以及快速有效地构建和部署端到端 ML 原型的能力而广受欢迎。
PyCaret 是一个替代的低代码库,可以用几行代码代替数百行代码。这使得实验周期成倍地快速和有效。
py caret简单 好用。PyCaret 中执行的所有操作都顺序存储在一个管道中,该管道对于**部署是完全自动化的。**无论是输入缺失值、一键编码、转换分类数据、特征工程,甚至是超参数调整,PyCaret 都能实现自动化。
要了解更多关于 PyCaret 的信息,请查看他们的 GitHub。
👉FastAPI
FastAPI 是一个现代、快速(高性能)的 web 框架,用于基于标准 Python 类型提示用 Python 3.6+构建 API。主要特点是:
- 快:非常高的性能,与 NodeJS 和 Go 不相上下(感谢 Starlette 和 Pydantic)。最快的 Python 框架之一。
- 快速编码:将开发特性的速度提高 200%到 300%左右。
- 易:设计为易于使用和学习。减少阅读文件的时间。
要了解 FastAPI 的更多信息,请查看他们的 GitHub 。
PyCaret 和 FastAPI 的工作流
👉正在安装 PyCaret
安装 PyCaret 非常容易,只需要几分钟。我们强烈建议使用虚拟环境来避免与其他库的潜在冲突。
PyCaret 的默认安装是 pycaret 的精简版本,只安装这里列出的硬依赖项。
**# install slim version (default)** pip install pycaret**# install the full version**
pip install pycaret[full]
当您安装 pycaret 的完整版本时,这里列出的所有可选依赖项也会被安装。
👉安装 FastAPI
您可以从 pip 安装 FastAPI。
pip install fastapi
👉商业问题
对于本教程,我将使用一个非常受欢迎的案例研究,由达顿商学院发表在哈佛商学院。这个案子是关于两个未来将要结婚的人的故事。名叫格雷格的家伙想买一枚戒指向一个名叫莎拉的女孩求婚。问题是找到莎拉会喜欢的戒指,但在他的密友建议后,格雷格决定买一颗钻石,这样莎拉就可以决定她的选择。然后,格雷格收集了 6000 颗钻石的价格和切割、颜色、形状等属性数据。
👉数据
在本教程中,我将使用一个数据集,该数据集来自达顿商学院的一个非常受欢迎的案例研究,发表在哈佛商业上。本教程的目标是根据钻石的重量、切割、颜色等属性来预测钻石的价格。您可以从 PyCaret 的存储库下载数据集。
**# load the dataset from pycaret** from pycaret.datasets import get_data
data = get_data('diamond')
数据中的样本行
👉探索性数据分析
让我们做一些快速可视化来评估独立特征(重量、切割、颜色、净度等)之间的关系。)与目标变量即Price
**# plot scatter carat_weight and Price**
import plotly.express as px
fig = px.scatter(x=data['Carat Weight'], y=data['Price'],
facet_col = data['Cut'], opacity = 0.25, template = 'plotly_dark', trendline='ols',
trendline_color_override = 'red', title = 'SARAH GETS A DIAMOND - A CASE STUDY')
fig.show()
莎拉得到了一份钻石案例研究
让我们检查目标变量的分布。
**# plot histogram**
fig = px.histogram(data, x=["Price"], template = 'plotly_dark', title = 'Histogram of Price')
fig.show()
请注意,Price
的分布是右偏的,我们可以快速查看对数变换是否可以使Price
接近正态,从而给假设正态的算法一个机会。
import numpy as np**# create a copy of data**
data_copy = data.copy()**# create a new feature Log_Price**
data_copy['Log_Price'] = np.log(data['Price'])**# plot histogram**
fig = px.histogram(data_copy, x=["Log_Price"], title = 'Histgram of Log Price', template = 'plotly_dark')
fig.show()
这证实了我们的假设。这种转换将帮助我们摆脱偏态,使目标变量接近正态。基于此,我们将在训练我们的模型之前转换Price
变量。
👉数据准备
对于 PyCaret 中的所有模块来说,setup
是在 PyCaret 中执行的任何机器学习实验中的第一个也是唯一一个强制步骤。该功能负责训练模型之前所需的所有数据准备。除了执行一些基本的默认处理任务,PyCaret 还提供了一系列预处理功能。要了解 PyCaret 中所有预处理功能的更多信息,您可以查看这个链接。
**# init setup**
from pycaret.regression import *
s = setup(data, target = 'Price', transform_target = True)
pycaret.regression 模块中的设置函数
每当在 PyCaret 中初始化setup
函数时,它都会分析数据集并推断所有输入要素的数据类型。在这种情况下,你可以看到除了Carat Weight
所有其他特征都被推断为分类,这是正确的。您可以按 enter 键继续。
注意,我在setup
中使用了transform_target = True
。PyCaret 将使用 box-cox 变换在后台转换Price
变量。它以类似于日志转换*(技术上不同)*的方式影响数据的分布。如果你想了解更多关于 box-cox 变换的知识,你可以参考这个链接。
设置的输出—为显示而截断
👉模型训练和选择
现在数据准备工作已经完成,让我们使用compare_models
功能开始训练过程。此函数训练模型库中可用的所有算法,并使用交叉验证评估多个性能指标。
**# compare all models**
best = compare_models()
compare_models 的输出
基于平均绝对误差的最佳模型是CatBoost Regressor
。使用 10 倍交叉验证的 MAE 为 543 美元,而钻石的平均价值为 11,600 美元。这还不到 5%。对于我们到目前为止所付出的努力来说还不错。
**# check the residuals of trained model**
plot_model(best, plot = 'residuals_interactive')
最佳模型的残差和 QQ 图
**# check feature importance**
plot_model(best, plot = 'feature')
最佳模型的特征重要性
完成并保存管道
现在让我们最终确定最佳模型,即在包括测试集在内的整个数据集上训练最佳模型,然后将管道保存为 pickle 文件。
**# finalize the model**
final_best = finalize_model(best)**# save model to disk** save_model(final_best, 'diamond-pipeline')
👉部署
首先,我们来了解一下为什么要部署机器学习模型?
机器学习模型的部署是使模型在生产中可用的过程,其中 web 应用程序、企业软件和 API 可以通过提供新的数据点和生成预测来使用经过训练的模型。通常建立机器学习模型,以便它们可以用于预测结果(二进制值,即用于分类的 1 或 0,用于回归的连续值,用于聚类的标签等)。生成预测有两种主要方式(I)批量预测;以及(ii)实时预测。本教程将展示如何将您的机器学习模型部署为 API 以进行实时预测。
既然我们已经理解了为什么部署是必要的,并且我们已经具备了创建 API 所需的一切,即作为 pickle 文件的训练模型管道。使用 FastAPI 创建 API 非常简单。
https://gist . github . com/moe zali 1/4bd 5312d 27884d 7 b 07 f 66 bef CDC 28 CCF
代码的前几行是简单的导入。第 8 行正在通过调用FastAPI()
初始化一个 app。第 11 行从您的磁盘加载训练好的模型diamond-pipeline
(您的脚本必须与文件在同一个文件夹中)。第 15–20 行定义了一个名为predict
的函数,它接受输入,并在内部使用 PyCaret 的predict_model
函数来生成预测,并将值作为字典返回(第 20 行)。
然后,您可以通过在命令提示符下运行以下命令来运行该脚本。在执行此命令之前,您必须与 python 脚本和模型 pickle 文件位于同一目录下。
uvicorn main:app --reload
这将在本地主机上初始化一个 API 服务。在您的浏览器上键入http://localhost:8000/docs,它应该显示如下内容:
http://本地主机:8000/docs
点击绿色的**POST**
按钮,会打开一个这样的表单:
点击右上角的**“试用”**,在表格中填写一些值,然后点击“执行”。如果您做了所有正确的事情,您将看到以下响应:
来自 FastAPI 的响应
请注意,在响应主体下,我们有一个预测值 5396(这是基于我在表单中输入的值)。这意味着,考虑到您输入的所有属性,这颗钻石的预测价格为 5396 美元。
这太好了,这表明我们的 API 正在工作。现在我们可以使用 Python 或任何其他语言中的requests
库来连接 API 并生成预测。我为此创建了如下所示的脚本:
https://gist . github . com/moe zali 1/545 be 5743 b 61 aa 5477228 b 8727 e 40 b 59
让我们来看看这个函数的运行情况:
为进行 API 调用而创建的 get_prediction 函数
请注意,预测值是 5396,这是因为我在这里使用了与上表中相同的值。(1.1,“理想”,“H”,“SII”,“VG”,“EX”,“GIA”)
我希望你会喜欢 PyCaret 和 FastAPI 的易用性和简单性。在不到 25 行代码和几分钟的实验中,我使用 PyCaret 训练和评估了多个模型,并使用 API 部署了 ML 管道。
即将推出!
下周我将写一篇教程来推进部署到下一个级别,我将在下一篇教程中介绍像容器化和码头工人这样的概念。请关注我的媒体、 LinkedIn 、 Twitter 获取更多更新。
使用 Python 中的这个轻量级工作流自动化库,您可以实现的目标是无限的。如果你觉得这很有用,请不要忘记给我们 GitHub 库上的⭐️。
要了解更多关于 PyCaret 的信息,请关注我们的 LinkedIn 和 Youtube。
加入我们的休闲频道。此处邀请链接。
您可能还对以下内容感兴趣:
使用 PyCaret 2.0
在 Power BI 中构建您自己的 AutoML 使用 Docker
在 Azure 上部署机器学习管道在 Google Kubernetes 引擎上部署机器学习管道
在 AWS Fargate 上部署机器学习管道
构建和部署您的第一个机器学习 web 应用
使用 AWS Fargate 无服务器
构建和部署机器
重要链接
文档
博客
GitHub
stack overflow
安装 PyCaret 笔记本教程 投稿于 PyCaret
想了解某个特定模块?
单击下面的链接查看文档和工作示例。
使用 Streamlit 构建您的第一个 Python 数据质量检查 Web 应用程序
最终产品快照。点击查看 app 。
质量从来不是偶然;它总是高度的意图、真诚的努力、明智的指导和熟练的执行的结果;它代表了多种选择中的明智选择。
M 保持数据集的质量不是一项简单的任务。众所周知,数据质量的下降通常会引入偏差,导致误导性结果,最终对业务产生不利影响。根据 Gartner research 的调查,数据质量差给组织带来的平均经济影响为每年 970 万美元。类似地,来自 IBM 的数据表明,仅在美国,由于数据质量低下,企业每年损失 3.1 万亿美元。数据质量低不仅仅是一个货币问题;这也有可能损害公司的声誉。
数据质量是一个普遍的问题。Forrester的研究表明,在进入决策流程之前,分析师三分之一的时间中有近 40%用于筛选和确认分析数据。
数据质量是业务运营、规划和发展的关键。然而,数据质量是由不同的因素定义的,有些是主观的,有些是客观的。因此,积累数据质量的所有参数是一个十亿美元的问题。
在这篇博客中,我们将学习创建一个 Streamlit python 应用程序,根据以下指标检查数据的基本质量:
1.缺失值/ NaN
2。完成率
3。重复率
4。正规性检验
这里是这个 tutoria l 的完整代码,如果你想跟随你的教程,这里是 演示 。
导入库
import os
import streamlit as st
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
from PIL import Image
导入库后,我们将自定义文本和表格的宽度。此外,我们将隐藏默认的页脚文本。
def main():
def _max_width_():
max_width_str = f"max-width: 1000px;"
st.markdown(
f"""
<style>
.reportview-container .main .block-container{{
{max_width_str}
}}
</style>
""",
unsafe_allow_html=True,
)# Hide the Streamlit header and footer
def hide_header_footer():
hide_streamlit_style = """
<style>
footer {visibility: hidden;}
</style>
"""
st.markdown(hide_streamlit_style, unsafe_allow_html=True)# increases the width of the text and tables/figures
_max_width_()# hide the footer
hide_header_footer()
现在,我们将创建一个选项来选择准备好的数据集或允许用户上传他们自己的文件。
st.markdown("# Data Quality Checker ✅")
st.markdown("Check the basic quality of any dataset")
st.markdown("---")st.subheader(" [Read full tutorial at Medium.]([https://medium.com/@maladeep.upadhaya](https://medium.com/@maladeep.upadhaya)) | [Complete code at GitHub]([https://github.com/maladeep](https://github.com/maladeep))")
st.markdown("---")
def file_select(folder='./datasets'):
filelist=os.listdir(folder)
selectedfile=st.selectbox('select a default dataset',filelist)
return os.path.join(folder,selectedfile)if st.checkbox('Select dataset from local machine'):
data=st.file_uploader('Upload Dataset in .CSV',type=['CSV'])
if data is not None:
df=pd.read_csv(data)
else:
filename=file_select()
st.info('You selected {}'.format(filename))
if filename is not None:
df=pd.read_csv(filename)
st.markdown("---")
直到这段代码,我们有了以下结果。现在我们将开始实现探索数据质量的必要部分。
图片作者。点击查看应用。
数据集和形状的快照
#show data
if st.checkbox('Show Dataset'):
num=st.number_input('No. of Rows',5,10)
head=st.radio('View from top (head) or bottom (tail)',('Head','Tail'))if head=='Head':
st.dataframe(df.head(num))
else:
st.dataframe(df.tail(num))
st.markdown("---")
if st.checkbox('Rows & Columns size'):
st.markdown("Number of rows and columns helps us to determine how large the dataset is.")
st.text('(Rows,Columns)')
st.write(df.shape)st.markdown("---")
图片作者。点击查看 app 。
检查缺少的值
缺失值称为空值或 NaN 值。在大多数情况下,缺失数据会导致偏差,从而导致模糊的结果。
#check for null values
if st.checkbox('Missing Values'):
st.markdown("Missing values are known as null or NaN values. Missing data tends to **introduce bias that leads to misleading results.**")st.write("Number of rows:", len(df))
dfnull = df.isnull().sum()/len(df)*100
totalmiss = dfnull.sum().round(2)
st.write("Percentage of total missing values:",totalmiss)
st.write(dfnull)
if totalmiss <= 30:
st.success("Looks good! as we have less then 30 percent of missing values.")
else:
st.success("Poor data quality due to greater than 30 percent of missing value.")st.markdown(" > Theoretically, 25 to 30 percent is the maximum missing values are allowed, there’s no hard and fast rule to decide this threshold. It can vary from problem to problem.")
st.markdown("[Learn more about handling missing values]([https://medium.datadriveninvestor.com/easy-way-of-finding-and-visualizing-missing-data-in-python-bf5e3f622dc5](https://medium.datadriveninvestor.com/easy-way-of-finding-and-visualizing-missing-data-in-python-bf5e3f622dc5))")
理论上,25%到 30%是允许的最大缺失值,没有硬性规定来决定这个阈值。它可能因问题而异。
图片作者。点击查看 app 。
完整率
完整性定义为数据集中非缺失值与记录总数的比率。实际上,大于 0.85 的完全率是可接受的。
#check for completeness ratio
if st.checkbox('Completeness Ratio'):
st.markdown(" Completeness is defined as the ratio of non-missing values to total records in dataset.")
# st.write("Total data length:", len(df))
nonmissing = (df.notnull().sum().round(2))
completeness= round(sum(nonmissing)/len(df),2)
st.write("Completeness ratio:",completeness)
st.write(nonmissing)if completeness >= 0.80:
st.success("Looks good! as we have completeness ratio greater than 0.85.")
else:
st.success("Poor data quality due to low completeness ratio( less than 0.85).")
图片作者。点击查看 app 。
复制率
重复率定义为数据集中的重复记录数除以记录总数。没有硬性规定来决定门槛。它可能因问题而异。
#check dupication rate
if st.checkbox('Duplication Rate'):
st.markdown(" Duplication rate is defined as the ratio of number of duplicates to total records in dataset.")
duplicated = df.duplicated().sum()
dupratio= round(duplicated/len(df),2)
st.write("Duplication rate:",dupratio)
st.markdown(" > There’s no hard and fast rule to decide the threshold. It can vary from problem to problem.")
图片作者。点击查看 app 。
正规性检验
正态性检验用于确定数据集是否由正态分布很好地建模。对于正态性检验,我们可以使用偏斜度技术,这是一种量化分布被向左或向右推的程度,是分布不对称性的一种度量。
#check for normality test
if st.checkbox('Normality'):images=Image.open('images/n.png')
st.image(images,width=600, caption="Image from ALVARO.")st.markdown("Normality tests are used to determine if a dataset is well-modeled by a normal distribution. For normality test we can use skewness technique which is a quantification of how much a distribution is pushed left or right, a measure of asymmetry in the distribution.")
aa= pd.DataFrame(df).skew()
normalityskew= round(aa.mean(),4)
st.write("How far is my dataset from Normal Distribution:", normalityskew)if normalityskew == 0 :
st.success("Your dataset is in Normal Distribution i.e mean, mode and median are all equal ")
elif normalityskew > 0:
st.success("Positively Skew so Mean > Median > Mode")elif normalityskew < 0:
st.success("Negatively Skew so Mode > Median > Mean")
图片作者。点击查看应用。
这就完成了我们用 Streamlit 构建的基于 python 的数据质量检查 web 应用程序。这只是理解数据集质量的一个小方法。维护和验证数据的质量是关键所在,应该承担很大的责任。
引用亨利·福特的话作为结束语:
质量意味着在没人看的时候做对。
点击此处,了解关于从 DataCamp 免费创建 python 应用程序的更多信息。(附属链接)
GitHub 提供完整代码:
https://github.com/maladeep/data-quality-checker
想进一步讨论这个吗?请在 Linkedin 上发表评论或与我联系。
推荐读物
https://www.datapine.com/blog/data-quality-management-and-metrics/
构建您的首个数据科学应用
七个 Python 库,打造您的第一个数据科学 MVP 应用
凯利·西克玛在 Unsplash 上的照片
要制作我的第一个数据科学应用程序,我需要学习什么?web 部署呢?web 应用需要学习 Flask 或者 Django 吗?做深度学习应用需要学习 TensorFlow 吗?我应该如何制作我的用户界面?我也需要学习 HTML、CSS 和 JS 吗?
当我开始学习数据科学的旅程时,这些是我脑海中一直存在的问题。我学习数据科学的目的不仅仅是开发模型或清理数据。我想开发人们可以使用的应用程序。我在寻找一种快速制作 MVP(最小可行产品)的方法来测试我的想法。
如果你是一名数据科学家,并且想开发你的第一个数据科学应用程序,在本文中,我将向你展示 7 个 Python 库,你需要学习它们来开发你的第一个应用程序。我相信你已经知道其中一些,但我在这里提到它们是为了那些不熟悉它们的人。
照片由 Med Badr Chemmaoui 在 Unsplash 拍摄
熊猫
数据科学和机器学习应用都是关于数据的。大多数数据集是不干净的,它们需要为你的项目进行某种清理和操作。Pandas 是一个库,可以让你加载、清理和操作你的数据。您可以使用 SQL 之类的替代方法进行数据操作和数据库管理,但是 Pandas 对于您这样一个想成为开发人员(或者至少是 MVP 开发人员)的数据科学家来说要容易得多,也更适用。
点击了解更多关于熊猫的信息。
Numpy
在许多数据科学项目中,包括计算机视觉,数组是最重要的数据类型。Numpy 是一个强大的 Python 库,允许您使用数组、操作数组,并高效地对数组应用算法。学习 Numpy 对于使用我稍后提到的其他一些库是必要的。
点击安装并了解更多关于 Numpy 的信息。
SciKitLearn
这个库是许多类型的机器学习模型和预处理工具的工具包。如果你正在做一个机器学习项目,有一点点可能你不需要 SciKitLearn。
安装并了解更多关于 SciKit 的信息-点击了解。
喀拉斯或皮托尔奇
神经网络,尤其是深度神经网络模型,是数据科学和机器学习中非常流行的模型。许多计算机视觉和自然语言处理方法都依赖于这些方法。几个 Python 库提供了对神经网络工具的访问。TensorFlow 是最著名的一个,但我相信初学者很难从 TensorFlow 入手。而是建议你学习 Keras,它是 Tensorflow 的一个接口(API)。Keras 使您作为一个人可以轻松测试不同的神经网络架构,甚至构建自己的架构。另一个最近越来越流行的选择是 PyTorch。
安装并了解更多关于 Keras 和 PyTorch 的信息。
要求
如今,许多数据科学应用程序都在使用 API(应用程序编程接口)。简而言之,通过 API,您可以请求服务器应用程序允许您访问数据库或为您执行特定的任务。例如,Google Map API 可以从您那里获得两个位置,并返回它们之间的旅行时间。没有 API,你必须重新发明轮子。Requests 是一个与 API 对话的库。如今,不使用 API 很难成为一名数据科学家。
点击安装并了解更多请求。
Plotly
绘制不同类型的图表是数据科学项目的重要组成部分。虽然 Python 中最流行的绘图库是 matplotlib,但我发现 Plotly 更专业、更易用、更灵活。Plotly 中的绘图类型和绘图工具非常多。Plotly 的另一个优点是它的设计。与具有科学外观的 matplotlib 图形相比,它看起来更加用户友好。
点击安装并了解更多关于 Plotly 的信息。
ipywidgets
谈到用户界面,你必须在传统外观的用户界面和基于网络的用户界面之间做出选择。您可以使用像 PyQT 或 TkInter 这样的库来构建传统外观的用户界面。但是我的建议是制作可以在浏览器上运行的 web 外观的应用程序(如果可能的话)。要实现这一点,您需要使用一个在浏览器中为您提供一组小部件的库。ipywidgets 为 Jupyter Notebook 提供了丰富的小部件。
点击安装 ipywidgets 并了解更多信息。
Jupyter 笔记本和瞧
创建第一个数据科学应用程序需要学习的最后一些工具是最简单的。第一,ipywidgets 在 Jupyter 笔记本中工作,你需要使用 Jupyter 来制作你的应用。我相信你们中的许多人已经在使用 Jupyter 笔记本进行建模和探索性分析。现在,把 Jupyter 笔记本想象成前端开发的工具。还有,你需要使用 Voila,一个你可以启动的第三方工具,它隐藏了 Jupyter Notebook 的所有代码部分。当您通过 Voila 启动 Jupyter 笔记本应用程序时,它就像一个 web 应用程序。您甚至可以在 AWS EC2 机器上运行 Voila 和 Jupyter 笔记本,并从互联网访问您的简单应用程序。
点击安装并了解更多关于的信息。
摘要
使用我在本文中提到的 7 个库,您可以构建人们使用的数据科学应用程序。通过成为使用这些工具的大师,您可以在几个小时内构建 MVP,并与真实用户一起测试您的想法。后来,如果您决定扩展您的应用程序,除了 HTML、CSS 和 JS 代码之外,您还可以使用更专业的工具,如 Flask 和 Django。
使用 Streamlit 构建您的第一个 Python 数据可视化 Web 应用程序
在不到 20 分钟的时间内,使用 Streamlit 视觉表达功能进行自我探索式可视化
最终产品快照。图片作者。Allison Horst 的作品。
作为数据科学弟子,我以前更多的工作是在 jupyter 笔记本上,进行 EDA ,设计开发模型,只在笔记本上展示结果。有时,我试图连接 Flask 模型,并为观众提供一个工作视图,但连接和开发一个具有前端的模型似乎既耗时又繁琐。然后我开始探索 alternative 并来到 Streamlit,这是一种分享机器学习/数据科学模型、分析和可视化的好方法,完全不用担心前端。
" Streamlit 是 ML 和数据科学工具的下一步."—来自 Vega-Lite 的张秀坤·莫提兹
社区喜欢它。图片来自 Streamlit 网站。
Streamlit 是一个发展迅速的开源 Python 库,可以轻松地为数据科学及其子领域制作漂亮的定制 web 应用。它也是一个优秀的工具,允许我们创建高度交互式的仪表板。Streamlit 最大的优点是,它不需要任何 web 开发知识。如果你懂 Python,你就可以开始了!
我喜欢 streamlit,因为它为非技术团队带来了一些高级模型和视觉效果。它可以让你从 jupyter 笔记本变成一个时尚的网络应用,值得以最小的努力提供给观众。
在这里,我们将学习通过使用 Streamlit visual expression 的强大功能来构建自我探索的可视化,我假设您对使用 jupyter notebook 有很好的理解。
这是本教程的完整代码如果你想继续学习本教程,这是最终产品。
最终产品。作者 Gif。
要求
- Python 3.7 版本或更高版本
- Streamlit 0.60 版本或更高版本
- 熊猫图书馆
- 数字图书馆
- Seaborn 图书馆
- Matplotlib 库
- Python 脚本的升华文本编辑器
我们开始吧
让我们首先通过 Mac 的终端或 windows 的命令提示符将 Streamlit 安装到我们的系统中。这里我使用终端。
$ pip install streamlit
一旦完成,让我们运行 Streamlit。
$ streamlit hello
运行上述命令后,localhost 服务器将在您的浏览器中打开,自动显示包含少量演示内容的 Streamlit 主页。
本地服务器上细流的主页。图片作者。
对于这个演示,我使用的是帕尔默企鹅数据。数据由克里斯汀·戈尔曼博士和LTER 南极洲帕尔默站收集并提供。在这里,我们将数据保存为“Penguin data.csv”
https://github.com/allisonhorst/palmerpenguins
目标
在帕尔默企鹅上创建自我探索可视化,用户可以
1。探索 daw 数据
2。参见统计描述
3。创建自己的图形(计数图、箱线图和显示图,根据用户的选择)
一旦我们下载了数据,让我们在任何文本编辑器中打开一个新文件(这里我使用的是 sublime 文本编辑器,并将其命名为 app.py
正在导入核心包,请注意我们正在使用*‘ST’*作为 Streamlit 命令。
import streamlit as st
from PIL import Image
导入数据可视化和数据操作包
import matplotlib.pyplot as plt
import matplotlib
matplotlib.use("Agg")
import seaborn as snsimport pandas as pd
import numpy as np
正在连接数据。
DATA_URL = ("Penguin data.csv")
到目前为止,我们的代码是这样的
图片作者。
现在,让我们使用减价来给出一些标题和一些信息(你一定会觉得哇,是的,减价是被接受的,_ )。此外,让我们添加一个图像。
请记住,您可以使用 st.markdown( ) 而不是 streamlit.markdown( ) ,因为我们将 streamlit 导入为’ st’ 。
st.markdown("# Self Exploratory Visualization on palmerpenguins")
st.markdown(“Explore the dataset to know more about palmerpenguins”)img=Image.open('images/palmerpenguins.png')
st.image(img,width=100)st.markdown(“**Penguins** are some of the most recognizable and beloved birds in the world and even have their own holiday: **World Penguin Day is celebrated every year on April 25**. Penguins are also amazing birds because of their physical adaptations to survive in unusual climates and to live mostly at sea. Penguins propel themselves through water by flapping their flippers. Bills tend to be long and thin in species that are primarily fish eaters, and shorter and stouter in those that mainly eat krill.”)st.markdown(“The data presented are of 3 different species of penguins - **Adelie, Chinstrap, and Gentoo,** collected from 3 islands in the **Palmer Archipelago, Antarctica.**”)
要在终端或命令提示符下运行应用程序:
$ streamlit run app.py
一旦你运行应用程序,这是结果。
图片作者。
现在,为了使过程更具交互性,让我们使用 st.button 添加一个按钮,一旦用户点击它,我们将使用 st.balloons( ) 显示一个带有一些气球效果的图像
if st.button("Meet the Palmer Penguins"):
img=Image.open('images/lter_penguins.png')
st.image(img,width=700, caption="We are Penguin 🐧")st.markdown(
"The data was collected and made available by **[Dr. Kristen Gorman]([https://www.uaf.edu/cfos/people/faculty/detail/kristen-gorman.php)**](https://www.uaf.edu/cfos/people/faculty/detail/kristen-gorman.php)**) and **[Palmer Station, Antarctica, LTER]([https://pal.lternet.edu/)**](https://pal.lternet.edu/)**).")
images=Image.open('images/meet.png')
st.image(images,width=600)
#Ballons
st.balloons()
在这里,您不需要重新运行应用程序,因为 Streamlit 会自动更新。您将看到一个带有文本的按钮:遇见帕尔默企鹅
图片作者。
一旦你点击按钮,我们就会看到这些可爱的企鹅和飞行气球的图片。
图片作者。Allison Horst 的作品。
现在,让我们使用 st.info( ) 突出显示数据中的内容,并再次添加一些图片。
st.info(“ The dataset contains the different aspect between the species like Body Mass (g), Flipper Length (mm), Culmen Length (mm), Culmen Depth (mm) etc.”)
img=Image.open(‘images/beak.jpg’)
st.image(img,width=700)
它呈现出
图片作者。由艾莉森·霍斯特创作的艺术品。
现在,允许用户探索数据的时刻到来了。我们将使用 st.sidebar 创建一个侧面板,并使用 st.sidebar.markdown( ) 在其上添加一些 markdown,我们将添加一些按钮来根据他们的需要浏览数据。我们还需要用 nrows 选项加载数据,解析它,并在数据完成时向用户显示信息。
st.sidebar.markdown("## Side Panel")
st.sidebar.markdown(“Use this panel to explore the dataset and create own viz.”)df = pd.read_csv(DATA_URL, nrows = nrows)
lowercase = lambda x:str(x).lower()
df.rename(lowercase, axis='columns',inplace=True)
return dfst.header(“Now, Explore Yourself the Palmer Penguins”)
# Create a text element and let the reader know the data is loading.
data_load_state = st.text('Loading palmerpenguins dataset...')
# Load 10,000 rows of data into the dataframe.
df = load_data(100000)
# Notify the reader that the data was successfully loaded.
data_load_state.text('Loading palmerpenguins dataset...Completed!')images=Image.open('images/meet.png')
st.image(images,width=600)
在我们的侧边栏上工作,我们为用户的自我探索添加选项和信息。
我们在此添加:
- 标题带 st.title( )
- 副标题为 st.subheading( )
- 带 st.checkbox()的复选框
- 用 st.write() 在屏幕上写入输出
# Showing the original raw data
if st.checkbox("Show Raw Data", False):
st.subheader('Raw data')
st.write(df)st.title('Quick Explore')
st.sidebar.subheader(' Quick Explore')
st.markdown("Tick the box on the side panel to explore the dataset.")
if st.sidebar.checkbox('Basic info'):
if st.sidebar.checkbox('Dataset Quick Look'):
st.subheader('Dataset Quick Look:')
st.write(df.head())
if st.sidebar.checkbox("Show Columns"):
st.subheader('Show Columns List')
all_columns = df.columns.to_list()
st.write(all_columns)
if st.sidebar.checkbox('Statistical Description'):
st.subheader('Statistical Data Descripition')
st.write(df.describe())
if st.sidebar.checkbox('Missing Values?'):
st.subheader('Missing values')
st.write(df.isnull().sum())
它呈现出
图片作者。
如您所见,我们使用了 Streamlit 语法,并在其中加入了 Python 数据操作和可视化代码。
**例如:**为了看一下 jupyter 笔记本中的数据集,我们这样做:
df.head()
在 Streamlit 中,我们还允许用户选中复选框,使用 if 语句查看原始数据:
if st.sidebar.checkbox('Dataset Quick Look'):
st.subheader('Dataset Quick Look:')
st.write(df.head())
现在,我们将深入创建图形。概念与上面的例子相同,即我们将使用 Streamlit 中的 seaborn 库来显示图形,由 if 语句控制。我们正在创建计数图,直方图或散点图和箱线图。
st.title('Create Own Visualization')
st.markdown("Tick the box on the side panel to create your own Visualization.")
st.sidebar.subheader('Create Own Visualization')
if st.sidebar.checkbox('Graphics'):
if st.sidebar.checkbox('Count Plot'):
st.subheader('Count Plot')
st.info("If error, please adjust column name on side panel.")
column_count_plot = st.sidebar.selectbox("Choose a column to plot count. Try Selecting Sex ",df.columns)
hue_opt = st.sidebar.selectbox("Optional categorical variables (countplot hue). Try Selecting Species ",df.columns.insert(0,None))
fig = sns.countplot(x=column_count_plot,data=df,hue=hue_opt)
st.pyplot()
if st.sidebar.checkbox('Histogram | Distplot'):
st.subheader('Histogram | Distplot')
st.info("If error, please adjust column name on side panel.")
# if st.checkbox('Dist plot'):
column_dist_plot = st.sidebar.selectbox("Optional categorical variables (countplot hue). Try Selecting Body Mass",df.columns)
fig = sns.distplot(df[column_dist_plot])
st.pyplot()
if st.sidebar.checkbox('Boxplot'):
st.subheader('Boxplot')
st.info("If error, please adjust column name on side panel.")
column_box_plot_X = st.sidebar.selectbox("X (Choose a column). Try Selecting island:",df.columns.insert(0,None))
column_box_plot_Y = st.sidebar.selectbox("Y (Choose a column - only numerical). Try Selecting Body Mass",df.columns)
hue_box_opt = st.sidebar.selectbox("Optional categorical variables (boxplot hue)",df.columns.insert(0,None))
# if st.checkbox('Plot Boxplot'):
fig = sns.boxplot(x=column_box_plot_X, y=column_box_plot_Y,data=df,palette="Set3")
st.pyplot()
它呈现出
图片作者。
现在,稍微润色一下,添加数据源信息,艺术品确认。
st.sidebar.markdown("[Data Source]([https://data.world/makeovermonday/2020w28](https://data.world/makeovermonday/2020w28))")
st.sidebar.info(" [Source Article]([https://github.com/allisonhorst/palmerpenguins](https://github.com/allisonhorst/palmerpenguins)) | [Twitter Tags]([https://twitter.com/allison_horst/status/1270046399418138625](https://twitter.com/allison_horst/status/1270046399418138625))")
st.sidebar.info("Artwork by [Allison Horst]([https://twitter.com/allison_horst](https://twitter.com/allison_horst)) ")
st.sidebar.info("Self Exploratory Visualization on palmerpenguins - Brought To you By [Mala Deep]([https://github.com/maladeep](https://github.com/maladeep)) ")
st.sidebar.text("Built with ❤️ Streamlit")
它呈现出
图片作者。
这结束了我们的过程。这是本教程的完整代码,这是你刚刚和我一起开发的最终产品。
在短短 20 分钟内,你已经开发了一个自我探索的可视化应用程序。在这里,我们已经讨论了交互式小部件、数据框、标题、图像、降价、绘图渲染。现在,您可以尝试不同的数据集来创建交互式数据可视化应用程序,我将更高兴地看到您在 Streamlit 上的进展。
Streamlit 社区论坛 每周综述 精选
点击此处,了解更多关于从 DataCamp 免费创建此类应用的信息。(附属链接)**
如果你对这篇文章有任何疑问,或者想在你的下一个 Streamlit 项目上合作,请在LinkedIn上 ping 我。