TowardsDataScience-博客中文翻译-2020-四十-
TowardsDataScience 博客中文翻译 2020(四十)
需求预测:波士顿犯罪数据

能够预测某一天某一特定地点发生暴力犯罪可能性的模型。
需求预测是零售、供应链管理和物流领域的热门话题和永无止境的目标。决策者需要根据预测的需求优化他们的资源,因此它也与优化问题直接相关。
预测在其通常的机器学习用途中处理一维的时间序列数据。预测股票价格或跨年度购买数量是最常见的用例。像 ARIMA 这样的加性模型是这个领域中最古老的数学模型之一:

预测明确的趋势。看起来很简单,是吧?
使用这些众所周知的数据——几年来航空乘客的数量——来理解预测的基础当然是有帮助的。但即使乍一看,也不难猜到现实生活中的问题很少如此简单。
波士顿犯罪数据简介

马特·波波维奇在 Unsplash 上的照片
分析波士顿波士顿的开放数据中心发布各种城市数据。其犯罪事件报道就是其中之一。该市的表格数据列出了 2015 年以来的犯罪事件。我们可以在这里看到他们数据集中的主要特征(总共有 16 列):

- 事件编号:事件的唯一标识符
- 犯罪代码组:事件按犯罪类型分组
- 报告区域:报告区域的代码。
- 发生日期:事件发生的日期
- Lat:犯罪地点的纬度
- Long:犯罪地点的经度
他们的最新数据超过 40 万行。他们还将自己的数据集上传到 Kaggle 来介绍它并挑战数据科学界。
对犯罪类型及其趋势的分析肯定有助于我们了解这个城市的犯罪动态。但是如果我们能比这更进一步呢?
目标
历史数据集具有城市中不同类型犯罪的时间和空间维度。
因此,最令人兴奋的项目是在犯罪真正发生之前为社区预测犯罪。

不,不是那个方向! —图片由杰拉尔丁·杜克斯提供,来自皮克斯贝
现在我们需要一个框架来组织问题。仅仅预测一个街区或者大体上整个城市的犯罪数量,并没有说太多,也没有用。我们需要预测某个特定地区是否会发生罕见的犯罪。
此外……这类问题不常被研究,而波士顿的犯罪数据给了我们一个机会去调查一个具有挑战性的问题。为什么?更多信息请见挑战部分。
问题框架
这里我将遵循另一篇 论文中分享的方法,“使用数据分析的 犯罪预测:波士顿市的案例”。它包含了解决的核心。我将使用 Python 实现它,并对特性(较少的空间工程)和模型(Xgboost 以提高准确性)进行一些修改。我还会分享代码,这样每个人都可以跟着做,并尝试改进预测。我们可以总结如下:
- ****我们需要预测一些罕见事件(在本例中为暴力犯罪)在特定日期以空间特征发生的概率。这样,警察可以利用这一点每天集中在城市的特定地区,以防止暴力犯罪,或至少增加在那里巡逻的机会。
这个框架如何塑造数据解决方案?无需过多思考,我们可以说我们将:
- A 汇总每天每个地区/报告区域的历史犯罪数据。
- 标记这些地点和日期的组合,以便当天是否发生暴力犯罪。
- ****用概率预测二进制值。这是一个分类问题。可以使用基于逻辑回归或决策树的模型。
由于我们的数据集将非常不平衡,对机器学习模型和决策阈值进行一些调整将是必要的。请记住,我们预测的是罕见事件。

挑战—为什么不使用时间序列预测?
请注意,我们已经将预测问题转化为传统的机器学习分类。这是为什么呢?
如果我们需要预测多个值,就会出现困难,因为设置和分析 ARIMA 类型的模型并不容易。
那么我们需要为此建立多个模型吗?如果我们需要为数百个时间序列数据建立模型,会发生什么?这可行吗?
让我们列出当需求分布在城市中且没有明确边界的情况下,在很长一段时间内如一年,预测需求所面临的挑战。
考虑出租车需求预测可能是一个很好的起点,因为我们将遵循类似的逻辑。在这种情况下,我们有在特定日期从特定位置开始的出租车出行数据。预测需求的挑战如下:
- ****需求是空间分布的,是连续的。它没有中心。想想城市里的几个市场,它们都有固定的位置。您可以建立预测模型来预测它们中每一个的总销售额,但这里的情况并非如此。
- 即使您对需求进行聚类,也可能有太多的聚类中心来为每个聚类中心建立预测模型。
- 您知道某些特征(如天气或时间——如假期)会严重影响需求。但是在传统的时间序列建模中,不可能添加这些特征。深度学习( LSTM 模型举例)允许这样做。
现在,对于犯罪预测来说,还有一个额外的挑战。我们需要预测像暴力犯罪这样罕见的事件:
- 请记住,传统的时间序列预测处理的是数字数据。这里我们需要预测一个二进制值:0 或 1。
方法

****开始建造吧!谁需要方法?—马库斯·斯皮斯克在 Unsplash 上拍照
现在,让我们列出创建预测模型要做的事情:
- 划分空间以聚集每个空间单元(格网或报告区域)的需求
- 将犯罪类型分为暴力犯罪和非暴力犯罪。
- 每天汇总每个空间单元的历史犯罪数据。该行的标签将是 1 或 0,这取决于那天在该位置是否发生了暴力犯罪。
- 将历史天气数据集成为波士顿每天的一项功能。
- 将数据分为训练集和测试集。使用一个特定的日期,在该日期之前,训练数据约为 70%,在该日期之后,测试数据为所有数据集的 30%。
- 建立一个侧重于预测阳性标签的模型:增加真阳性率,即灵敏度。(稍后将详细介绍)
- 通过选择阈值来评估测试集的准确性和敏感性。
1-群需求
从这一点开始,你可以遵循 github repo 中的代码。
在对数据进行了一些探索之后,我们可以从“来自报告区域的集群中心”一节开始。通过取纬度和经度的平均值来计算报告区域中心:

用于可视化空间数据的 KeplerGL 包
显然,有一些异常值。通过使用此处的城市边界文件,我们绘制并提取波士顿多边形外的报告区域:
# load shape file for 500 cities
city_data = gpd.read_file("geodata/CityBoundaries.shp")# some spatial processing here...# select the reporting areas (points in geodf_ra) that are
# in geodf_boston polygon. using spatial join function
# in geopandas package
geodf_ra_inboston=gpd.sjoin(geodf_ra, geodf_boston, how="inner", op='within')

现在它们都在波士顿多边形内
在论文中,使用了 500 个网格。因此,按照同样的逻辑,我们可以创建 500 个集群,使需求中心更少,需求面分布更均匀。
# create 500 centers with K-means
clusterer = KMeans(n_clusters=500,random_state=101).fit(reporting_area_centers[["Long","Lat"]])
# get predictions from our Kmeans model
preds_1 = clusterer.predict(reporting_area_centers[["Long","Lat"]])
# set our new column: cluster_no
reporting_area_centers["cluster_no"]=preds_1

报告区域的 500 个集群中心。

报告区域聚集成 500 个中心。
2-集团犯罪类型
现在我们需要对犯罪类别进行分组(OFFENSE _ CODE _ GROUP ),以便将其中一些归类为暴力犯罪。我根据我的假设添加了这些类别,其中哪些是暴力犯罪,但是当然你可以交叉引用法律定义..
# check labeled crime groups: violent, property and other
# the crimes are grouped manually into 3 groups: violent, property or other
data_1718_ocg=pd.read_csv("./data/data_1718_ocg_grouped.csv")
被称为暴力犯罪的有:

3-汇总历史犯罪数据
至此,在笔记本文件中,我们已经到达了“为 ML 准备数据:为每个集群和日期组合聚集数据”部分。
我们有标有经纬度的聚类中心。现在我们需要预测功能!
****这是脚本的核心部分:每天计算所有聚类中心过去的犯罪统计数据。过去 120 天、30 天、7 天、1 天都是这样做的。
为了准备剧本,我先做了一天的计算。然后我写了一个全天的“for 循环”。
# check one of the lists:
# here we calculated sums for different crimes for the date: 2017-10-3
# they are aggregated for each clusters.
# in this table we see the results for the past 120 days
working_120_results.head()

在这里,我们可以看到仅一天内不同地区不同犯罪类型的总和。它是通过计算该地区前 120 天的相关犯罪类型来计算的。
在检查了结果的合理性之后,我们可以继续进行更大的计算:“计算过去 365 天和最后一天每天的统计数据。”现在我们运行一个循环来聚合每个集群和日期组合的历史犯罪数据。
# check resulting dataframe. This is going to be our baseline for train&test data
crime_stats_fordays_df.info()

所有历史预测特征被聚集

查看生成的数据框
4-整合天气数据
同样,根据这篇论文,我们希望将天气数据集成到我们的训练集中,作为一个预测功能。我们认为天气状况可能会影响暴力犯罪。
出于这个原因,我们可以使用 Python 包 wwo-hist ,它封装了来自世界天气在线的天气 API。我已经创建了一个免费试用帐户来收集所需的 API 密钥。你可以尝试其他选择,但这似乎是最快的解决方案。
# use package: [https://github.com/ekapope/WorldWeatherOnline](https://github.com/ekapope/WorldWeatherOnline)from wwo_hist import retrieve_hist_data# daily frequency.
frequency=24
start_date = '1-JAN-2015'
end_date = '31-DEC-2018'
api_key = 'your-api-key-comes-here'
location_list = ['boston,ma']# this one runs for all days from start_date to end_date
# and saves the results as csv to the current directory.
hist_weather_data = retrieve_hist_data(api_key,
location_list,
start_date,
end_date,
frequency,
location_label = False,
export_csv = True,
store_df = True)## some processing# include weather data to our aggregated data for: rain, cloud cover and minimum temperature.
# you can include more features herecrime_stats_fordays_df=pd.merge(crime_stats_fordays_df,weather_data[["date_time","precipMM","cloudcover","mintempC"]],left_on="theday",right_on="date_time")
我们使用云量、最低温度和降水量作为预测特征。
5-建模
首先,我们将数据分为训练集和测试集。因为这是时间序列预测,所以我们选择一个截止日期,使之前的数据对应于 70%的数据。
然后,我们决定功能列:
# feature set
x_columns=[ 'Lat', 'Long',
'sumviolentcrime120', 'sumpropertycrime120', 'sumothercrime120',
'sumviolentcrime30','sumpropertycrime30', 'sumothercrime30',
'sumviolentcrime7','sumpropertycrime7', 'sumothercrime7',
'sumviolentcrime1','sumpropertycrime1', 'sumothercrime1',
'precipMM','cloudcover', 'mintempC']# outcome
y_column=["isviolentcrime"]
请注意,与我们一直关注的论文不同,我们在这里使用经度和纬度来标识位置。这是因为如果您使用每个网格的收入数据,您将失去空间编码的“位置敏感”特性。简单来说,我们需要这样的空间特征,如果它们在二维空间中彼此接近,那么它们的编码就彼此接近。如果我们仅仅使用“收入数据”,我们就失去了这个特征,因为遥远的邻居可能有相同的平均收入。
这一选择的另一个结果是我们需要使用基于树的模型,因为纬度和经度在物流回归等线性模型中不携带信息。
我继续为模型使用“ Xgboost 分类器”。正如我们在开始时说的,这是一个分类问题。我们已经为每个聚类中心和每一天创建了聚合的历史特征。现在我们将根据这些历史特征和天气数据来预测那天是否发生了暴力犯罪。****
我跳过了模型的调优,以免过多地扩展文章,但是可以在 Jupyter 笔记本的“调优参数”一节中查看。
# tuned parameters: in the next session we run hyperparameter search with cross validation
# these parameters are gathered from that tuning session.
# so you can just continue with the tuned parameters
# you can switch back and forth between the baseline model and the tuned model to see the
# change in accuracy and other parametersxgb_model=xgb.XGBClassifier(base_score=0.5, booster='gbtree', colsample_bylevel=1,
colsample_bynode=1, learning_rate=0.1,
max_delta_step=0, missing=None,
n_estimators=100, n_jobs=1,
nthread=None,scale_pos_weight=83,
objective='binary:logistic', random_state=101,
subsample= 0.6,
min_child_weight= 10,
max_depth= 3,
gamma= 1,
colsample_bytree= 0.8)
6 阈值选择
现在我们有了将“isviolentcrime”目标标记为 1 或 0 的概率。但是,我们应该如何选择决策阈值来将行(区域和日期组合)标记为 1 或 0 呢?
从论文中得出的假设如下:让我们假设警察每天可以巡逻城市的 30%。这最终确定了我们问题的框架。我们需要这样一个模型,它能在 30%的时间里预测阳性标签。因此,警方每天将有 30%的区域被标记为阳性。
# 30 percent of the labels: 38250.0
X_train.shape[0]* 0.3# tune threshold so that 30 percent of all the labels are predicted as positive
# we found we can use 0.48 as our threshold# (38819,)
y_pred_prob_pos[y_pred_prob_pos>0.48].shape# it is 1 if greater than 0.48
xgb_predictions=np.where(y_pred_prob_pos>0.48,1,0)
7-评估
让我们检查一下培训数据的指标:
# my accuracy score: 0.7031058823529411
accuracy_score(y_train,xgb_predictions)train_confusion_matrix=confusion_matrix(y_train, xgb_predictions)pd.DataFrame.from_dict({"Negatives":train_confusion_matrix[0],
"Positives":train_confusion_matrix[1]},orient='index',columns=["Negative Pred.","Positive Pred."])

****注意,在 1523 个阳性病例中,我们的模型正确预测了 1244 个,因此具有 1244/1523=0.82 的真实阳性率。

真实阳性率公式来自维基百科

我们可以看到总体评估指标。请注意,标签 1 的召回率为 0.82。
现在是测试集:
****
我们的真阳性率(召回)下降到 0.73** 。**
其计算方式为 191 / (191+524)
我们还为训练数据设置了 30%正标签的阈值。我们在测试集中使用了相同的阈值,如果您检查:
# our predictor predicts 28 percent positive labels
# police needs to travel 28 percent of the area
xgb_predictions_test.sum() /y_test.shape[0]
在测试集中,甚至有更少的正面预测标签,这甚至更好。
摘要和用法
那么我们在这里做了什么?而且最重要的是,这种方法怎么用?
- 首先,我们对犯罪报告区域进行聚类,使 500 个需求中心平稳地分布在波士顿市。
- 我们将一些犯罪类别归类为暴力犯罪。
- 然后,我们使用历史犯罪数据来创建一个训练数据集。对于每个聚类中心和每一天,我们汇总过去的犯罪数据以用作预测特征:该地区过去 120 天、30 天、7 天等的暴力犯罪总数…该地区过去 120 天、30 天、7 天等的财产犯罪总数…
- 我们整合了历史天气数据作为预测特征。
- 我们建立了一个机器学习模型来预测那天和那个地区是否发生了暴力犯罪。

我们的训练数据。一些特征和目标变量:“isviolentcrime”
- 我们为我们的分类模型选择了一个阈值,使得 30%的预测是肯定的。
这意味着,如果对每个空间单元(在我们的例子中是分布在城市中的 500 个需求中心)的历史犯罪数据进行相应的汇总,警方就可以使用该模型来预测暴力犯罪。每天,警察可以运行这个模型,他们将得到大约 30%的聚类中心对暴力犯罪的积极预测。这相当于 500 个地点中的 150 个。他们甚至可以订购那些贴有正面标签的区域。排序将考虑相应的概率,从而优先考虑暴力犯罪的最危险区域。

比尔·牛津在 Unsplash 上的照片
凭借该模型的这一性能,警察只需巡逻 30%的区域,就可以捕获 70%的暴力犯罪。如果你分析历史犯罪数据,你会发现每天大约有 7 起暴力犯罪。根据我们的真实阳性率,警方可以预计每天大约有五起暴力犯罪。
结论
预测整个波士顿市的暴力犯罪问题尤其具有挑战性。它不同于通常的需求预测问题:
- 通常的需求预测模型有固定的需求和供应中心。
- 需求是一个连续的特征,就像总销售额或总请求量一样。
在我们的案例中:
- 需求在城市中不断分布。需要聚类。
- 需求是一个分类特征。问题是那里是否发生过暴力犯罪。
- 而作为一个二元分类问题,我们的数据集是高度不平衡的。阳性标签只占 2%左右。这给建模和调整增加了额外的挑战。
未来的工作
我们知道波士顿市有 12 个警察局/区。因此,我们可以尝试找到 12 个供应中心的最佳位置,以捕捉暴力犯罪的需求。
这个问题对应于设施选址问题。实际上我已经用 Python 的优化包做到了。我的下一篇文章将介绍和实现这些包来解决一个线性优化问题。
源代码和注释
我在我的 github repo 中分享了我的 Python 代码和准备好的数据。
参考
[1] G. Martegiani,L. Berrada,利用数据分析进行犯罪预测:波士顿市的案例 (2016 年)
[2] A .贾恩,波士顿犯罪数据/ Kaggle 数据集,(2018)
[3]分析波士顿,波士顿犯罪/卡格尔数据集,(2018)
[4] G. Sharma,出租车需求预测—纽约市—好观众 (2018)
使用 FB-Prophet 进行需求预测

来源:维基百科,时间序列预测
实施简单有效的需求预测方法
预测未来需求是一个基本的商业问题,任何成功解决这一问题的解决方案都将在不同的商业领域找到有价值的商业应用。在零售环境中,实施需求预测方法来做出有关购买、供应、补货和财务规划的决策。应用于需求预测和供应的一些常见时间序列方法包括移动平均法、指数平滑法和 ARIMA。Kaggle 时间序列预测竞赛中最受欢迎的模型是梯度推进模型,该模型将时间序列数据转换为表格数据,时间序列中的滞后项作为“特征”或表格中的列。
脸书先知模型是 GAM(广义加法模型)的一种类型,专门解决商业/计量经济学-时间序列问题。我在这个项目中的目标是应用和调查脸书先知模型在需求预测问题上的表现,为此,我使用了卡格尔 M5 需求预测竞赛数据集并参加了竞赛。该竞赛旨在在产品商店层面生成 28 天前的积分预测。
该数据集涉及 3049 种产品的单位销售额,分为 3 个产品类别(爱好、食品和家居)和 7 个部门。这些产品在 3 个州(加利福尼亚州、德克萨斯州和威斯康星州)的 10 家商店销售。该图概述了产品的聚合级别。竞争数据由沃尔玛提供。

图 1:时间序列层次和聚合级别的分解[2]

图 2:数据层次图[2]
来源:-https://mofc.unic.ac.cy/m5-competition/
数据描述
销售数据的数据范围是从 2011 年 1 月 29 日到 2016 年 6 月 19 日。因此,产品最多有 1941 天或 5.4 年的可用数据。(不包括 28 天的测试数据集)。
数据集分为日历数据、价格数据和销售数据[3]。
日历数据— 包含日期、工作日、月份、年份以及德克萨斯州、加利福尼亚州和威斯康星州的快照日等列。此外,该表通过其列 event_type1 和 event_type2 包含有关假日和特殊事件(如超级碗)的信息。节日/特殊活动分为文化、民族、宗教和体育活动[3]。
价格数据——该表由列组成——商店、商品、周和价格。它提供了某一周某一商店某一商品的价格信息。
销售数据 —由验证和评估文件组成。评估文件包括额外 28 天的销售额,可用于模型评估。该表提供了特定部门、特定州和商店中特定商品的销售量信息[3]。
数据可以在链接中找到—【https://www.kaggle.com/c/m5-forecasting-accuracy/data
数据分析和故事讲述

图 3:各状态下的销售数量

图 4:每个类别的销售额百分比

图 5:每个州的销售额百分比
从上面的图表中可以看出,在每个类别中,CA 的销售额最高,其次是 TX 和 WI。CA 贡献了约 50%的业余爱好销售额。这三个州的销售类别分布是对称的,在每个州按销售降序排列的最高销售类别是食品、家居和爱好。
价格数据分析


图 6:价格变化百分比= 100*(最高价格-最低价格)/最高价格


图 7:原木分布(售价)
上面的图表显示百分比价格变化是高度右偏的。对 sell_price 执行对数变换,使其分布更加对称。
快照日的影响

图 8:平均值。销售与快照日
上图显示,在所有 3 个州的抢购日都有较高的销售额。
调查销售数据的季节性

图 9:跨类别的时间序列分解

图 10:跨状态的时间序列分解
使用stats models . TSA . seasonal _ decompose函数对时间序列进行季节性分解。上面的图表显示了随着时间的推移,销售的线性增长(跨类别和州)以及季节性的影响。从 2014 年开始,线性在时间序列的后半部分尤为明显。在所有州和类别中都可以看到年度季节性。

图 11:每周季节性:一周中各天的销售额
上图显示了所有 3 个类别的每周季节性。周末和周一的销售额比平日高。

图 12:月度季节性-当月各天的销售额
上图显示了不同类别的月度季节性。我们看到的模式是,销售额在月初很高,然后稳步下降,接近月底时再次回升。

图 13:2011-2016 年不同类别的年度季节性
上面的图表显示了 2011 年至 2016 年各个类别的年度季节性。销售行为在每个类别中都是对称的,例如,2011 年的家庭销售额与 2012 年的家庭销售额相似,以此类推。这种历史数据在预测某个类别的年销售额时会很有用,例如,2011 年家庭销售额的数据在预测 2012 年家庭销售额时会很有用。
模型描述
对 Prophet 模型进行训练,并在产品商店级别进行预测。因此,30490 个不同的 prophet 模型在产品商店级别针对 30490 个不同的时间序列进行了训练。两年的训练数据和 28 天的预测/评估数据用于每个系列的模型训练和评估。最后 28 天的测试数据被 Kaggle 隐藏。下表显示了培训、评估和测试数据的划分-

训练-评估-测试数据分割
在所有时间序列中尝试了两个模型—
模型 1
def run_prophet(id1,data):
holidays = get_holidays(id1)
model = Prophet(uncertainty_samples=False,
holidays=holidays,
weekly_seasonality = True,
yearly_seasonality= True,
changepoint_prior_scale = 0.5
)
model.add_seasonality(name='monthly', period=30.5, fourier_order=2)
模式二
def run_prophet(id1,data):
holidays = get_holidays(id1)
model = Prophet(uncertainty_samples=False,
holidays=holidays,
weekly_seasonality = True,
yearly_seasonality= True,
changepoint_prior_scale = 0.5
)
model.add_seasonality(name='monthly', period=30.5, fourier_order=2)
model.add_regressor('log_sell_price')
模型 1 由假期、周季节性、年季节性和月季节性组成。
模型 2 由以下部分组成——假期、每周季节性、每年季节性、每月季节性,此外还有回归变量 log_sell_price = log(sales_price)。假设每个 product-store 系列中的最新 sales_price 在 28 天的预测范围内保持不变,并用于预测未来的销售额。
脸书先知模型类似于 GAM(广义相加模型),使用一个可分解的时间序列模型,该模型由三个部分组成——趋势、季节性和节假日——y(t)= g(t)+s(t)+h(t)+e(t)[4]。
Growth g(t): 默认情况下,Prophet 允许您使用线性增长模型进行预测。这里使用的就是这种模式[4]。
节假日 h(t):——先知考虑节假日影响。这里模拟的假日有宗教假日、文化假日、国家假日和快照日。Prophet 允许用户添加一个“上窗口”和“下窗口”,在假日日期前后扩展假日的效果。在当前模型中,0 天的上下窗口应用于快照日,1 天的上下窗口应用于其他节假日。Prophet 假设每个假日 D_i 是相互独立的[4]。
季节性 s(t): — 傅立叶级数用于模拟季节性影响。在下面给出的公式中,P 是正常周期(每周— 7 天,每年— 365.25 天)。拟合季节参数,需要拟合 2 N 个参数— beta = (a1,b1,… an,bn) [4]。

季节性傅立叶级数[4]
例如,对于年度数据,N = 10,季节分量 S(t)= X(t)*β

N=10 时的 x(t )[ 4]
平滑先验—beta~Normal(0,sigma)应用于 beta。增加傅里叶级数的项数 N 会增加模型的复杂性,并增加过度拟合的风险[4]。
建模变点 : —几个变点的参数可以用超参数“changepoint_prior_scale”调整。这在 Prophet 中的变点参数之前施加了稀疏。增加这个参数可以增加模型的灵活性[4]。
实施多重处理和优化运行时
from joblib import Parallel, delayedsubmission = Parallel(n_jobs=4,
backend="multiprocessing")(delayed(run_prophet)(comb_lst[i][0],comb_lst[i][1]) for i in range(30490))model.make_future_dataframe(periods=28, include_history=False)
FB Prophet 中的模型训练和预测比 ARIMA 模型或指数平滑模型需要更长的时间。由于我们在产品商店级别拟合模型 30490 次,因此有必要减少单个系列的运行时间,并将 30490 系列的训练和预测并行化。前者通过 1)在模型 1 &模型 2 中使用的 Prophet() 函数中设置“不确定性 _ 样本=假”来实现。这可防止为预测创建不确定性区间,以及 2)在用于模型预测的 make_future_dataframe() 函数中设置“include_history=False”(如上所示),这可防止 Prophet 显示适合训练数据集的模型。
joblib。Parallel() 函数用于实现 30490 系列拟合和预测的多重处理,如上面的代码片段所示。
模型评估
使用三个指标评估点预测的准确性——RMSE、RMSSE 和 WRMSSE。度量 WRMSSE 是 Kaggle 在比赛中使用的评估度量。

均方根误差

均方根标度误差

加权均方根标度误差
wi 是数据集中 42,840 个(包括如图 1 所示的各种级别的聚合)时间序列中每个时间序列的权重。权重是根据一段时间内该系列的累计美元销售额计算的。竞赛指南中给出了重量的更多细节—https://mofc.unic.ac.cy/m5-competition/
结果
模型 1 和模型 2 的性能如下所示。通过计算所有 30490 个产品商店时间序列的平均 RMSE 或 RMSSE 来计算平均 RMSE 和平均 RMSSE。可以看出,模型 2 中包含 log_price 提高了所有指标的性能。Kaggle 计算了隐藏测试数据集上的性能。

预测结果


图 14:https://github.com/Ritvik29/Walmart-Demand-Prediction<10 (R)
The graphs above show the RMSE distribution of the 30490 product-store time-series. As can be seen, the distribution is heavily right-skewed. The performance of both models is similar across all RMSE levels. For more details on the code and implementation kindly refer the GitHub repository -RMSE 分布(左)放大 RMSE 分布 RMSE
总之,FB- Prophet 中的季节性、变点、增长和假期等组件使其特别适合处理需求预测等商业时间序列问题。我建议分析师至少把 Prophet 作为建立需求预测模型的第一站。
参考
【1】https://www.kaggle.com/c/m5-forecasting-accuracy 卡格尔 M5 预测—准确率竞赛
https://mofc.unic.ac.cy/m5-competition/
【3】https://www.kaggle.com/c/m5-forecasting-accuracy/data 卡格尔 M5 —精准预测竞赛数据
****【4】泰勒·勒瑟姆(2017),《规模化预测》https://peerj.com/preprints/3190/
****【5】FB prophet—quick starthttps://Facebook . github . io/prophet/docs/quick _ start . html # python-API
人工智能民主化
双刃剑
当公司领导人谈论民主化人工智能(AI)时,不难想象他们的想法。越多的人能够接触到构建人工智能系统所需的知识、工具和数据的原材料,必然会出现越多的创新。效率提高,参与度增加。面临技术人才短缺?微软、亚马逊和谷歌都发布了预制、拖放或无代码的人工智能工具,允许人们将人工智能集成到应用程序中,而无需知道如何建立机器学习模型。
但随着公司走向民主化,一个警示故事正在浮现。即使是由高度合格的工程师设计的最复杂的人工智能系统,也可能成为偏见、可解释性问题和其他缺陷的牺牲品。由没有经过适当培训的人构建的人工智能系统,或者在没有适当控制的情况下运行的人工智能系统,可能会产生非常危险的东西——引入歧视或严重错误。更糟糕的是,问题可能直到系统实施后才变得明显,让公司争先恐后地安抚利益相关者,消除损害,修复技术。
这并不是说 AI 的民主化不是没有价值。让这些新技术变得更容易获得和负担得起,扩大了企业和政府所能实现的可能性,并刺激了竞争。例如,与抗击 COVID19 相关的数据集、模型、论文和研究已经开源,使大型全球社区能够进行协作。公司领导人的关键是避免被宣传冲昏头脑,而是专注于确定他们到底要民主化什么(是简单的东西,如数据可视化,还是复杂的东西,如模型开发?),用户是谁(新手还是专家),以及他们的组织如何通过适当的培训和治理来最大化收益,同时管理或减轻风险。
技术领域——民主化什么?
发布人工智能和机器学习(ML)产品的技术供应商需要从确定他们的工具或平台将民主化价值链的哪个或哪些部分开始。在这里,考虑一个范围(见下面的图 1)是有帮助的,在这个范围内,工具和模型变得越来越复杂,并产生更大的价值。
一方面是数据,将数据接收到数据仓库和数据湖中。人工智能系统,尤其是人工智能,运行在大量的结构化和非结构化数据上——这是你可以从中产生见解、决策和结果的材料。在其原始形式中,它很容易民主化,使人们能够进行基本的分析。许多技术提供商已经创建了数据浏览器,帮助用户搜索和可视化公开可用的数据集。
接下来是数据输入的算法。在这里,随着数据投入使用,价值和复杂性都在增加。在这一点上,民主化还是比较容易实现的,事实上算法是广泛可及的。像 GitHub 这样的开源代码库在过去的十年里有了显著的增长。2018 年 11 月,有超过 1 亿个代码库,其中相当一部分与人工智能相关。理解算法需要对计算机科学有一个基本的了解,并有一定的数学或统计学背景,才能理解算法的作用。
随着我们继续向存储和计算平台发展,复杂性也在增加。在过去的五年里,人工智能的技术平台随着亚马逊网络服务(AWS)、微软 Azure 和谷歌计算平台三大人工智能/人工智能提供商转移到了云。这使得中央处理单元和图形处理单元(对训练相当大的深度学习模型至关重要)可以在按需付费的基础上供最终用户使用,大大降低了准入门槛。然而,尽管算法是硬件不可知的(例如,它们通常可以在任何硬件或云平台上运行),但云存储和计算平台需要技术供应商(亚马逊、微软或谷歌)的特定培训和认证。
现在我们来看模型开发。模型解决具体问题:有的成为推荐引擎,有的成为面部识别,等等。在这里,我们看到了使用自动化平台和工具的民主化。例如,自动化接收各种数据格式(结构化、半结构化和非结构化)的能力,以及在同一数据集上运行多种算法并选择最佳算法集合的能力,使模型开发过程变得更容易(也更快)。但是,如果用户没有经过适当的培训,则很有可能在模型中产生偏见,无法解释模型的结果,甚至做出错误的决策。
最后,在光谱的远端,我们正处于创建数据、算法和模型市场的早期阶段。对于问题和能够解决这些问题的人才,也有一个新兴的市场。Kaggle 创建于 2010 年,于 2017 年被谷歌收购,是数据科学或人工智能市场最知名的例子之一。奖金丰厚的数据科学挑战赛,如卡格尔·网飞电影推荐挑战赛,让世界上任何地方的任何人都可以参与竞争并展示他们的技能。随着我们在这些市场中筛选数据、算法和模型,曲解它们并将其应用于错误环境的风险会显著增加。在这种情况下,系统滥用模型的危险将会增加。

图 1:民主化什么?
了解你的用户——为谁民主化?
设计一个人工智能系统需要广泛的技术知识和对数据科学的牢固掌握。就像你希望确保一名外科医生合格、训练有素并有手术室经验一样,人工智能系统应该由拥有扎实技术功底、了解人工智能系统关键组件并致力于负责任的人工智能的人来设计、测试和维护。
供应商经常发表笼统的声明,称他们已经通过创建拖放工具使数据接收、数据清理和数据挖掘民主化。或者他们通过自动化整个机器学习或数据科学过程,使复杂的统计和计算模型开发民主化。但是谁在使用这些工具和模型呢?他们是否接受过适当的培训——不仅是在工具方面,而且在基本概念方面?
在一个例子中,一个已经广泛使用拖放工具的组织的商业用户建立了一个机器学习模型,而没有留出数据样本用于验证和测试。因为模型过度符合训练数据,所以报告的模型准确性是有缺陷的。如果部署了该模型,可能会导致重大的财务损失。
AI 民主化的受益者存在于三大类——高级用户专业开发者* 。临时用户和专业开发人员处于相反的极端,而高级用户介于两者之间;后一组比临时用户更有知识,训练有素,但不是专家水平。商业用户通常是临时用户;他们既没有接受过模型背后的统计和数学概念方面的广泛培训,也没有接受过建立模型所需的具体过程方面的培训。专业开发人员或数据科学家通常具有很强的资格或适当的认证。*
公司需要确定他们的各种计划针对的是这三个类别中的哪一个。例如,当我们使数据可视化大众化时,我们使所有三种类型的用户能够快速创建各种各样的可视化,只需很少或不需要编程——这是一个低风险的提议。然而,当我们说我们正在使模型开发民主化时,我们是在为专业数据科学家做这件事,让他们能够运行不同的算法,评估它们,并选择正确的模型集合吗?或者,我们是不是也在尝试为临时用户和高级用户普及它?如果是后者,就需要格外小心。
民主化的好处——为什么要民主化?
人工智能的民主化提供了三个主要好处。首先,它降低了个人和组织开始尝试人工智能的门槛。他们可以利用公开可用的数据和算法,开始尝试在云基础设施上构建人工智能模型。世界上任何地方的个人,只要很少或没有金融投资(可能只是接入互联网),就可以进入令人兴奋的人工智能世界。他们不仅可以学习人工智能,还可以解决 Kaggle 等市场中的重要问题,以获得重大奖励。
其次,随着程序员和用户社区开始使用和扩展数据、算法和工具来构建更强大的解决方案,民主化降低了构建人工智能解决方案的总成本。民主化的开放性也有助于培养必要的人才。在民主化中,数据或算法可以免费提供给其他人。ImageNet 的管理和使其公开提供定义的性能指标帮助许多研究人员建立了更快、更准确的模型。开源深度学习框架的可用性,如 Caffe、TensorFlow、PyTorch 等,极大地促进了有才华的深度学习专家数量的增长。因此, 减少了人才发展的时间 也是民主化的一个显著好处。**
所有这些方面都在增加学术和商业世界采用人工智能的速度。自然语言处理的各个方面,如从文本文档中分析和提取结构化信息、分析来自社交媒体或呼叫中心的客户情绪、使用对话界面或聊天机器人,正在成为常见的商业应用。同样,使用机器学习和深度学习来获取见解、识别或分类数据、自动化任务或增强人类决策也变得越来越普遍。
民主化的价值杠杆——如何民主化?
当前围绕民主化的大部分努力都集中在 访问 数据、算法、存储、计算、模型开发和市场。然而,我们需要超越仅仅使人工智能的访问民主化,转向民主化的许多价值驱动因素,这些因素可以确保人工智能不被滥用,还可以提高整体价值(见图 2)。
对人工智能不同组成部分的访问需要是负担得起的——在某些情况下,如开放数据倡议或通过 GitHub 共享算法——甚至是免费的。超越 实惠接入 以上每一层都需要 好用 。如果每个人都需要编写 SQL 查询来访问数据,或者理解线性代数和微分方程,以便能够使用一些算法,那么很难说我们已经使人工智能民主化。
民主化进程的下一步是能够用 控制 堆栈中的不同元素。例如,如果在一个层(比如计算平台)中提供服务的技术供应商坚持他们将在有空闲周期时运行计算,并限制您可以从他们的平台之外获取的内容,民主化就变得不那么有用了。为了让人工智能真正民主化,用户需要控制他们运行什么,何时运行,以及如何使用运行的结果。
超越控制 所有权 的概念需要解决。数据是由生成数据的组织/人员、处理数据的组织还是从中获取见解的组织/人员所有。所有权真的可以在多方之间分割吗?我们能让区块链调解或分配所有权的概念吗?这些都是在寻求民主化过程中有待解决的悬而未决的问题。
访问、使用、控制和所有权是越来越多的价值杠杆,使人工智能民主化的供应商,以及寻求从人工智能中受益的用户和企业都需要考虑。这些价值杠杆的另一面是与民主化相关的风险。最初提供免费访问以获取市场份额或获取数据,然后收费或使用数据来加强模型和货币化数据是一种成熟的商业模式。明确这一点,并为数据的 使用 提供安全保障,对于建立消费者的信任大有帮助。
其次,如果一个人提供免费使用数据,算法,模型等。,但不要对临时用户或高级用户进行有关获取数据的环境、开发模型的假设或解释模型结果的必要数学的培训,结果可能是灾难性的。在过去的几年中,已经有许多记录在案的误用模型的实例,甚至是由专家构建的模型,例如,机器学习模型中的数据偏差、恶意攻击等。如果没有关于算法和模型的使用和解释的培训,这种现象只会增加。

图 2:如何民主化?
将所有这些结合在一起——民主化框架
设计一个人工智能系统需要广泛的技术知识和对数据科学的牢固掌握。正如你希望确保一名外科医生合格、训练有素并在手术室有丰富的经验一样,人工智能系统应该由拥有扎实技术功底、了解人工智能系统关键组件并致力于负责任的人工智能的人来设计、测试和维护。
需要采取四种不同的行动(见图 3)来确保一个人从不同的价值层次——获取、使用、控制和所有权——中获得民主化的全部好处。同时避免误用、滥用、偏见和其他问题。领导者需要采取五项行动:
1。培训。在人工智能开发和实施方面缺乏足够的培训可能是灾难性的——特别是在涉及到处理人们健康或财务福祉的系统时。例如,如果不经意或未经训练的用户不理解将数据分成桶用于训练、验证和测试的重要性,他们很容易以产生不准确或意外结果的人工智能而告终。如果我们想从仅仅提供访问权限转向刺激这些工具的使用,那么培训具有适当数据科学基础的临时或高级用户对于安全使用人工智能至关重要。
****2。治理。公司领导人需要明确输入人工智能平台的数据的所有权和控制权,以及权利与所产生的洞察力之间的关系。当为特定的 AI/ML 程序收集数据,然后用于不同的应用程序时(开源数据湖可能就是这种情况),很容易看不到数据的来源、收集数据的目的、修改数据的方式以及如何(或是否)适当地保护数据。“影子人工智能”(Shadow AI),即使用数据创建的人工智能,而这些数据不是由组织内负责确保数据完整性的团队管理的,也是一个令人担忧的问题。为了最小化风险,AI/ML 模型应该使用被监控、保护和理解的数据来构建。
组织通常将数据治理作为公司合规活动的一部分,但很少有人像应有的那样密切监控 AI 系统中涉及的其他元素。控制需要到位,以确保模型的开发具有适当的成功或验证指标(准确性、公平性、可解释性的平衡),以避免开发和部署结果有偏差或不容易解释或理解的 AI 模型。
3。知识产权。如果不决定谁拥有知识产权,民主化的预期好处可能无法实现。许多公司拒绝使用云平台进行图像处理或音频处理,因为他们担心机密信息会在他们的四面墙之外被处理,而云解决方案提供商正在使用并受益于从他们的数据中产生的重要见解。随着越来越多的公司意识到民主化的全部力量来自他们的数据(以及他们竞争对手的数据),而不是来自工具和平台本身,他们可能会要求某种程度的知识产权。
****4。开源。要实现民主化,需要所有政党在不侵犯隐私、保密和竞争动态的前提下,公开他们所做的事情。如果不能完成从所有权到使用权的循环,基本上会造成一种单向流动,一些参与者——通常是资金充裕的大公司或政府——将在短期内从民主化中受益,但那些资源较少的人将被抛在后面。

图 3:民主化框架
可以肯定的是,让人工智能变得更容易获得和负担得起是有好处的。这样做扩大了企业和政府通过让实验变得更容易而实现的可能性。总的来说,开源运动刺激了竞争,使得质量和客户体验成为最终的赢家。
在一个开源越来越普遍,技术专家和早期采用者都渴望降低门槛以追求进步的世界里,让人工智能民主化的想法似乎是一个好主意。事实上,如果我们不能从彼此的人工智能项目中学习,我们就有可能创造一个单向流,让一些参与者——通常是拥有充足资金的大公司或政府——受益,而那些资源较少的人被抛在后面。正如世界经济论坛人工智能和机器学习负责人 Kay Firth-Butterfield 最近写道,人工智能的长期成功取决于“协作的敏捷性、数据的多样性和完整性以及风险评估的准确性。”
但是,允许拖放或新手创建人工智能模型的技术,特别是在极端情况下,对问题的严重性是不公平的。当训练有素的数据科学家在创造道德和负责任的人工智能时会遇到困难,将鲁棒性的负担放在未经训练的人身上是不公平的,也有潜在的危险。通过承认真正民主化可能带来的负面影响,工业界可以探索确保任何可能的风险都不会被打开的标准和准则。通过使人工智能透明并建立治理,可以将其从“黑箱”中移除,并产生信任。因为如果人们不信任 AI,它就不可能真正进步。
通过承认 AI 民主化可能带来的负面影响,行业可以探索确保创新与安全实施齐头并进所需的标准和指南。通过使人工智能透明并建立治理,它可以从其“黑箱”中取出,并可以产生信任。
像 Zynga、脸书和易贝一样将数据民主化

数据民主化的三大支柱&自助服务分析。Zynga 的数据法,易贝的廉价易得,脸书的数据基础设施。(所有图片由作者提供)
多年来,Zynga、脸书和易贝一直在民主化他们的数据,让他们公司的每个人都可以访问和轻松使用这些数据。数据民主化是自助服务分析的基础,所以让我们看看您如何也能做到这一点。
这三家公司对他们的流程都非常开放,所以我们可以看到,尽管他们选择了三种不同的技术架构,但他们都遵循相同的流程来实现基于三大支柱的自助服务分析的数据民主化。
这三大支柱分别是“数据法”、“数据基础设施”和“廉价数据访问”。
在本文的最后,您将有一个三大支柱的蓝图,以及三个清单来指导您的数据民主化工作。
但是在我们深入所有的技术术语之前,让我们回到 150 年前,回到巴黎…
关于污水的寓言
1870 年一个温暖阳光的日子,尤金·贝尔格兰德沿着巴黎的塞纳河散步。阳光明媚的日子是可爱的,但不是在 1870 年的巴黎。1870 年,塞纳河是 180 万巴黎人的“厕所”。它一定很难闻。但更糟糕的是,霍乱和伤寒刚刚开始席卷整个城市。
贝尔格兰德心想一定有更好的办法。
因此,他和他同时代的人,奥斯曼将军以及所有其他聪明的法国人决定着手解决污水问题。
首先,他们通过了一项法律;法律规定它不再被允许倒入塞纳河,因为这是霍乱传播的主要原因之一,嗯,还有气味。
然而,人们开始在街上倒空家中的厕所,这让事情变得更糟。
贝尔格兰德和其他人意识到他们不能强迫人们保持卫生。他们需要给他们提供一个合适的方法。所以,他们建立了一个基础设施。而且是巨大的。贝尔格兰德在巴黎修建了 600 公里的下水道,有效地给每个人提供了放置一次性用品的地方。
但即使这样还不够,变化只是慢慢来的,人们仍然有“简单的出路”,仍然只有富人有连接到这个庞大污水系统的厕所。他们意识到,他们的最后一步将是使这种 像清空街道上的 一样容易和便宜。所以他们降低了下水道和厕所的价格,并开始教育人们。
因此,到 1914 年,68%的家庭有了下水道,从接近 0%上升到现在。人们不再死于霍乱和伤寒,巴黎繁荣了。
快进 150 年…贝尔格兰德和其他人发现的三大支柱是:
- 法律,或者用现代术语来说激励人们做出正确的选择并就此教育他们。
- 基础设施,给了他们所有的可能性。
- 的轻松,使访问尽可能的容易和便宜。
让我们看看今天的科技公司如何构建这三大支柱来支持他们的数据民主化和自助式分析工作。
Zynga 和数据法
Zynga 成立于 2007 年,是 FarmVille 和许多其他非常成功的手机游戏背后的公司;2018 年,他们的收入接近 10 亿美元,净收入 1500 万美元,员工接近 2000 人。
在他们 12 年的公司历史中,他们引入了一种数据驱动的崇拜,将数据作为 Zynga 每一项决策的核心。
Zynga 致力于为每一款游戏分析和设计实验。跟踪点必须是他们构建的每个新应用程序的一部分。Zynga 甚至开发了一个名为 ZTrack 的系统,能够追踪用户如何与游戏互动。
通过这些工具,Zynga 能够改变整个游戏的方向,就像他们对 FarmVille 所做的一样。
那么在 Zynga,人们实际上是如何访问这些数据来做出决策的呢?
Zyngas 架构特点两个重要决策:
- 它们为特定的 SQL 访问提供专用的“服务”。他们只是简单地复制了公司中任何人都可以访问的所有数据,提供了一套不同的数据保证,没有运营数据那么严格。
- 它们至少提供两种类型的访问,面向所有人的专用 SQL 访问,以及计划报告和商业智能工具。
示意性地,访问看起来像下面的图片。

终端用户有两种途径来访问数据。一条路径是通过某个组件,即某个报告功能,然后访问其中一个数据库。第二条路径是对另一个数据库的特定直接 SQL 访问。
Zynga 和“数据法则”的浓缩:
- 基于数据的决策被灌输到公司的价值观中。
- 每一个产品决策都具有 a 假设,A/B 测试以及测量它的可能方式。
- 不通过实施跟踪来了解如何进一步开发该产品,就不会开发出任何产品。
让我们转向一家大得多的公司,看看他们有什么不同。
脸书和数据基础设施
当脸书选择如何建立他们的数据仓库时,他们决定走稍微不同的方向。Zynga 的数据是海量的,所以脸书选择建立一个巨大的 Hadoop 集群,让公司的每个人都能访问这个 T21。
意识到这种规模的访问是一个问题,不是简单地提供访问并说“你必须使用数据就能解决的。facebook 做了 Belgrand 做的事情,他们开始建立基础设施。
今天,脸书有一个完整的部门,其中充满了数据基础架构团队。数据工程师在技术团队中工作,支持产品决策,整个部门帮助公司做出更好的决策。
但是回到 2007-2009 年,facebook 之前存储数据的方法碰壁了。所以他们决定转向 Hadoop。在此之前,数据是一个 SQL 查询,但现在它要复杂得多。
非技术用户无法访问这些数据,所以脸书决定采取行动。
脸书开发了 Hive,给用户一个类似 SQL 的界面,即使非技术用户也可以使用。现在,通过这个基础设施,就像下水道系统一样,每个人都可以轻松地访问所有的数据。
如果你比较访问架构,它与 Zynga 略有不同,但它在 Facebooks 规模上提供了类似的好处。它可能看起来像这样。

与第一种模式不同,第二种模式有一个主要界面,可以将非技术性的最终用户问题转化为技术性问题,这些问题可以在公司拥有的所有数据中运行。
Facebook 和“数据基础设施”的浓缩:
- 访问数据应该像问一个问题一样简单。这就是“SQL”所提供的。
- 非技术人员应该能够访问大部分或全部数据。脸书的基础设施能够访问所有的 Pb 级数据,不仅仅是一小部分,而是全部。就像巴黎 600 公里的污水。
贝尔格兰德和他的朋友们最重要的一步,在几年内将污水的采用率从 1%提高到 68%,是使变得便宜和容易。我们看到的最后一家公司正是这样做的。
易贝和廉价数据访问
多年来,易贝一直致力于让每个人都能廉价、便捷地获取数据。
他们经历了一系列步骤,尽可能方便地访问数据。
易贝选择的建筑又是一个不同的建筑。易贝集中收集数据,然后为每个团队提供一个“桶或立方体”和他们的数据。这种方法从一个"Datensparsamkeitsperspektive开始就很棒,并且使得把" 数据转换靠近最终用户 "成为可能。

与前两种模式不同,第三种模式认识到不同最终用户群之间的数据需求可能会有很大差异。因此,终端用户拥有自己的小数据“集市”,他们可以直接访问,也可以通过他们选择在组中使用的任何工具访问。
为了让人们使用数据,他们需要知道数据在哪里。易贝只是从一个维基开始,解释什么是与元数据仓库相结合。
然后他们添加了图片,展示了数据是如何连接的,标记了数据,并把整个系统变成了一个产品叫做“数据中枢”。一个查找数据的中心位置。
但是他们并没有就此止步,2015 年他们的最先进的数据民主化平台功能:
- 作为元数据目录,
- 讨论板,以及拥有数据并了解数据的团队的链接,
- 与元数据存储库相结合的 SQL 助手,
使其成为检查数据的无缝体验。易贝提供全程幻灯片。
易贝的廉价和简单的数据访问方法压缩:
事实证明,facebook 所遵循的可以被理解为在数据网格方法中使用的属性的“ 数据列表 ”。适用于易贝的标准是:
- 使数据对每个人都是可发现的;易贝通过提供像“数据中心”或 Alation 这样的中心工具做到了这一点。
- 使数据可寻址;易贝通过在其元数据存储库中的一个中心位置提供连接信息来做到这一点。
- 使数据可信;易贝通过提供知情人士的姓名、数据的 SLA 等等来做到这一点。
- 使其自描述;易贝通过提供适当的元数据做到了这一点。
- 使互操作;易贝通过提供 SQL 帮助做到了这一点,并把一切都建立在 SQL 之上。
- 确保安全。
很好,我们现在有三个支柱,每个支柱都有一个清单。现在怎么办?
你从哪里开始?
你从瓶颈所在开始。
这些柱子很好地反映了正在发生的事情。如果你还没有屋顶,你可以从任何地方开始。你可以提供三块短木头来支撑一个轻型铁皮屋顶。
但是如果你想支撑一个完整的石头屋顶,你就必须在所有的三根柱子上下功夫,一次又一次地使它们变得坚固。
在你让公司做出基于数据的快速决策的过程中,这三个支柱都可能成为瓶颈。
如果没有人知道如何做出基于数据的决策和编写 SQL,你就需要研究“数据法则”,对人们进行这方面的教育,在产品中建立跟踪等等。这就是为什么 Zynga 非常重视它,也是为什么 Spotify 有整个团队为特定产品做基于数据库的决策。
如果人们不能以一致的方式访问数据,就没有人能获得数据来做出基于数据的决策。Zynga 似乎还不是这种情况,因为它使用了多个数据库,所以这不是它们的瓶颈。但对于像网飞这样的公司来说,情况似乎就是如此。网飞开发了一个名为 Metacat 的工具来解决这个问题,并提供一个统一的基础设施。
最后,如果访问数据不够容易,人们将无法及时获得数据,从而无法做出基于数据的快速决策。
因此,你必须关注这三个方面,从一个瓶颈到另一个瓶颈,以便在你的公司做出比以往更好更快的决策。
我必须给他们直接的临时 SQL 访问权限吗?
不要!尽管 Zynga、脸书和易贝显然是这样做的,但这实际上是你的具体组织如何运作的问题。通过提供一个中央数据湖,提供一个中央商业智能工具,并教育人们如何使用它,你的瓶颈可能会得到解决。
但是上面的三个支柱依然存在,每个支柱的详细计划都符合你所能想到的最集中的架构,就像它符合你所能想象的最分散的架构一样。
更多资源
下面链接的所有资源都为本文提供了信息。
- 看看巴黎下水道系统的真实故事,也许还有可爱的巴黎博物馆。我喜欢它!
- 易贝现在使用 alation 作为元数据和 SQL 完成工具,他们与易贝就数据治理和自助服务分析进行了会谈。
- 此幻灯片分享提供了易贝案例的大部分背景,以及这篇关于易贝数据治理的文章。
- 最后,DJ Patil 的这本短文提供了这三个案例的背景。
使数据科学民主化
数据科学/观点
学习一些基本技能可能会让你成为一名数据科学家!

伊尔哈姆·拉赫曼萨在 Unsplash 上的照片
偶尔,我会看到一篇文章,谴责在线数据科学课程和训练营是获得数据科学工作的途径。大多数文章的目的不是打击,而是提醒我们先照照镜子,意识到我们面临的是什么。然而,一些批评者宣称,这些在线课程和训练营的激增导致了该行业的退化。
对于后者,我坚决不同意。
弥合技能差距
自从《哈佛商业评论》将数据科学家称为21 世纪最性感的工作以来,数据科学就抓住了大众的想象力。七年多后,数据科学仍然是当今最受欢迎的就业市场之一。事实上,由于供需动态,“预计到 2024 年,仅美国就将面临约 25 万数据科学家的缺口。”
因此,资本主义和企业家精神响应了这一号召,像 Codeup 这样的公司发誓要“帮助弥合公司和希望进入这一领域的人之间的差距。”
此外,像 PyCaret 这样的 AutoML 库“通过为业务分析师、领域专家、公民数据科学家和经验丰富的数据科学家提供免费、开源和低代码的机器学习解决方案,使机器学习和高级分析的使用民主化”。
在线课程、训练营和 AutoML 库的可用性让许多数据科学家皱起了眉头。他们担心新兵训练营的校友和自学的候选人会以某种方式降低数据科学家的整体素质,给这个领域抹黑。此外,他们担心像 AutoML 这样的工具会让任何人成为数据科学家。
我的意思是,上帝禁止任何人认为他们也可以成为数据科学家!对吗?
不对。
街头智能数据科学家
像我一样,新兵训练营的校友和自学者都有一个优势:我们的新秀智慧。引用《新秀智慧》一书的作者利兹·怀斯曼的话:
在一个快速变化的世界里,经验可能是一种诅咒。新的,天真的,甚至是无知的可能是一种资产。——利兹·怀斯曼
菜鸟无牵无挂。我们像狩猎采集者一样警觉而不断地寻找,像火行者一样谨慎而敏捷,像 frontiersmen⁴.一样饥饿而无情换句话说,我们很聪明。
许多人陷入了“你必须学会这个”和“你必须学会那个”的困境,以至于他们忘记了强调这样一个事实,即数据科学如此庞大,你不可能知道任何事情的一切。这没关系。
我们学得快,适应得也快。
归根结底,我们为组织带来的价值才是最重要的。毕竟,是他们在为我们买单。我们不会因为记住公式或者知道如何从头开始编写算法而得到报酬。
我们解决问题是有报酬的。
这是街头智能数据科学家擅长的地方。我们不会遭受分析瘫痪或被理论所困扰,至少在上班的时候不会。我们关注的中心是基于对问题的务实解决方案,而不是学术辩论。
这并不是说我们对最新的研究不感兴趣。其实恰恰相反。我们是机器学习和人工智能最新发展的贪婪消费者。我们对自然语言处理的最新发展垂涎三尺。我们总是在寻找最新的工具,让我们的工作变得更简单,不那么无聊。
和 AutoML
那么如果我们必须使用 AutoML 呢?如果它让我们进入一个自动管道,分析师可以在没有数据科学家人工干预的情况下获得机器学习的结果,那就更好了。我们没有被自动化所威胁,我们被它所振奋!
不要让完美成为进步的敌人。——温斯顿·丘吉尔
通过建立自动管道,必然会有一些权衡。但是以这种方式构建它将解放我们的脑细胞,让我们有更多的时间专注于解决其他更高层次的问题,并产生更有影响力的解决方案。
我们不关心工作保障,因为我们知道它不存在。我们所知道的是,我们给企业带来的价值越多,从长远来看我们就越好。
也许他们是对的?
经过这一切,我会让步一点。为了便于讨论,也许他们是对的。也许在线课程、训练营和低代码机器学习库真的会产生低水平的数据科学家。
也许很大。
但是,我认为,这并不意味着我们没有价值。数据科学技能取决于一个范围,公司在数据方面的成熟度也是如此。当你的组织几乎没有可识别的机器学习基础设施时,为什么要雇用一名六位数的员工?
也许吧。
独角兽
也许,要被贴上数据科学家的标签,首先必须是独角兽。独角兽数据科学家是在数据科学的所有方面都表现出色的数据科学家。

hckum/CC BY-SA(https://creativecommons.org/licenses/by-sa/4.0)
数据科学长期以来被描述为计算机科学、应用统计学和商业或领域知识之间的交叉。对此,他们问,一个人怎么可能在短短几个月内积累所有这些知识?对此,我们也提出同样的问题,一个大学毕业生如何才能?
我相信独角兽确实存在,但它们也必须从某个地方开始。
那么我们为什么不能呢?
结论
一系列在线课程和工具承诺将数据科学民主化,这是一件好事。
感谢您的阅读。如果你想了解更多关于我从懒鬼到数据科学家的旅程,请查看下面的文章:
我的无学位数据科学之旅。
towardsdatascience.com](/from-slacker-to-data-scientist-b4f34aa10ea1)
如果你正在考虑改变方向,进入数据科学领域,现在就开始考虑重塑品牌:
给我们其他人的固执己见的建议。热爱数学,选修。
towardsdatascience.com](/the-slackers-guide-to-rebranding-yourself-as-a-data-scientist-b34424d45540)
敬请期待!
[1]哈佛商业评论。(2020 年 6 月 3 日)。在您的组织中实现数据科学的民主化。https://HBR . org/sponsored/2019/04/democrating-data-science-in-your-organization
[2]圣安东尼奥快报-新闻。(2020 年 6 月 3 日)。软件开发训练营 Codeup 推出新的数据科学计划。https://www . mysanantonio . com/business/technology/article/Software-development-boot camp-code up-launching-13271597 . PHP
[3]走向数据科学。(2020 年 6 月 4 日)。Power BI 中使用 PyCaret 的机器学习。https://towardsdatascience . com/machine-learning-in-power-bi-using-py caret-34307 f 09394 a
[4]怀斯曼集团。(2020 年 6 月 4 日)。为什么在新的工作游戏中,学习胜过了解。https://thewisemangroup.com/books/rookie-smarts/
将人工智能大众化
“AI 黑匣子”是给所有人的。

照片由 Unsplash 上的 h heyerlein 拍摄
“领导者的真正标志是愿意坚持大胆的行动路线——非传统的商业战略、独特的产品开发路线图、有争议的营销活动——即使世界上其他人都想知道为什么你不与现状保持一致。换句话说,真正的领导者乐于曲折前进,而其他人则乐于曲折前进。他们明白,在一个高度竞争和不间断破坏的时代,脱颖而出的唯一方式就是代表一些特别的东西。”——比尔·泰勒。
谷歌、脸书、亚马逊等科技巨头在人工智能领域的成功经验。证明了投资先进技术新时代的效率。他们的重要结果将人们分为两类:一类是愿意掌握人工智能艺术的支持者,另一类是声称这只不过是炒作的怀疑者。有一件事是肯定的,从那以后,工业一直在发展。
人工智能研究的发展。

- 1998 年至 2018 年间,经过同行评审的人工智能论文数量增长了 300%以上,占同行评审期刊出版物的 3%,占已发表会议论文的 9%。
- 中国现在每年发表的人工智能期刊和会议论文与欧洲一样多,已经在 2006 年超过了美国。美国出版物的领域加权引用影响仍比中国高出约 50%。
- 新加坡、瑞士、澳大利亚、以色列、荷兰和卢森堡人均在 arXiv 上发表的深度学习论文数量相对较高。
- 超过 32%的世界人工智能期刊引用来自东亚。超过 40%的世界人工智能会议论文被北美引用。
- 北美占 2014 年至 2018 年全球人工智能专利引用活动的 60%以上。
- 许多西欧国家,特别是荷兰和丹麦,以及阿根廷、加拿大和伊朗,在人工智能研究中显示了相对较高的女性比例。

开源软件。
在过去的十年里,许多机器学习和人工智能库都是开源的,可供广大公众使用,这使得开发人员更容易开发智能产品和平台。这种开源代码受到了社区的广泛关注和欢迎。
衡量各种人工智能编程框架受欢迎程度的标准之一是 Github stars。它们表明一个人在 GitHub 上表达了对特定代码或项目的兴趣,类似于 Twitter 和脸书等社交媒体服务上的“赞”可以表明某个帖子的受欢迎程度。
下图显示了各种 AI 和 ML 软件包在 GitHub 上被打上星号的次数。

人工智能库累积 Github 星级-来源:Github,2019 年

人工智能库(不包括 TensorFlow)累积 Github 星级—来源:Github,2019
每个人的人工智能!
最近对人工智能的兴趣激增,对该领域产生了重大影响。除了开源人工智能系统的可用性,其他因素也使人工智能越来越容易为每个人所用:
教育
教育已经延伸到大学之外。Moocs 越来越多地为全球劳动力提供不同人工智能技能的课程。人工智能和相关学科的入学人数继续成倍增长,无论是在线课程还是美国和国际上的传统大学。


人工智能在大学和 Moocs 中的应用。
云的力量
- 大数据平台提供了捕获和存储大型数据集的能力。
- 计算时间显著减少。在一年半的时间里,在云基础设施上训练大型图像分类系统所需的时间从 2017 年 10 月的约 3 小时下降到 2019 年 7 月的约 88 秒。
- 培训模特的成本也有类似的下降。
人工智能的民主化正在增加与之互动的人数。这种扩张允许人工智能应用扩展到新的领域,并释放人工智能专家的时间来从事前沿开发。
人工智能不再被视为在工业界和学术界输出神奇结果的黑匣子。越来越多的公众可以使用不同的技术。
** 参考文献 : 上述统计数据来自斯坦福海 2019 年度报告。
自动化大众化
让每个人都从人工智能热潮中受益可能比一些人预期的更具挑战性。

我们如何平衡人工智能的超能力——在少数人手中——对其他人的眼睛和生活的影响?通过各种文章、播客和对话,我对基于自动化的产品如何进一步分化我们的社会产生了一些担忧。我写了三个主题,我们需要解决,以推动智能系统走向公平。
- 机器的情感容量及其对用户的影响。
- 如何让数据驱动的系统没有偏见?
- 如何缓解科技公司权力聚集后的财富聚集?
为什么我说这很难?看到这个国家对冠状病毒的反应平平,表明我们几乎无法应对一个紧迫的问题。我会把对自动化民主化的需求循环为仅次于气候变化的社会不稳定风险。这些问题是相似的,因为它们慢慢地悄悄逼近我们,逐渐改变我们的生活方式,而我们却没有意识到未来就在眼前。
自动化不是一个零和游戏——也就是说,每个人都可以从它的实施中获得胜利和收益——但肯定会对服务不足的群体和社会产生一些巨大的成本。我希望尽自己的一份力量,建立一个能帮助所有人的系统,而不是一个以增加他人成本的方式过度帮助少数人的系统。
这篇文章启发了我,使我的博客和我的方向正式化,你可以在这里找到更多https://robotic.substack.com/。

人工智能中的情感能力
现代生活已经给我们的人性带来了很大的压力,因为我们将如此多的互动转移到了屏幕后面,智能繁荣也将如此(对于成年人来说,屏幕后面的时间长达 34 年)。数据驱动方法的革命还很年轻。我担心当我们再也看不到咖啡店里的笑脸时会发生什么。我并不是说这是人们渴望和需要的互动,但这是事实。这是一种联系。 这些微小而众多的联系累积起来,关系到个人的长期心理健康 。我对我的精神健康斗争非常开放,这种斗争是由通信的技术漏斗加强的。它影响到每个人,我看不出有什么方法可以让它不那么成问题。
自动咖啡机能让人类感觉自己是整个系统的一部分吗?我们都有变焦疲劳 ( 来源,来源)在一个月的在线工作中,如果生活重新开始,我们只能看到屏幕,那会怎么样——我不认为这将是一个巨大的胜利。消除人与人之间的互动对客户来说也是一种负担;这不仅仅是一种节省成本的技术。
情感人工智能
一家公司开始提高患有某些疾病的人的情绪智商,这些疾病使他们很难融入正常社会,情感人工智能 ( 链接)在这一领域拥有许多关键。创始人希望为那些未被充分代表的人和那些获益最多的人服务。
我强烈推荐下面这一集人工智能播客,它定义并深入探讨了这些问题。
[## 罗莎琳德·皮卡德:情感计算、情感、隐私和健康|麻省理工学院|人工智能……
罗莎琳德·皮卡德是麻省理工学院的教授,麻省理工学院媒体实验室情感计算研究组的主任,以及…
lexfridman.com](https://lexfridman.com/rosalind-picard/)
科技公司将情感货币化
我们希望机器也能跟踪我们的情绪吗?我看到在接下来的几年里,某些社交应用程序想要追踪眼球运动来衡量广告的参与度(来源一或二)。如果先进的面部识别硬件作为我们手机的生物护照,成为优化广告技术的情感测量设备,会怎么样?老实说,我不知道也没有听到足够多的人谈论这种担忧(来源关于情感如何进入广告技术)。
随着科技公司能够随时改变服务条款,我认为这是一个时间问题,而不是是否的问题。消费者需要对被跟踪的内容有发言权,否则功能蔓延会将情感添加到持续跟踪的内容列表中(位置、浏览、购买等)。
无偏差数据
数据驱动方法(也称为基于学习的方法)接受给它们的信号,并优化一些输出。
科技领域的当前偏见
谁在移动设备上花费最多?富裕人群(主要在苹果设备上)。来源。
面部识别工具上谁的成功率最高?白种人。来源。
这只是我们日常生活中已经存在的有偏见的数据的两个例子。我想说它们并不具有超级影响力,但当自动化系统影响我们生活的更多领域时,它会发人深省。
科技领域的未来偏见
如果人工智能系统被用来招聘工作,如果某些人口统计数据被排除在训练集之外,因此他们永远不会被选中,那会怎么样?来源。
在医疗系统中,已经存在跨人口统计学的治疗有效性的系统性差异,当决策被输入计算机时会发生什么?来源。
在这两种情况下,计算机会复制给它们的数据。例如,当神经网络在拟合数据时,其精度与训练数据的密度成比例。关于如何解决这个问题的工作很少,只有很多关于这些问题将如何影响我们的白皮书。
我认为我们需要在数据处理和汇总方面做更多的工作。我刚才谈到的数据是推动公司价值的,但我们也需要一些数据的透明度。这是麻省理工学院斯隆管理学院关于数据偏差问题的一个很好的总结。
谁驾驶这个?
我也很高兴看到伯克利 EECS 分校聘请了一个对这些问题感兴趣的新教师团队。欢迎光临!我认为教职员工有一个表达问题的大平台,但运营这个平台的公司能更早地看到潜在的问题。这是一件很难监管的事情,所以我认为工程师们应该意识到这个问题。这就是为什么我认为最优秀的计算机科学家都有某种程度上多样化的背景——理解更广泛问题的能力。
参见脸书、谷歌、亚马逊和微软对公平的推动。这些只是公共方法。
金融公平
2020 年上半年将是技术领域的一次重大聚合事件。枯竭的种子资金,失败的走向市场战略,以及经济封锁的随机打击。大的变得更大(FAANG 或其他更受欢迎的五大科技公司的缩写)。我在自动化领域工作,并期望大量资金流向那里,但这一切都隐藏在隐形模式初创公司和根深蒂固的工程公司的面纱后面。
每个人都在谈论即将到来的自动化,但为什么它如此难找(即使对于该领域的专家来说)?
我的目标是研究什么样的自动化会以其前所未有的影响规模让人们措手不及(例如自动驾驶汽车),以及什么会成为一个具有良好公共关系的玩具应用程序?我想继续写自动化的民主化。我想打造工具,了解趋势。
(软银在 Q1 的财报电话会议上对科技独角兽的陨落进行了滑稽的想象;来源。)
基于人工智能的万亿 GPD 增长
我们能不能让更多的美国科技巨头立足于美国。我不会说任何关于改变税收结构的话,但我们需要找到一种方法,随着 GDP 的飙升,它不仅会创造更多的亿万富翁。每个数字用户的边际增值是惊人的。如果你有好的资源,可以让财务收益正常化并保留资本主义的好处,请联系我们或发表评论。
人工智能(AI)工具和技术在商业和全球经济中的作用是一个热门话题。这个…
www.mckinsey.com](https://www.mckinsey.com/featured-insights/artificial-intelligence/notes-from-the-ai-frontier-modeling-the-impact-of-ai-on-the-world-economy) 
这个国家的一些地区不用走很远就可以到达令人惊叹的地方。
科技公司没有动力通过解决这些长期风险来限制其增长。我们需要有效的政府来调节技术的长期轨迹——因为他们是唯一可以为长远的未来安全承担财务风险的人。
一个关于机器人和人工智能的博客,让它们对每个人都有益,以及即将到来的自动化浪潮…
robotic.substack.com](https://robotic.substack.com/)
民主化图像分类
用 Kubernetes 构建基于网络的迁移学习门户
创建定制的图像分类模型需要详细了解 TensorFlow 或其他类似的深度学习框架。它还需要大量的 CPU。虽然存在更高级的工具,如苹果的桌面应用程序, CreateML ,但它们要求你在本地机器上运行软件,这可能会很慢且效率低下。
我们的项目旨在使机器学习民主化,并使任何软件工程师都可以建立图像分类模型,不管他们的 ML 知识如何。
站在巨人的肩膀上
我们在几个现有资源的基础上开发了一个 web 服务,它可以无缝地接收图像并输出定制的图像分类模型。
- 基本模型:使用的基本模型来自 Google 开发的 MobileNet v2 模型。这是在 ImageNet 数据集上预先训练的,这是一个由 1.4 M 图像和 1000 个类组成的大型数据集
- 迁移学习:我们利用 MobileNet 基础模型为用户训练定制的图像分类模型
- Docker:我们将迁移学习模型容器化,这样它就可以部署在 GCP 的实例中
- Kubernetes:利用 Kubernetes,我们可以在创建每个分类模型时自动扩展和管理工作
- GitHub:我们服务前端和后端的所有代码都在 GitHub repo 中维护
产品组件和基础设施
我们的产品包含三个不同的组件:用于管理用户上传的部署和服务,用于管理模型训练的作业定义,以及用于在训练期间存储数据的持久性存储。组件已连接,如下所示。

在谷歌云上部署到 Kubernetes
对于这个项目,我们需要动态的计算能力来应对需求高峰。Kubernetes 自动管理可伸缩的容器化应用程序,是一个完美的选择。谷歌云让快速建立新的 Kubernetes 集群变得简单。

接下来,我们需要设置持久存储,以便上传图像,然后供培训作业使用。Kubernetes Pods 可以使用永久卷共享文件。永久卷有三种访问模式 : ReadWriteOnce、ReadOnlyMany 和 ReadWriteMany(这些名称表明了每种卷类型的使用方式)。对于这个项目,我们需要前端能够将文件写入存储;然后,相应的培训工作需要能够读取这些文件。因此,我们需要一个支持读写的卷。
我们选择使用 Filestore ,这是一个托管的谷歌服务,其工作方式类似于 NAS 服务器。Filestore 至少需要 1Tb 的磁盘空间,并且有些昂贵,因此对于长期项目来说,它可能不是一个理想的选择,除非您计划存储大量数据。但是对于一个短期项目(并且有学分),它很容易建立并且对我们的用例有意义。为了建立一个文件存储实例,创建了一个新实例,并跟踪文件共享名和 IP 地址。

接下来,我们使用该文件存储信息创建了一个持久卷。
最后,我们创建了一个持久的卷声明,可以由前端和各种作业共享。
版本管理和自动部署
这个项目发生在新冠肺炎,所以我们不得不远程合作,因为庇护所的订单。因此,使用源代码控制和协作工具甚至更加重要。我们将代码存储在 GitHub 中,并使用 GitHub 动作管理我们所有的部署。设置 autodeploy 需要首先在 Google Cloud 中创建一个服务帐户。

服务帐户角色需要设置为编辑器,这样 GitHub 才能向 Google Cloud 发送命令。在最后阶段,我们为服务帐户生成并下载了一个密钥。

接下来,我们将构建并部署到 GKE 工作流添加到 GitHub 项目中。默认模板使用 Github secrets 作为 GKE_EMAIL、GKE_KEY 和 GKE_PROJECT 环境变量。GKE 电子邮件和 GKE 项目分别对应于服务帐户电子邮件地址和项目 ID。GitHub 在这里提供指令生成 GKE _ 密钥(使用你上面下载的服务账号密钥 JSON 文件)。
最后,我们对动作文件做了一些修改。首先,为了避免为每个部署削减一个新的发布,我们在每次有新的提交到主分支时触发工作流。
其次,我们构建了两个 Docker 容器,而不是一个——一个用于主服务,一个用于作业(下面将详细介绍)。
建立核心服务和工作岗位
设置前端
我们使用 Flask 和 Bootstrap 设置前端。前端服务被打包成一个容器,并部署在 Kubernetes 集群中。
为了帮助用户完成这个过程,我们设计了一个如下所示的 3 步表单(尽管你可以随意定制!).第一步,我们收集一个. zip 文件,其中包含用户希望模型学习的不同新类的图片。的内容。zip 文件必须匹配keras . preprocessing . images . imagedata generator . flow _ from _ directory使用的结构。然后,我们要求用户输入他们希望接收训练模型的电子邮件。最后,我们向用户提供一个摘要和通知,以检查所有细节是否正确。

与作业共享图像数据
上传. zip 文件后,我们使用 Kubernetes Python 包创建一个作业。我们使用 UUID 生成器包给每个作业一个唯一的 UUID。作为环境变量的 zip 文件路径。请注意,创建作业时会附加永久卷声明。
前端需要特殊权限才能创建作业。对于这个项目,我们给默认角色 Admin 访问权限。在生产环境中,前端的访问应该仅限于必要的权限。
(重新)教授模型
为了创建定制的图像分类模型,我们在预训练的神经网络上使用了迁移学习技术。文章Transfer Learning using Mobilenet and Keras非常有用,并被用作这项工作的框架。
在图像分类的背景下,迁移学习的理论是,已经在大量图像上训练过的预训练模型可以有效地充当大多数图像的通用模型。我们可以利用神经网络的大多数层,只在新图像上重新训练最后几层。这使我们能够减少开发定制图像分类模型所需的时间和计算资源。它还减少了我们添加新类所需的新图像的数量。
在这个项目中,我们使用 Google 开发的 MobileNet v2 的基本模型。该网络在 ImageNet 数据集(由 140 万幅图像和 1000 个类组成)上进行预训练。我们冻结了第一批预训练层的大部分,只重新训练最后几个密集层。然后,我们打开分类图像的 zip 文件,重新训练模型。模型被保存为一个. h5 文件,并保存到一个 dropbox 文件中,然后通过电子邮件发送回给用户。
集装化的转移学习
将我们的机器学习模型产品化的第一步是将其放入 Docker 容器中,以便我们可以将其部署为微服务。利用 Docker,我们可以维护统一的环境、库需求,并使用 Kubernetes 在云中扩展模型。
Dockerfile 本质上是一个命令文档,存储在启动容器映像的文本文件中。在我们的 token 文件中,我们安装了 python 和 requirements.txt 中定义的所有包。我们还实例化了几个可以传递到 main.py 文件中的环境变量:图像的 zip 文件位置、用户电子邮件以及 dropbox 密钥和令牌。
创建 docker 文件后,我们构建映像并进行测试,以确保输入和输出在本地工作。最后,我们将图像推送到 Google 云平台,在那里它可以被我们的 Kubernetes 集群部署。
共享模型并通知用户
由于 Google Drive 存储昂贵,我们决定使用 Dropbox API 来临时存储重新训练的模型。训练完成后,模型被上传到 Dropbox,并生成一个可共享的链接。
该链接随后被传递给 SendGrid API,以生成一封通知电子邮件供用户检索。下面可以看到这封漂亮邮件的样本!

后续步骤
我们所创造的服务只是这个产品未来发展的一个起点。为了更好地满足那些希望利用分类模型的人的需求,可以结合以下特征:
进一步产品化
- 改进 web 应用程序,为用户提供更多指导
- 关于培训状态、后端如何工作等更多信息。
- 提供更多基本型号的选择(目前只有 MobileNet)
- 让用户选择超参数
合并模型蒸馏和压缩
- 模型文件相当大;输出可用于移动电话的版本可能有用
提高用户测试能力
- 提供一个界面,允许用户测试模型的准确性
承认
我们要感谢 Pavlos Protopapas 和哈佛应用计算 295 课程的其他教学人员的指导和支持。
为手机游戏出版平民化 PySpark

与朋友的话 2(来源:https://www.zynga.com)
2020 年火花峰会上的 Zynga Analytics
在过去的两年里,Zynga 的分析越来越多地使用 PySpark,这是 Spark 大数据平台的 Python 接口。我们的中央和嵌入式分析团队使用 PySpark 支持移动出版运营,包括分析和报告、实验、个性化服务和营销优化。我在 2020 年 Spark 峰会上介绍了我们如何向整个分析组织开放这个强大的平台,并讨论了我们面临的一些挑战以及我们团队开发的新应用。这篇文章提供了视频演示的文本版本,可在这里获得。我们的机器学习(ML)工程团队也在峰会上展示了强化学习的新应用。

我是 Zynga 的一名杰出的数据科学家,我的职责是探索新技术,并倡导扩大我们分析团队的技术堆栈。本次会议符合大会的主题,即实现人工智能和大数据工具的民主化。在 Zynga,我们通过向我们的完整分析团队开放 Spark 生态系统,与这一主题保持一致。我们确实面临着这种方法的成长烦恼和扩展挑战,但我们将讨论我们如何克服这些障碍,并提供一些在您的分析组织内扩展 Spark 的最佳实践。

我们正处于前所未有的时代,今年的虚拟会议反映了这一现实。Zynga 回应 COVID 疫情的方式之一是领导与世界卫生组织的一项倡议,我们与数十家游戏出版商和工作室合作,通过游戏传播关于社交距离的信息。 Play Apart Together 倡议扩大了关于如何在这些充满挑战的时期保持安全,同时通过游戏与朋友和家人保持联系的沟通。我们的使命是通过游戏连接世界,我很自豪 Zynga 在这一举措中发挥了至关重要的作用。

我们在 Zynga 的分析团队现在超过 50 人,我们已经向整个组织开放了 PySpark 平台。Zynga analytics 的任何成员现在都可以使用该平台将分析和 ML 模型扩展到大规模数据集。虽然开放这一强大的工具有助于加快我们分析组织的产出,但随着越来越多的团队成员采用该平台处理日常任务,我们确实面临着一些挑战和成长的烦恼,我们将重点介绍我们克服这些问题的几种方法。我们应对这些挑战的一个关键方法是将一套广泛的培训材料放在一起,并制定政策来保持集群的可维护性和成本可控性。虽然开发 PySpark 并推动该平台的采用需要一些努力,但我们发现我们的团队以新颖的方式使用 Spark,为我们的游戏团队和直播服务带来了有用的分析和工具。

Zynga 拥有多样化的游戏组合,并有嵌入式分析师和数据科学家支持开发这些游戏的工作室。我们把每年收入超过 1 亿美元的游戏称为“永远的专营权”,我们预计这些游戏将持续几年繁荣发展。在录制这个环节的时候,我们有 6 个游戏符合这个标准。从那以后,我们收购了 Peak Games,将玩具爆炸和卡通爆炸加入到我们的投资组合中,使这个数字达到了 8。
作为一个分析组织,我们面临的挑战之一是,我们的游戏组合会生成非常不同的数据集。例如,我们有赌场游戏、社交吃角子老丨虎丨机游戏、赛车游戏和基于比赛 3 的游戏,它们具有不同的事件分类。虽然数据集在不同的游戏中差异很大,但我们在过去几年的目标之一是标准化基础设施和工具,我们的嵌入式团队使用这些基础设施和工具来处理这些大规模数据集,并为我们的工作室找到见解。我们发现 Spark 非常适合集中式平台,因为它可以与我们所有的数据源很好地集成,并且可以扩展到处理巨大的工作负载。

就 Zynga analytics 的结构而言,我们是我们的分析工程、嵌入式分析和中央分析团队的组合。虽然这个团队是不同学科的混合体,但我们有一个共同的目标,那就是帮助我们的游戏团队找到洞察力和个性化的游戏体验。
嵌入式分析师和数据科学家与他们支持的工作室位于同一地点,并与产品经理和工作室领导密切合作,以支持游戏发布和直播服务。这些团队负责监控游戏的性能,进行个性化实验,并探索如何改善我们游戏中的用户体验。我所在的中央分析部门专注于构建工具,这些工具可以扩展到我们所有的分析团队,并支持发布运营,如用户获取和企业发展。这两个团队都利用了我们的数据平台,该平台提供了跟踪事件数据、处理不同数据集以及构建支持我们实时服务的数据产品的能力。我们的分析工程团队负责构建和维护这个平台,它是我们分析能力的支柱。

虽然我们的分析团队执行各种不同的职能,但我们在不同的团队中看到了几个共同的主题,即作为游戏发行商支持工作室。第一个是 Zynga 分析的核心功能之一,即利用我们的数据平台来衡量游戏的性能,并为改善我们的玩家体验提供见解。我们看到的第二个常见主题是在我们的游戏中进行实验,并与产品经理密切合作,以确定实验的结果以及如何基于这些发现。第三个主题是构建数据产品,推动游戏中的个性化体验。例如,我们建立倾向模型,预测哪些用户可能会在游戏中失败,并可以根据这些信号定制体验。最后的主题是营销优化,这是产品营销和用户获取的交叉点。虽然这通常是中央分析团队的职能,但在构建支持这一职能的 ML 模型时,利用我们的嵌入式分析师和数据科学家的领域知识是非常有用的。

自 Zynga 于 2007 年成立以来,我们的数据平台已经经历了几次迭代,但在过去的几年里,随着我们对分析团队使用的工具进行标准化,我们已经看到了巨大而有益的变化。十多年来,我们一直使用 Vertica 作为数据存储,该数据库为我们的核心分析功能提供了动力,如报告、探索性数据分析和游戏中的 A/B 测试。虽然这个数据库在过去十年中一直是我们数据平台的一部分,但我们的分析师使用的许多工具已经随着时间的推移发生了变化。我将这些不同的工具转变归类为 Zynga 的三个分析时代。
我将第一个时代称为 SQL 时代,因为分析师和数据科学家花了大部分时间直接与我们的数据库打交道。这包括构建报告、探索新用户漏斗的指标、计算实验结果以及将数据整理成可用于预测和倾向建模等任务的格式。在这个时代,分析师使用的主要工具是连接和查询我们的数据存储的 IDE。虽然一些分析师和数据科学家使用 R 编程语言来构建 ML 模型,但不同的嵌入式分析团队之间并没有标准化。
2017 年,我们组建了中央分析团队,这是我们工具标准化的转折点。我们决定将 Python 作为 Zynga 的标准分析语言,并建立一个托管的 Jupyter 笔记本环境,分析师可以在其中进行项目合作。我们称之为笔记本时代,因为我们的分析师开始花更多的时间在笔记本环境中,而不是直接与我们的数据库打交道。其中一个巨大的成果是,为笔记本电脑使用一个通用的托管环境意味着跨团队共享脚本变得更加容易,因为该环境有固定数量的特定版本的库。虽然我们的团队花了一些时间将 Python 作为我们分析团队的通用语言,但好处很快超过了培训我们团队的成本,因为团队可以更容易地协作,并且更容易对我们的整个游戏组合进行分析,而不是单个游戏。
Zynga 当前的分析时代被称为生产时代,因为我们的分析团队现在正在利用工具将 ML 模型投入生产。我们的分析师现在正在利用 PySpark 构建可扩展到数千万玩家的批量 ML 管道,我们正在使用 Flask 构建端点和 web 工具来支持游戏和发布团队,我们正在与分析工程合作,使用 AWS SageMaker 构建实时预测模型。我们的分析团队现在更多地参与构建基于这些见解为直播服务提供动力的系统,而不是寻找见解并将这些见解交给游戏团队。
过去几年发生的变化之一是,我们为分析团队提供了比以前更多的工具。虽然我们现在已经向整个团队开放了我们的 Spark 环境,但我们从有限的访问开始,并在扩展到所有 Zynga Analytics 之前展示了该平台的实用性。当我们看到我们的分析师和数据科学家可以构建端到端的 ML 模型时,我们希望让越来越多的团队能够使用这个平台。

我们希望向所有分析师开放我们的 Spark 生态系统有几个原因。其中一个核心动机是,我们希望为我们的分析师提供一条继续发展他们的技术能力和提升他们的技能集的途径。接触 Spark 并建立端到端的渠道是分析师在 Zynga 继续职业发展的方式之一。
另一个动机是,我们希望对工具进行标准化,使我们的分析师能够处理机器集群,而不是单个实例,这是我们 Jupyter 笔记本电脑生态系统中的一个限制。我们使用 Databricks 作为我们的 Spark 平台,它提供集群管理、作业调度和协作笔记本。与此动机类似,我们希望更新我们的平台,以涵盖我们的团队正在执行的更多类型的任务。例如,一些团队需要处理我们数据库中没有的大型数据集,而 Spark 有多种数据连接器,这意味着我们可以将该平台用作统一的解决方案。同样相关的是,我们希望我们的团队能够扩展到更大的问题,例如为我们的整个用户群而不是一个游戏或一群玩家创建倾向模型。
我们希望向所有分析师开放平台的最后一个原因是为了分配在平台上运行的作业的所有权。不是让我们的分析工程团队负责所有计划作业的监控,而是设置作业的分析团队也负责监控作业失败以及模型维护。随着平台上运行的作业和任务数量的增加,分配所有权变得至关重要。

当我们过渡到 PySpark 作为大规模分析的标准化平台时,我们面临的第一个问题是我们的团队需要学习 PySpark,这可以被描述为 Python 语言的一种方言。虽然 PySpark 可以运行任何 Python 命令,但是当您利用使用这种分布式数据结构的 Spark 数据帧和库时,PySpark 的真正潜力将被释放出来,这种分布式数据结构使命令能够在一个机器集群上运行,而不仅仅是在一个驱动程序节点上运行。
为了启动采用 PySpark 运行日常任务的流程,我们开始收集培训材料,以帮助我们的团队适应这个新的生态系统。我们的培训材料包括执行常见操作的示例笔记本、我们为开始使用该平台而编写的入职培训材料,以及作为场外团队活动一部分的培训课程。我们希望提供足够的材料,以确保我们的团队能够在这个新平台上执行日常任务。
我们在这个平台上进行培训的下一步是指导。除了录制培训课程的场外活动之外,我们还提供了更直接的指导。我们举行了办公时间,在那里我们更有经验的 PySpark 用户可以为我们仍在学习该平台的团队成员回答问题。这种方法的结果喜忧参半,但一个积极的结果是,最活跃的参与者与能够提供定向反馈的导师结成了伙伴关系。
虽然我们试图在培训材料方面走在前面,但一旦平台推广到整个团队,推动平台的采用仍然是一个挑战。我们发现,推动平台采用的最佳方式之一是将需要利用平台来完成项目的不同团队配对,从而实现跨团队协作。例如,我们有一个团队正在我们的 Jupyter 笔记本电脑环境中进行强化学习项目,当我们将我们的 ML 工程团队添加到该项目中时,数据科学家了解了如何通过将现有工作流移植到 PySpark 来扩展它们。

我们加快平台采用的另一种方法是利用 Python 编码人员熟悉的 PySpark 生态系统的功能,但在幕后使笔记本电脑能够在一个机器集群上以分布式方式运行。Pandas UDFs 是一种以分而治之的方式创作函数的方法,在这种方法中,您可以定义如何对数据集进行分区,编写标准 Python 代码以对数据子集进行操作,然后将结果组合回分布式数据框中。我在 2019 年 Spark 峰会上讨论了【Zynga 如何使用这种方法。
考拉是 PySpark 中的另一个特性,我们探索这个特性是为了让我们的分析师和数据科学家能够从 Python 代码跳到 PySpark。它提供了与 Pandas dataframes 相同的接口,但是以分布式模式执行。虽然由于实现的限制,目前不可能简单地替换这些库来使现有的 Python 代码在集群环境中工作,但它确实为学习如何使用分布式数据集提供了一个有用的桥梁。

我们已经为 ML 模型分配了数据管道的所有权,这使得我们的分析团队能够将我们生产的模型数量扩大一个数量级。虽然我们以前的方法是让数据科学家构建模型规范,并将其交给我们的分析工程团队进行生产,但我们的新模型是在这些团队之间进行合作,让分析师和数据科学家拥有更多实时 ML 模型的 DevOps 方面。我们有多种方法将模型投入生产,例如构建批处理管道,将预测推送到我们的应用程序数据库,或者与 ML engineering 合作,使用 AWS SageMaker 将模型设置为 web 端点。虽然我们的分析师和数据科学家不负责监控支持这些模型的基础架构,但他们负责监控为预测服务的模型的正常运行时间和性能。

我们让我们的团队更容易访问该平台的另一种方式是创作一个内部库,该库执行我们的分析团队需要执行的常见功能。这包括读取和写入各种数据源,以及将 ML 输出发布到我们的应用程序数据库,在那里我们的实时服务可以使用预测。我们也构建了一些模型维护工具,但是随着库的成熟和提供更多的特性,我们一直在向 MLflow 迁移。

随着我们向更多的团队成员开放平台,我们面临的一个问题是不同笔记本之间的库版本冲突。我们也不想为每个用户增加一个集群,因为成本可能会失控。我们决定采用一种策略,在这种策略中,交互式集群有固定的库版本,调度的作业被设置为在临时集群上运行,这意味着调度的作业不会干扰任何其他任务。此外,对于处理新工作流的团队,团队可以请求开发集群在迁移到运行在临时集群上的计划作业之前测试工作流。

虽然我们将所有权分配给了运行作业的嵌入式团队,但我们在确定作业所有者方面仍然存在差距。在我们向所有团队开放平台之前,我们对现有作业进行了审核,并确保所有正在运行的作业都产生了可供我们的游戏团队使用的输出。一旦我们完成了审计,我们就建立了一个安排新工作的流程。现在作业需要一个所有者、一个备份所有者和一个团队别名来调度,我们收集游戏工作室正在使用的模型输出的日志。对于我们计划长期运行的任务,我们将工作流迁移到气流,在那里我们有强大的监控。

我们学到的另一课是关于成本跟踪。我们在一个新的平台上释放了一个兴奋的团队,我们的团队渴望使用 GPU 等功能来训练深度学习网络。虽然任何人都可以连接笔记本电脑和运行 PySpark 脚本,但我们将集群创建限制在我们的 ML 工程团队,这是分析工程的一部分。为了控制成本,我们使用脚本标记所有集群,以确保我们可以监控费用。我们还会淘汰旧集群,并根据需要淘汰特定于项目的集群。我们的目标是避免需要特定库的长时间运行的集群,而是建立具有最新库的共享集群。

我们打开了这个新平台的闸门,但需要一些推动才能让团队探索这个平台。虽然这是一个类似于 Jupyter 的笔记本电脑环境,但它也面临着挑战。例如,Spark 中任务的延迟执行给我们的团队带来了具有挑战性的调试工作。任务不会立即失败,脚本可能会在失败前完成几个步骤。
虽然我们最初的方法是有一个松散的频道作为 Spark 问题的总括,但当我们将较新的 Spark 用户与有经验的 Spark 用户配对时,我们发现信噪比更高。我们还关注跨团队合作,以确保我们有不同经验水平的人在项目中工作。

我们发现成功采用 PySpark 的第一个项目是 AutoModel 系统,该系统每天构建数百个倾向模型。这是一个端到端的工作流,它从我们的数据湖中提取数据,使用 Featuretools 库应用自动化特征工程,并使用 Spark 附带的 MLib 库训练分类模型。工作流的输出是写入我们的应用程序数据库的预测分数,该数据库构建在 Couchbase 上。一旦结果发布到 Couchbase,我们的游戏团队就可以使用预测值来设置实验和个性化游戏体验。虽然我们对这个系统有一些用例,这为我们所有的游戏创造了失效的可能性和购买预测的可能性,但我们的产品经理为这些预测值提出了我们没有预料到的新应用。

Zynga 的 PySpark 的另一个用例是使用我们的数据将玩家分为不同的玩家原型,这使我们能够更好地了解我们的玩家群。虽然一些嵌入式分析师已经为特定的游戏做了这种类型的工作,但这通常是一次性的工作,而不是为我们的游戏团队提供最新细分市场的计划任务。我们能够使用 PySpark 将这些细分模型投入生产,使这些细分能够用于我们的实验堆栈。虽然与 scikit-learn 相比,我们在 MLlib 中可用于聚类玩家的算法较少,但我们能够标准化我们的方法,并将此管道应用于我们产品组合中的多个游戏。

我们的分析团队在过去几年中参加了黑客马拉松,这是我们的分析团队在 PySpark 上尝试项目的绝佳机会。这些项目产生的一个新颖应用是使用深度学习的异常检测系统。该系统将用户活动编码为 1D 图像,使用自动编码器将图像压缩到潜在空间,然后使用自动编码器解压缩图像。输入和输出图像之间有很大差异的玩家会被进一步调查。虽然这个工作流仅限于单个机器而不是集群,但我们的团队能够利用 GPU 设置的大型实例来快速迭代 Tensorflow 模型。这是开放这个平台真正有利于我们正在探索的一些工作的一个很好的方式。

我们在 PySpark 中看到的一个主题是,它支持组合规模分析,为特定游戏开发的方法通常可以扩展到多个游戏。这方面的一个例子是我们的老丨虎丨机分析团队最初探索的经济模拟项目。虽然这个工作流的最初版本是针对这种类型的游戏的,但该团队能够将模拟游戏经济概括为马尔可夫链,并将该方法移植到使用 Spark 数据框架。其结果是一种方法,可以提升到跨我们的几个游戏的大型模拟。

虽然我们发现的大多数新应用程序都专注于构建 ML 管道,但我们也发现 PySpark 对于扩展其他类型数值计算的工作负载很有用。使用 Pandas UDFs,我们能够使用现有的笔记本,并使用分而治之的方法使代码在一个机器集群上并发运行。这使我们能够使用 scipy、numpy 和 statsmodels 库进行分布式工作,并帮助完成缩放任务,例如 A/B 测试的显著性测量。

我还想展示 Zynga 的另一个项目,这是我们的强化学习管道,名为 RL Bakery 。虽然这个工作流没有直接使用 PySpark,但我们发现我们的一些数据科学家正在使用 Spark 进行深度学习模型的离线训练,我们需要一个管道来实时服务这些模型,并为模型提供在线更新。我们已经使用这个管道为 Word With Friends 2 和 CSR Racing 2 的生产中的强化学习模型提供服务,示例应用程序包括通知计时。

回顾本次会议的收获,我们已经向我们的整个分析团队开放了我们的 Spark 基础设施,结果是为游戏工作室开发了新颖的应用程序,这些应用程序现在正在为直播服务提供支持。虽然推动该平台的采用需要一些时间,但随着更多团队成员开始使用该平台,我们确实建立了势头,并且我们专注于能够利用 PySpark 快速扩大规模的跨团队项目。我们还面临着管理机器集群和库版本的挑战,以及控制成本的挑战,但产出的提高完全值得付出这些成本。Zynga 的 PySpark 民主化使我们的分析组织能够解决新的大规模问题,并使我们的分析团队能够接触到更多大数据工具。

感谢您参与本次会议。Zynga analytics 正在招聘,你可以在这里找到空缺职位的名单。
揭开员工离开 EDA 的神秘面纱
解释性数据分析,具有深刻的视觉效果和有趣的发现

来自 pixabay 的 Img 通过链接
在之前的帖子中,我试图预测一个银行客户是否可能离开,或者一个应用程序用户是否可能流失或订阅。现在,我将分享最近在人力资源领域的工作,给那些努力留住员工的公司带来一些预测能力。
在这第一篇文章中,我将重点探索数据集的任何有趣的模式。一如既往,它分为以下几部分:
1.问题陈述
2.数据审查
3.分布分析
4.独立变量相关分析
5.响应变量相关分析
6.外卖食品
让我们开始旅程吧🏃♂️🏃♀️.
1。问题陈述
如果你来自人力资源部门,你可能会同意雇佣和留住员工是复杂的任务,需要资金、时间和技能。
根据 toggle hire 的说法,公司花费员工工资的 15%-20%来招聘一名新的候选人。在一家拥有 0-500 名员工的公司中,雇佣一名员工的平均成本为 7645 美元🙀🙀。
作为一名数据科学家,你的任务是开发一个可以预测哪些员工更有可能辞职的模型。您的发现将有助于更有效地留住员工。
2。数据回顾
这里使用的数据集是来自 Kaggle 的 IBM HR Analytics 数据集。共有 1470 条记录,包含 35 个特征。查看下面的视频,真正接触原始数据集。
为了更好地理解每个特性的含义,我在下面做了一个易于查看的图。

图 1 数据变量概述
要了解数值变量的分布,请使用下面的。
employee_df.describe()
对于数据质量检查(如果每列中有任何空数据或缺失数据)和查看数据类型,请使用以下内容:
employee_df.info()
请注意,您还可以使用下面的命令来检查数据帧中是否有 NA 值:
employee_df.isna().any()
employee_df.isnull().any()
通过以上所有内容,我们发现 26 个数值变量和 9 个分类变量没有缺失值。
3。分布分析
我们使用直方图作为数值变量分布分析的简单可视化。
首先,让我们将二进制分类数据转换成数字。使用带有 lambda 的单行函数来应用于整个列。然后,pandas 内置绘图功能来创建直方图。具体来说,
employee_df[‘Attrition’] = employee_df[‘Attrition’].apply(lambda x: 1 if x == ‘Yes’ else 0)
employee_df[‘OverTime’] = employee_df[‘OverTime’].apply(lambda x: 1 if x == ‘Yes’ else 0)
employee_df[‘Over18’] = employee_df[‘Over18’].apply(lambda x: 1 if x == ‘Y’ else 0)
employee_df.hist(bins = 30, figsize= (15, 15), color = 'r')

图 2 数值变量的分布分析
回顾图 2,您可能会发现“员工人数”、“18 岁以上”和“标准工时”栏没有价值,因为这些对所有员工都是一样的。因此,让我们删除它们:
employee_df.drop([‘EmployeeCount’, ‘EmployeeNumber’, ‘Over18’, ‘StandardHours’], axis = 1, inplace = True)
4。自变量相关性分析
变量相关性是一个值得每个数据科学家关注的重要问题。
通常,相关要素不会提高模型性能。考虑到维数灾难和模型的可解释性,移除相关特征是明智的。要执行相关性分析,请使用:
correlations = employee_df.corr()
plt.subplots(figsize = (20, 20))
sns.heatmap(correlations, annot = True)
图 3 显示了一些明显的相关性。例如,‘总工作年数’与‘工作级别’和‘月度收入’有很强的相关性。一般来说,我们可以看到相当多的变量相关性很差。太好了,因为我们希望用彼此不高度相关的特征来训练预测模型。

图 3 预测因子的相关性分析
5。响应变量相关性分析
为了分析每个特征如何影响员工休假,我们可以检查每个变量相对于响应变量的分布。
首先,对于员工【年龄】,我们用计数图,
plt.figure(figsize = (25, 10), dpi = 300)
sns.countplot(x = ‘Age’, hue = ‘Attrition’, data = employee_df )
图 4 显示了 25-35 岁之间的员工,与其他年龄组相比,显示了较高的休假比率。在 21 岁以下,可以看到很高的离职率,表明年轻的专业人士更有可能离开公司🤭。

图 4 员工休假计数图与年龄
第二,对于‘job role’,计数情节为:
sns.countplot(x = ‘JobRole’, hue = ‘Attrition’, data = employee_df)
图 5 显示 【销售主管】【销售代表】【实验室技术员】相比其他角色**更有可能离职。

图 5 员工休假曲线图与工作职责
第三,让我们用 KDE(核密度估计)来分析数值变量的概率密度函数。
KDE 采用带宽和核函数,通过加权每个样本附近的距离来近似人口的真实分布。附近的数据点越多,估计值就越高,表示看到一个点的概率。带宽决定了最终曲线的“平滑”程度。较低的带宽意味着只有靠近当前位置的点被赋予权重。解释的够多了,如果想要更多的介绍,试试这个链接。我们来看看如何实现。
对于变量‘距离原点’,
sns.kdeplot(left_df[‘DistanceFromHome’], label = ‘Employee left’, shade = True, color = ‘r’, )
sns.kdeplot(stayed_df[‘DistanceFromHome’], label = ‘Employee stay’, shade = True, color = ‘b’)
如图 6 所示,当离家的距离大于 10 公里时,更多的员工倾向于离开🆒🆒。

图 6 KDE 距离图
对于变量【任职年限】,更多的员工倾向于在任职不到 2 年的情况下离开,现任经理,倾向于在任职超过 5 年的情况下留在🧨🧨,如图 7 所示

图 7 使用 CurrManager 的年 KDE 曲线图
对于变量‘总工作年数’,更多的员工倾向于在工作不到 7 年时离开 ️📣如图 8 所示

图 8总工作年限的 KDE 曲线图
现在,让我们用箱线图来形象化地比较【每月收入】在【性别】之间的分布。如图 9 所示,女性和男性月收入显示出相似的可变性,具有相似的中位数、75%和 25%四分位值👏👏如图 9 所示

图 9月收入 btw 性别箱线图
最后,让我们看看不同的【工作角色】收入分配。图 10 显示了不同角色的月收入分布和可变性。有趣的是,我们发现“销售代表”的分布很紧凑,收入普遍低于其他职位🙀。这可以解释为什么【销售代表】倾向于离开更多,如图 5 所示

图 10月收入 btw 岗位职责箱线图
6。外卖
- 数据质量检查告诉我们,我们的数据集非常干净,没有丢失值。
- 独立变量相关性分析表明,相当多的特征似乎彼此相关性很差。
- 自变量和响应变量之间有趣的模式显示了员工可能离职的一些线索。
希望这能对如何更好地理解你的员工或同事的离职决定有所启发。
太好了!这趟旅程的终点。在下一篇文章中,我们将关注真正有趣的部分:建模。在那里见💕💕
用机器学习揭开员工离职之谜
用于休假预测的少数机器学习模型的创建和评估

来自 unsplash 的 Img 通过链接
在以前的帖子中,我试图预测银行客户是否可能离开,或者应用程序用户是否可能流失或订阅。在这里,我将分享最近在人力资源领域的工作,给任何努力留住员工的公司带来一些预测能力。
在这第二篇文章中,我的目标是评估和对比一些不同模型的性能。一如既往,它分为:
1.数据工程
2.数据处理
3.模型创建和评估
4.外卖食品
1。数据工程
在第一篇帖子中完成了简短的数据探索之后,让我们继续进行特征工程和数据编码。特征工程包括从当前特征创建新特征和关系。
首先,让我们把分类变量和数字变量分开。我们可以使用 数据类型方法 来查找分类变量,因为它们的 数据类型 将是‘对象’。您可能会注意到,在使用employee _ df . info()时,已经显示了数据类型。
然后,我们可以对分类变量进行编码。有两种方法可用。一个是用来自 sklearn 的 OneHotEncoder,一个是来自 熊猫 的get _ dummies()。我更喜欢后者,因为它返回一个 dataframe,使下面的步骤变得容易。具体来说,
employee_df_cat = pd.get_dummies(employee_df_cat)
然后,将编码的分类变量和数字变量连接在一起。具体来说,
X_all = pd.concat([X_cat, X_numerical], axis = 1)
最后一步是生成目标变量。
employee_df[‘Attrition’] = employee_df[‘Attrition’].apply(lambda x: 1 if x == ‘Yes’ else 0)
y = employee_df[‘Attrition’]
2。数据处理
现在我们准备好处理数据,包括数据分割、缩放和平衡。
为了使数据为训练做好准备,我们需要缩放特征以避免任何变量支配其他变量,即采取更高的权重和对模型学习的强烈影响。具体来说,
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
X = scaler.fit_transform(X_all)
现在,让我们将数据集划分为训练集和测试集。要拆分数据,
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.25)
我们已经注意到员工去留严重失衡。所以让我们实现 SMOTE 方法来对少数类进行过采样。具体来说,
oversampler = SMOTE(random_state=0)
X_smote_train, y_smote_train = oversampler.fit_sample(X_train,y_train)
太好了!现在模型的数据已经准备好了📣📣。
3。模型创建&评估
正如本文开头提到的,我们的目标是评估和比较一些模型的性能。
3.1 逻辑回归
简单地说,逻辑回归对独立变量的线性组合使用对数变换,这允许我们以线性方式对非线性问题建模。通常用于二元分类问题,其中假设预测值和响应变量之间存在某种相关性。
为了创建一个逻辑回归分类器,我们使用 sklearn 如下。
from sklearn.linear_model import LogisticRegression
model = LogisticRegression()
model.fit(X_smote_train, y_smote_train)
为了评估性能,我们使用混淆矩阵。
y_pred = model.predict(X_test)
cm = confusion_matrix(y_pred, y_test)
sns.heatmap(cm, annot= True)
如图 1 所示,逻辑回归分类器给出的准确度为 0.75,F1 值为 0.52。

图 1 逻辑回归模型的混淆矩阵
3.2 随机森林
随机森林是一种以决策树为构建块的集成模型。它创建了一组决策树,并使用它们的集体预测能力来获得相对较强的性能。要想真正了解兰登森林的基础知识,可以参考这个公民网博客。
要创建随机森林分类器,
from sklearn.ensemble import RandomForestClassifier
model = RandomForestClassifier()
model.fit(X_smote_train, y_smote_train)
使用相同的方法来评估性能,我们获得了 0.85 的准确度和 0.39 的 F1 分数。

图 2 随机森林模型的混淆矩阵
3.3 人工神经网络
最后的尝试是创建和训练一个人工神经网络。在这里,我们将建立一个具有几个密集层的顺序模型,并使用剔除技术来减少过拟合。具体来说,
from keras.models import Sequential
from keras.layers import Dense, Dropout
model = Sequential()
model.add(Dense(units = 50, activation = ‘relu’, input_shape = (50, )))
model.add(Dense(units = 500, activation = ‘relu’))
model.add(Dropout(0.3))
model.add(Dense(units = 500, activation = ‘relu’))
model.add(Dropout(0.3))
model.add(Dense(units = 50, activation = ‘relu’))
model.add(Dense(units = 1, activation = ‘sigmoid’))
为了编译神经网络,我们使用‘亚当’优化器和二元交叉熵作为损失函数。
model.compile(optimizer=’adam’, loss = ‘binary_crossentropy’, metrics = [‘accuracy’])
epochs_hist = model.fit(X_smote_train, y_smote_train, epochs = 50, batch_size = 50)
y_pred = model.predict(X_test)
y_pred = (y_pred > 0.5)
如上所述,我们将 sigmoid 函数输出的阈值概率设置为 0.5。因此,任何大于 0.5 的输出被视为“离开”,否则被视为“停留”。图 3 显示了训练期间的模型损失。似乎该模型在 20 个纪元内达到了收敛。

图 3 训练过程中的模型丢失
最后,如图 4 所示的混淆矩阵热图给出了 0.88 的准确度和 0.41 的 F1 分数。

图 4 人工神经网络的混淆矩阵
4。外卖
最后,让我们将性能汇总在表 1 中。为了更好地理解指标,后退一步。我们的任务是预测员工是否可能离职。由于类别之间的高度不平衡,准确性不是一个好的指标。在我看来,减少假阴性错误比假阳性更有意义,因为该模型可以识别更多正在离开的人🤔。基于这个逻辑,逻辑回归模型是赢家。但显然,还有相当大的提升空间。

表 1 模型性能概述
太好了!希望这篇文章为不同的 EDA 和机器学习技术打下良好的基础。像往常一样,如果你对代码感兴趣,可以查看我的 GitHub 资源库 这里 🤞🤞。
揭开阿帕奇箭的神秘面纱
了解关于一种工具的更多信息,该工具可以在两秒钟内在您的笔记本电脑上过滤和聚合 20 亿行
在我作为数据科学家的工作中,我在一系列看似不相关的情况下遇到过 Apache Arrow。然而,我总是很难准确地描述它是什么,它做什么。
Arrow 的官方描述是:
用于内存分析的跨语言开发平台
这很抽象——而且有充分的理由。该项目雄心勃勃,旨在为大范围的数据处理任务提供主干。这意味着它位于较低的级别,为更高级的、面向用户的分析工具(如 pandas 或 dplyr)提供构建模块。
因此,对于那些在日常工作中偶尔遇到这个项目的用户来说,这个项目的重要性可能很难理解,因为它的大部分工作都是在幕后进行的。
在这篇文章中,我描述了我在工作中遇到的 Apache Arrow 的一些面向用户的特性,并解释了为什么它们都是 Apache Arrow 旨在解决的更基本问题的各个方面。
通过连接这些点,可以清楚地了解为什么 Arrow 不仅是解决当今一些实际问题的有用工具,而且是最令人兴奋的新兴工具之一,有可能成为未来数据科学工作流的大部分背后的引擎。
更快的 csv 读取
Arrow 的一个显著特点是,它可以将 CSV 读入熊猫图,比pandas.read.csv快 10 倍以上。
这实际上是一个两步过程:Arrow 将数据读入内存中的 Arrow 表,该表实际上只是记录批次的集合,然后将 Arrow 表转换为 pandas 数据帧。
因此,加速是 Arrow 底层设计的结果:
- Arrow 有自己的内存存储格式。当我们使用 Arrow 将数据加载到 pandas 时,我们实际上是将数据加载到 Arrow 格式(数据帧的内存格式),然后将其转换为 Pandas 内存格式。因此,读取 CSV 的部分加速来自于箭头列格式本身的精心设计。
- 箭头中的数据以记录批的形式存储在内存中,记录批是一种 2D 数据结构,包含等长的连续数据列。可以从这些批处理中创建一个'表,而不需要额外的内存复制,因为表可以有“分块”列(即数据段,每个部分代表一个连续的内存块)。这种设计意味着可以并行读取数据,而不是 pandas 的单线程方法。
PySpark 中更快的用户定义函数(UDF)
在 Apache Spark 中运行 Python 用户定义函数一直非常慢——慢到通常建议不要在任何大规模的数据集上运行。
最近,Apache Arrow 使得在 JVM 和 Python 进程之间高效地传输数据成为可能。结合矢量化 UDF,这导致了巨大的加速。
这是怎么回事?
在引入 Arrow 之前,将数据从 Java 表示转换为 Python 表示的过程非常缓慢——包括序列化和解序列化。它也是一次一行,速度较慢,因为许多优化的数据处理操作对以列格式保存的数据最有效,每列中的数据保存在内存的连续部分中。
Arrow 的使用几乎完全消除了序列化和解序列化步骤,还允许以列批处理方式处理数据,这意味着可以使用更高效的矢量化算法。
Arrow 能够在不同语言之间传输数据,而不会产生很大的序列化/反序列化开销,这是一个关键特性,使得用一种语言实现的算法更容易被使用其他语言的数据科学家使用。
将文件夹中的文件作为单个表格读取
Arrow 能够将包含许多数据文件的文件夹读入单个数据帧。Arrow 还支持读取数据被划分到子文件夹的文件夹。
此功能说明了记录批次周围的箭头的高级设计。如果所有东西都是一个记录批,那么源数据是存储在一个文件中还是多个文件中就无关紧要了。
读取拼花文件
Arrow 可用于将 parquet 文件读入 Python 和 R 等数据科学工具,正确表示目标工具中的数据类型。由于 parquet 是一种自描述格式,并且在模式中指定了列的数据类型,因此获得正确的数据类型似乎并不困难。但是仍然需要一个翻译的过程来将数据加载到不同的数据科学工具中,这是令人惊讶的复杂。
例如,在历史上,pandas 整数类型不允许整数为空,尽管在 parquet 文件中这是可能的。类似的怪癖也适用于其他语言。Arrow 为我们处理这个翻译过程。数据总是首先被加载到 Arrow 格式中,但是 Arrow 提供了翻译器,然后能够将其转换成特定于语言的内存格式,比如 pandas dataframe。这意味着对于每个目标格式,需要一个格式到箭头的翻译器,这是对当前需要“n 取 2”个翻译器(每对工具一个)的巨大改进。
Arrow 的目标是最终完全消除这个翻译问题:理想情况下,数据帧应该有单一的内存格式,而不是每个工具都有自己的表示形式。
编写拼花文件
Arrow 可以很容易地将 pandas 和 R 等工具中保存在内存中的数据以 Parquet 格式写入磁盘。
为什么不直接将数据以 Arrow 格式保存到磁盘上,从而拥有一个在磁盘上和内存中相同的单一的跨语言数据格式呢?一个最大的原因是,Parquet 通常产生较小的数据文件,如果您是 IO 绑定的,这是更可取的。如果你从像 AWS S3 这样的云存储中加载数据,情况尤其如此。
Julien LeDem 在一篇讨论两种格式的博客文章中进一步解释了这一点:
列数据和内存中数据的权衡是不同的。对于磁盘上的数据,通常 IO 主导延迟,这可以通过以 CPU 为代价的激进压缩来解决。在内存中,访问速度要快得多,我们希望通过关注缓存局部性、流水线和 SIMD 指令来优化 CPU 吞吐量。
这使得在内存和磁盘格式的开发中密切合作,在两种表示之间进行可预测和快速的转换是可取的——这正是 Arrow 和 Parquet 格式所提供的。
这些想法是如何联系在一起的?
虽然非常有用,但迄今为止讨论的面向用户的特性并不是革命性的。真正的力量在于底层构建模块的潜力,它可以实现数据科学工具的新方法。目前(2020 年秋季),Arrow 背后的团队仍在进行一些工作。
记录批次和分块
在 Apache Arrow 中,数据帧由记录批次组成。如果存储在磁盘上的 Parquet 文件中,这些批处理可以非常快地读入内存中的 Arrow 格式。
我们已经看到这可以用来将 csv 文件读入内存。但更广泛地说,这一概念打开了整个数据科学工作流的大门,这些工作流是并行的,并对记录批次进行操作,从而消除了将整个表存储在内存中的需要。
数据帧的一种常见(跨语言)内存表示
目前,数据科学工具及其数据帧的内存表示的紧密耦合意味着用一种语言编写的算法不容易移植到其他语言。这意味着相同的标准操作,如过滤器和聚合,会被无休止地重写,优化不容易在工具之间转换。
Arrow 提供了在内存中表示数据帧的标准,以及允许多种语言和引用相同内存数据的机制。
这为的发展创造了机会
C++中的一个原生箭头列查询执行引擎,不仅用于 C++中,也用于 Python、R 和 Ruby 等用户空间语言中。
这将提供一个单一的、高度优化的代码库,可用于多种语言。对维护和贡献这个库感兴趣的开发人员将会更多,因为它可以在各种工具上使用。
伟大的想法
这些想法在 Arrow 作为“数据 API”的描述中结合在一起。其思想是 Arrow 提供了一种跨语言的内存数据格式,以及一种相关的查询执行语言,为分析库提供了构建块。像任何好的 API 一样,Arrow 为常见问题提供了一个高性能的解决方案,用户不需要完全理解实现。
借助分析库,这为数据处理能力的重大变革铺平了道路:
- 默认情况下被并行化
- 在数据帧上应用高度优化的计算
- 不再需要处理整个数据集必须适合内存的约束
同时通过在单台机器上或通过网络在工具之间更快地传输数据,打破工具之间共享数据的障碍。
我们可以在 R 中 Arrow 包的插图中一窥这种方法的潜力,其中一个 37gb 的数据集有 20 亿行,在一台笔记本电脑上处理和聚合不到 2 秒钟。
这将现有的高级数据科学工具和语言(如 SQL、pandas 和 R)置于何处?
正如插图所示,Arrow 的目的不是直接与这些工具竞争。相反,更高级的工具可以使用箭头,对它们面向用户的 API 施加很少的约束。因此,它允许在不同工具的表达能力和特性方面继续创新,同时提高性能并为作者节省重新发明通用组件的任务。
进一步阅读
https://arrow.apache.org/overview/
https://arrow.apache.org/use_cases/
https://arrow.apache.org/powered_by/
https://arrow.apache.org/blog/
https://ursalabs.org/blog/
https://wesmckinney.com/archives.html
https://www.youtube.com/watch?v=fyj4FyH3XdU
箭头设计文档:
文件系统 API
数据集 API
数据框架 API
C++查询引擎
揭秘人工智能!
打破人工智能领域和它的未来。

GIF 来自 GIPHY
根据麦肯锡全球研究所的一项研究,预计到 2030 年,人工智能每年将创造 13 万亿美元的额外价值。即使在今天,人工智能技术也产生了巨大的收入,但主要是在软件领域。
然而,到 2030 年,将产生的收入将在软件行业之外,特别是在零售、旅游、运输、汽车、材料、制造等行业。
人工智能将在几个领域产生巨大影响,但围绕它也有很多不必要的炒作。人工智能的“金发姑娘法则”指出,人们不应该对人工智能技术持乐观或过于悲观的态度。
虽然承认人工智能将拥抱世界的现实期望是令人敬畏的,但理解和揭穿围绕人工智能的神话同样重要。
人工智能、机器学习(ML)和深度学习(DL)这些热门词汇在最近被频繁使用。让我们分别反省一下每个方面,以便真正理解这些概念。
在这篇文章中,我们将揭开人工智能的所有概念,并完美地理解它的每个方面,以便在这个问题上没有任何困惑。
所以,事不宜迟,让我们开始打击——人工智能。
缩小人工智能的领域

人工智能的主题是巨大的,类似于巨大的银河系。人工智能(AI)是一个广泛的领域,有许多子类别,如自然语言处理(NLP)、人工神经网络、计算机视觉、机器学习、深度学习、机器人等等。人工智能的正式定义是—
“能够执行通常需要人类智能的任务的计算机系统的理论和发展,如视觉感知、语音识别、决策和语言之间的翻译。”
然而,即使在我们开始深入这些其他领域之前,人工智能也可以缩小到以下两个独立的更广泛的领域:
- 人工狭义智能— 执行一项或几项特定的任务,这些任务是通过编程来完成的。这些例子包括自动驾驶汽车、下一个单词预测、自动更正等。这是我们将关注的主要概念。
- 人工通用智能— 它们执行类似人类的活动和任务。通用人工智能是一种智能,可以像人类一样高效地执行任何智力任务。在这一领域仍有许多进展要做。
还有另一个术语叫做超级人工智能或强人工智能,被认为是超越人类的人工智能。然而,这只是一个假设的概念,本文不会讨论,因为我们在未来几年还远远没有达到这种智能水平。
为了理解人工智能的概念和围绕它的各个方面,我开发了一个关于宇宙的简单类比。
浩瀚的银河系类似于人工智能的广阔领域。它包含了数十亿个太阳系,类似于人工智能是如何由这么多子领域组成的。我们的太阳系类似于人工智能中的一个子领域,即“机器学习”。地球是我们太阳系中唯一可居住的星球,可以被称为“深度学习”。
通过我们的类比,我们可以得出这样的结论:人工智能类似于浩瀚的银河系,这是一个由子课题组成的广阔领域,如可以与我们的太阳系相提并论的机器学习,深度学习是机器学习的子课题,类似于太阳系中的地球。下面是一个简单的参考,以便更好地理解这个类比。
AI =银河系| ML =太阳系| DL =地球
让我们讨论一下人工智能的其他重要方面,即机器学习、深度学习和数据。

机器学习:
机器学习是程序自动学习和提高效率的能力,而无需显式编程。这意味着给定一个训练集,你可以训练机器学习模型,它将理解一个模型到底是如何工作的。在对测试集、验证集或任何其他看不见的数据进行测试时,模型仍然能够评估特定的任务。
让我们用一个简单的例子来理解这一点。假设我们有一个 30,000 封电子邮件的数据集,其中一些被分类为垃圾邮件,一些被分类为非垃圾邮件。机器学习模型将在数据集上训练。一旦训练过程完成,我们可以用一封没有包含在我们的训练数据集中的邮件来测试它。机器学习模型可以对以下输入进行预测,并正确分类输入的电子邮件是否是垃圾邮件。
机器学习的三种主要类型如下:
- 监督学习— 这是一种用专门标记的数据集训练模型的方法。数据集可以是二元分类,也可以是多类分类。这些数据集将具有指定正确和错误选项或一系列选项的标注数据。在监督下,即在这些标记数据的帮助下,对模型进行预训练。
- 无监督学习— 无监督学习是在无标签数据集上训练模型。这意味着模型没有先验信息。它通过将相似的特征和模式组合在一起来训练自己。无监督学习的一个例子可以是狗和猫的分类。
- 强化学习— 强化学习是一种试凑法模型。这是模型通过重复失败来学习的方法。当一个模型没有达到期望的结果时,该模型将重新训练。这可以应用于像下棋这样的概念,在玩了数百万局游戏后,模型将能够学习适当的模式和移动。
随着对机器学习的想法和认识的清晰,我们现在可以继续前进到数据的基本概念以及为什么它对我们如此重要。

斯蒂芬·菲利普斯-Hostreviews.co.uk 在 Unsplash 上拍摄的照片
数据:
数据可以被认为是适用于执行机器学习或深度学习任务的任何可用的有用资源或信息。您想要构建的每个模型都有大量数据可用。重要的是搜集并找到完成评估所需的有价值的数据。
数据集是数据的集合。在表格数据的情况下,数据集对应于一个或多个数据库表,其中表的每一列代表一个特定变量,每一行对应于所讨论的数据集的给定记录。
在当今时代,人工智能的普及速度比以往任何时候都快,为此,我们必须感谢数据的丰富和增长。由于数据量的增加,人工智能的增长速度大大加快。
更多的数据可以更好地训练机器学习或深度学习模型,因为我们能够在更大的数据集上训练模型,这有助于模型在训练中更好地学习,通常可以更好地执行手头的任务。
数据科学就是关于数据的。这个术语有时可能会被随意抛弃,但它对任何项目来说都是最有价值的资源。大数据、数据科学和数据分析领域正在迅猛发展。科技巨头正在加大对有用数据收集的投资。
数据收集是在一个已建立的系统中收集和测量目标变量信息的过程,然后使人们能够回答相关问题并评估结果。要了解更多关于数据收集和每个机器学习和数据科学项目所需的其他基本技术,请查看下面的文章。
详细讨论构建您的机器学习和数据科学项目的最佳方法…
towardsdatascience.com](/10-step-ultimate-guide-for-machine-learning-and-data-science-projects-ed61ae9aa301) 
深度学习:
深度学习是机器学习的一个子领域,它基于人工神经网络的概念来执行特定的任务。人工神经网络从人脑中提取灵感。
然而,最重要的是要注意,它们在理论上并不像我们的大脑那样运作,一点也不像!它们被命名为人工神经网络,因为它们可以完成精确的任务,同时达到理想的精度,而无需用任何特定的规则显式编程。
几十年前,深度学习非常流行,但由于缺乏计算复杂计算的数据和技术,它最终失去了大部分宣传。
然而,在过去几年里,这种情况发生了显著变化。大量的数据每天都在激增,因为大型科技巨头和跨国公司正在投资这些数据。由于强大的图形处理单元(GPU),计算能力也不再是一个大问题。
深度学习的强化每天都在快速增加,尤其是有了巨大的改进。深度学习在今天非常受欢迎,并且具有远远超过现代大多数机器学习算法的巨大潜力。
如果你有兴趣了解更多关于深度学习和人工神经网络的历史,那么请随意访问下面的文章。
重温人工神经网络发展背后的迷人历史
towardsdatascience.com](/the-complete-interesting-and-convoluted-history-of-neural-networks-2764a54e9e76) 
库纳尔·辛德在 Unsplash 上拍摄的照片
结论:
人工智能是当今发展最快的领域。据财富报道,统计数据显示,人工智能专家的雇佣量在过去 4 年里增长了 74%。人工智能被认为是当代人最热门的工作。
对熟练人工智能专家的需求正以前所未有的速度增长。对机器学习、深度学习、计算机视觉、统计学和自然语言处理等人工智能子领域专家的需求和空缺职位每天都在激增。
由于我们周围存在巨大的机会,我们很幸运处于人工智能兴起的时代。我们被人工智能包围着,我发现这个领域的快速进步非常令人着迷。我对未来更新的技术和人工智能的兴起感到兴奋。
我很想知道你们所有人对人工智能的不断进步和崛起有何看法。是让你兴奋,还是你真的不太在乎?不管怎样,知道这个会很酷。😄
看看我的其他一些文章,你可能会喜欢读!
[## 用代码和例子简化函数的 args 和 kwargs!
理解 python 编程和机器学习的args 和kwargs 的完整概念。
towardsdatascience.com](/simplifying-args-and-kwargs-for-functions-with-codes-and-examples-b785a289c2c2) [## 简单有趣的万圣节 Python 项目!
这是一个有趣的“不给糖就捣蛋”的游戏,让你在万圣节愉快地学习 python 编程
towardsdatascience.com](/simple-fun-python-project-for-halloween-ff93bbd072ad) [## 5+独特的 Python 模块,用于创建脱颖而出的机器学习和数据科学项目!
超过 5 个酷 Python 库模块的指南,用于创建令人敬畏的机器学习和数据科学项目。
towardsdatascience.com](/5-unique-python-modules-for-creating-machine-learning-and-data-science-projects-that-stand-out-a890519de3ae) [## 用代码和例子理解 Python 中的高级函数!
详细了解 python 中的匿名函数和高级函数及其实际应用…
towardsdatascience.com](/understanding-advanced-functions-in-python-with-codes-and-examples-2e68bbb04094)
谢谢你们坚持到最后。我希望你们喜欢阅读这篇文章。我希望你们都有美好的一天!
揭秘二分搜索法
搜索算法指南
升级你的搜索游戏!
在之前的文章中,我们一直在讲线性搜索。如果你没看过,建议你先浏览一下。现在你已经理解了线性搜索的概念,是时候让你知道一个更强大的搜索方法,那就是二分搜索法。

图片由 Unsplash 上的 Annie Theby 拍摄
在编程中,你会遇到很多需要在一个有序数组中找到一个元素的确切位置/索引的情况。大多数时候,二分搜索法将是正确的方法。这就是为什么二分搜索法是程序员工具箱中必不可少的工具。
什么是二分搜索法?
二分搜索法是一种有效的搜索技术。唯一的缺点是它只能在有序列表上运行。二分搜索法也称为对数搜索、二分法或半区间搜索。
通过从数组的中间开始,该算法可以通过确定所需的关键字是放在前半部分还是后半部分来有效地将搜索空间减半。
它是如何工作的?
这些是在二分搜索法完成的步骤:
- 从中间元素开始,将该元素与所需的键进行比较。
- 如果键匹配中间的元素,则返回中间的位置。
- 如果键小于中间的元素,那么键只能位于左半部分的子数组中。我们只将焦点移到左半部分的子阵列。
- 否则,我们只关注右半部分的子阵列。
- 重复步骤 1、2、3 和 4,直到找到所需的键或检查完每个子阵列。
- 如果数组中没有匹配项,则返回-1
二分搜索法的例子
在这里,我将为您提供一个二分搜索法算法的伪代码。阅读伪代码将帮助你更好地理解算法中到底发生了什么。
二分搜索法伪码
我还将提供 3 种不同编程语言的示例代码,Python、C 和 JavaScript。
Python 中的二分搜索法代码
C 语言中的二分搜索法码
JavaScript 中的二分搜索法代码
二分搜索法的时间复杂性
二分搜索法的最佳情况发生在所需密钥位于数组中间的时候,在这种情况下,时间复杂度为 O(1)。而对于最坏的情况,我们将需要进行 log2(n)比较,因为在每次迭代中,数组的长度变成一半。
例如,我们有一个长度为 8 的数组。在最坏的情况下,我们需要经历 3 次迭代。
- 在第一次迭代之后,我们关心的子阵列的长度是 8/2 = 4
- 在第二次迭代时,剩余子阵列的长度是 4/2 = 2
- 这是最后一次迭代,因为在这一步之后,子数组是一个单元素数组。
我们知道 log2(8)等于 3,这就是为什么二分搜索法的时间复杂度是 O(log n)。对于一般情况,所做的比较次数与最差情况大致相同。因此,平均情况下的时间复杂度也是 O(log n)。
最后的话
尽管二分搜索法很实用,但我们应该始终记住它有一些局限性:
- 必须对列表进行排序。
- 我们必须能直接接触到中间元素。
学习二分搜索法对每个想发展编程技能的人来说都是必不可少的。二分搜索法是一个伟大的工具,它将帮助你克服你在成为一名专业程序员的道路上所面临的许多问题。
"一步一个脚印是让你达到目标的唯一办法."
—艾米莉·狄金森
永远不要说以后再往前走一步!
问候,
弧度克里斯诺
揭开冒泡排序的神秘面纱
排序算法指南
升级你的排序游戏!
在前面的文章中,我们一直在讨论搜索算法。您可能还记得二分搜索法和插值搜索只对有序数组有效。可以肯定地说,排序是搜索算法的补充。排序是将数据结构中的元素重新排列成某种特定顺序(升序或降序)的操作。为了简单起见,我们将对所有数组进行升序排序。

有许多可用的排序算法,其中一些比另一些更好。然而,对我们来说,重要的是理解它们中的每一个,给我们一个完整的算法基础。在本文中,我们将从最简单的冒泡排序开始。
什么是冒泡排序?
冒泡排序也称为下沉排序,是一种简单的排序算法,它通过比较每对相邻元素来进行操作。首先,它比较第一个和第二个元素,然后是第二个和第三个元素,依此类推。如果前一个元素大于后一个元素,这两个元素将互换。
该算法因较大的元素会向最右边的位置“冒泡”而得名。在每个周期之后,最大的元素将是数组中未排序部分的最后一个元素。
它是如何工作的?
冒泡排序中完成的操作:
- 比较前两个元素。
- 如果前一个元素较大,则互换这两个元素。
- 重复步骤 1 和 2,直到到达数组的末尾。
- 重复步骤 1、2 和 3,直到所有元素都排序完毕。
需要注意的是,在第一次运行中,假设数组中的元素数量为 n,您需要进行 n-1 次比较。在第二次运行中,您只需要进行 n-2 次比较,而不需要进行最后一次比较,因为此时最后一个元素是最大的。这意味着,在每次运行中,比较的次数减少 1。
冒泡排序示例
在我们用 3 种不同的编程语言进行真正的实现之前,我会先给你们提供伪代码。
冒泡排序伪代码
是时候继续学习 Python、C 和 JavaScript 的真正代码了。
Python 中的冒泡排序代码
C 中的冒泡排序代码
JavaScript 中的冒泡排序代码
冒泡排序的时间复杂度
冒泡排序操作是基本的,但是它的时间复杂度不是最好的。最佳情况/最差情况/平均情况的时间复杂度是 O(n ),因为在任何阵列中,比较的总数是:
(n-1) + (n-2) + … + 3 + 2 + 1 = n(n-1)/2
对于任何数组,尽管该数组已经被排序,但是算法将精确地进行 n(n-1)/2 次比较。由于冒泡排序的时间复杂度为 O(N ),所以它很少在实际实现中使用。随着 n 变大,运行时间的增长会非常大。
放弃
虽然冒泡排序可能很少使用。学习冒泡排序绝对值得。学习冒泡排序将帮助你更容易地学习更高级的主题,因为它将充当你理解更高级概念的桥梁。
"我没有学到新东西的一天就是虚度的一天."
— B. B .金
每天愉快地学习新概念!
问候,
弧度克里斯诺
揭秘置信区间和误差范围
从统计学上说,我有 95%的信心到底意味着什么?

我最近看到了盖洛普国际协会电晕跟踪器的调查
我们都喜欢阴谋论!全球 36%的人将新冠肺炎归咎于外国势力。在 95%的置信水平下,调查的误差幅度为 3。本次调查在全球范围内进行了 20,000 多次采访。
我试图找到更多关于置信区间和误差幅度的信息,但对于没有深入统计学知识的人来说,它们似乎很难理解。挑战在于,大多数解释依赖于大量外行可能不知道的行话。
在这篇文章中,我会试着解释误差范围和置信区间的概念,而不用太多的数学和花哨的统计术语。

照片由 Element5 数码在 Unsplash 上拍摄
比方说,一家新闻机构正在试图计算在即将到来的选举中,有百分之多少的人会投票给一个政党。由于几乎不可能采访全部人口,他们随机选择了 100 人作为样本。在接受采访的 100 人中,有 43 人愿意投 A 。
让我们用数学术语来转换这个问题。我们要说,抽样一个将要投 A 的人相当于抽样 1,抽样一个不打算投 A 的人相当于抽样 0。这意味着在这 100 个样本中,43 个是 1,其余 57 个是 0。
现在让我们定义一些数学符号:

这里你可能会奇怪为什么计算标准差的分母是 n-1 而不是 n 。这是通过使用贝塞尔修正来消除总体方差估计中的偏差。更多信息,请参考此处的。
对于均值 μ_p (未知)、标准差 σ_p (未知)的总体,中心极限定理告诉我们:
- 如果我们从替换总体中随机抽取足够多的样本,那么样本均值的分布将是近似正态的。
- 抽样分布的平均值可以用来估计真实的总体平均值 μ_p
- 抽样分布的样本标准差( σ_x) 由 σ_p/√n 给出(即总体的标准差除以样本中的观察数)。
重要的补充说明:只有当我们的样本是随机的,即它们代表总体时,上述估计才成立。
为了计算 σ_x,我们需要未知总体的标准差( σ_p )。相反,我们使用样本的标准偏差( σ_s )来估计 σ_p 在使用贝塞尔校正去除偏差之后。
置信区间(CI)和误差范围的计算:

从上面的分布中,让我们找到一个区间,即我们可以 95%确定包含真实总体均值( μ_p,其值与抽样分布的均值( μ_s ))的值范围。说总体均值( μ_p )有 95%的概率在区间内,这是不太正确的。总体均值( μ_p )有一个我们不知道的固定值。如果我们重复进行相同的实验,它不会改变总体平均值( μ_p )。因此,询问总体均值( μ_p )在一定范围内的概率是不正确的。相比之下,我们计算的置信区间取决于收集的样本。如果我们重复这个实验,置信区间几乎肯定会不同。所以我们应该问区间包含总体均值的概率。
95%的置信区间仅仅意味着,在重复的随机样本中,真实总体均值( μ_p )有 95%的可能性位于区间内。
置信区间是频率统计中最广泛使用的区间估计方法,经常与可信区间混淆,可信区间是贝叶斯统计中的一个类似概念。关于这些差异的更专业的解释,请参考这里:置信区间和可信区间有什么区别?

现在让我们找出 z 的值,使得阴影区域的面积为 0.95 。 z 是偏离样本均值的标准偏差数,也称为临界值。
计算 ci 的公式采用以下通用形式:
CI =样本平均 z 值×平均值的标准误差(SEM)
CI =样本平均 z 值×(标准差/√n)
如果我们正在计算平均值的 95%置信区间,要使用的 z 值将是 1.96。
在我们的虚拟例子中,误差幅度是 0.098,或者大约 10% ( 1.96*σ_x )。
上述陈述可以解释为“我们有 95%的把握认为0.332(0.43–0.098)和 0.528(0.43+0.098) 之间的区间,捕捉到了将投票给的人口的真实平均比例。”这意味着,如果对来自同一总体的随机样本重复采样过程,那么预计 95%的计算区间将包含真实值。
误解:
我们不应该说总体的真实均值( μ_p )在 0.332 到 0.528 之间有 95%的几率,因为这暗示着均值可能在这个区间内,也可能在别的地方。这使得总体均值看起来是可变的,但事实并非如此。这个区间要么抓住了平均值,要么没有。样本与样本之间的间隔会发生变化,但是我们试图获取的总体参数不会发生变化。
95%的置信区间并不意味着 95%的样本数据位于该区间内。置信区间不是样本的可信值范围,而是总体参数的可信值的区间估计。

置信区间模拟。http://www.rossmanchance.com/applets/ConfSim.html
在第一个实验中,我随机选择了 1000 个样本,样本量为 5,95.5%的时间我们的置信区间包含真参数。需要注意的重要一点是,如果我们希望区间更窄,我们需要增加样本量,因为它与样本量的平方根成反比。
我希望置信区间和误差幅度这两个术语不再是一个陌生的概念。虽然这篇介绍遗漏了一些技术部分,但是有很多非常好的资源,可以提供更多的细节。我总是乐于接受问题和建议。通过 LinkedIn 联系我,别忘了点击👏🏻如果你喜欢邮报。
参考:
Morey,R.D .,Hoekstra,r .,Rouder,J.N. 等将信心置于置信区间的谬误。心理牛 Rev* 23,103–123(2016)。https://doi.org/10.3758/s13423-015-0947-8*
用购物篮分析揭开客户行为的神秘面纱
在这篇博客中,我们将看到如何通过使用关联规则进行市场购物篮分析来预测客户行为。

来源:oracle.com
购物篮分析简介
购物篮分析是大型零售商用来发现商品之间关联的关键技术之一。它通过寻找在交易中频繁出现的项目组合来工作。换句话说,它允许零售商识别人们购买的商品之间的关系。
该方法基于这样的理论,即购买某一商品的顾客更有可能购买另一特定商品)。
例如,买面包的人通常也会买黄油。零售店的营销团队应该瞄准购买面包和黄油的顾客,并向他们提供优惠,让他们购买第三样东西,如鸡蛋。

来源:爱德华卡
因此,如果顾客购买面包和黄油,看到鸡蛋打折或打折,他们就会被鼓励花更多的钱去买鸡蛋。这就是市场篮子分析的全部内容。
这只是一个小例子。因此,如果你把你的超级市场的 10000 或 20000 项数据带给一个数据科学家,想象一下你能得到多少洞见。这就是为什么关联规则挖掘如此重要。
现实生活应用

购物篮分析也可用于交叉销售产品。众所周知,亚马逊使用一种算法,根据你的浏览历史或其他人购买的东西,推荐你可能感兴趣的商品。
一个众所周知的城市传说是,一家超市,在运行商业部门蒲式耳检查后,发现男子可能会一起购买啤酒和尿布。Deals 通过将贮藏啤酒放在尿布旁边来扩大交易。
这听起来很简单(大多数时候确实如此)。尽管如此,纠结要知道:
- 对于巨大的库存(例如超过 10,000),这些东西的组合可能会爆炸成数十亿,这使得数学几乎是古怪的。
- 信息是定期从大量的交易记录中挖掘出来的。许多信息通常由特定的可测量程序处理
关联规则挖掘
关联规则挖掘主要用于当我们必须在给定的集合中找到对象之间的关联,或者在任何一条信息中找到一些隐藏的模式。
购物篮分析或购物篮数据分析在零售或聚类中是关联规则挖掘的一些应用。
处理这些例子最广泛使用的方法是市场篮子分析。这是零售领域许多大公司使用的一个关键系统,如亚马逊、Flipkart 等,通过识别用户放入其“购物容器”中的各种东西之间的关系来细分用户的购买行为。这些从属关系的揭示可以帮助零售商通过获取知识来创建广告程序,这些知识是客户尽可能经常一起获取的。这些方法可以包括:
- 根据趋势改变商店布局
- 网上商店的交叉营销
- 顾客购买的流行商品是什么
- 带附加销售的定制电子邮件
- 客户行为分析
- 目录设计
注:关于购物篮分析和推荐系统的相似性,大家心里都有很多困惑
联想和推荐的区别
正如已经讨论过的,关联规则对个人的偏好不起作用。它总是发现每笔交易的一些元素集之间的关系。这使得它们与被称为协作过滤的推荐系统方法完全不同。
如果你想了解一下推荐系统,可以去看看我之前的博客推荐引擎。
示例:
为了更好地理解它,请看下面来自 Amazon.com 的快照。你会注意到在每个产品的信息页面上有两个标题“经常一起购买”和“购买该商品的顾客也购买了”。
经常一起买→买了这件物品的协会客户也买了→推荐

这就是关联规则和推荐之间的区别。
现在,我们来谈谈主要的联想机器学习算法之一。即。 Apriori 算法
Apriori 算法
假设我们有一个包含集合{Banana,菠萝,芒果}的事务,也包含另一个集合{Banana,芒果}。所以,根据先验原理,如果{香蕉,菠萝,芒果}是频繁的,那么{香蕉,芒果}也一定是频繁的。

我们有一个由一些交易组成的数据集。
0 ->缺少项目
1->项目的存在
为了从这个小型企业场景的多个可能规则中找出有趣的规则,我们将使用以下矩阵:
支持度:支持度是一个物品的受欢迎程度(出现的频率)。它可以通过包含该项目的交易数量占交易总数的比例来计算。所以,如果我们想计算香蕉的支持度,这里是:
支持(香蕉)=(涉及葡萄的交易)/(总交易)
支持度(香蕉)= 0.666
置信度:如果 A 项发生,B 项发生的可能性(条件概率)。
置信度(A => B) =(涉及 A 和 B 的事务)/(仅涉及 A 的事务)
信心({香蕉,菠萝} = > {芒果}) =支持(香蕉,菠萝,芒果)/支持(香蕉,菠萝)
= 2/6 / 3/6
= 0.667
提升:如果 A 项出现,B 项出现的几率增加。
升力(A => B) =信心(A,B) /支持(B)
lift({香蕉,菠萝} = > {芒果}) = 1
因此,客户同时购买 A 和 B 的可能性是单独购买的机会的“提升价值”倍。
- Lift (A= > B) = 1 表示项目集合内没有相关性。
- Lift (A = > B)
- Lift (A = > B) < 1 表示项目集内部存在负相关,即项目集中的产品, A ,和 B 不太可能一起购买。
履行
你可以从这里得到数据。
该数据集包含一家商店的各种产品的交易数据。
在导入库之前安装 apyori 包
conda install --yes apyori
OR
pip3 install --yes apyori
导入包
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from apyori import apriori
我们已经导入了所有必需的库:
- NumPy 和熊猫用于基本操作
- 用于数据可视化的 Matplotlib
- apyori 用于我们的数据建模
导入数据
store_data = pd.read_csv("store_data.csv",header = None)
我们已经使用 pandas 将数据集读入名为“store_data”的数据框中。现在让我们看看数据
store_data.head()

所以,这是我们数据的样子,它包含了各种产品的所有交易历史。
store_data.shape

7501 表示不同物品一起购买的交易总数。20 表示显示项目的列数
数据预处理
因为 Apriori 库要求我们的数据集是列表的列表形式。因此,整个数据集是一个大列表,数据集中的每个事务都是外部大列表中的内部列表。[[交易 1],[交易 2],。。[交易 7501] ]
让我们将熊猫的数据框转换成如下的列表列表:
records = []
for i in range(0,7501):
records.append([str(store_data.values[i,j]) for j in range(0,20)])
让我们看看这些事务集:
for sets in records:
print(sets)

Apriori 算法
先验的参数:
- 记录:列表列表
- min_support :选择支持值大于参数指定值的项目的概率值
- min_confidence :过滤置信度大于指定阈值的规则的概率值
- min_lift :入围规则列表的最小提升值
- min_length :您希望在规则中包含的最小项目数
association_rules = apriori(records, min_support = 0.0055, min_confidence = .3, min_lift = 3, min_length = 2)
将上述规则转换为规则列表:
association_results = list(association_rules)
现在让我们看看我们的算法生成了多少规则:
print(len(association_results))

因此,我们总共有 18 条规则,这些规则比我们预期的有更高的支持、信心和提升。让我们看看一些规则
print(association_results[5])

我们可以看到,规则 5 包含(意大利面条、碎牛肉、冷冻蔬菜)之间有很好的关联。
显示规则列表
for item in association_results:
pair = item[0]
items = [x for x in pair]
print("Rule :"+ str(items[0]) + "->" + str(items[1]))
print("Support : {}".format(item[1]))
print("Confidence : {}".format(item[2][0][2]))
print("List : {}".format(item[2][0][3]))
print("\n-------------------------------------------------\n")

所以,这是关于如何实现 apriori 算法,在我们的事务集中找到关联性。
保持曲调,快乐学习🙂
最初发布在 Knoldus 博客上:https://blog . knold us . com/machinex-demystifying-market-basket-analysis/
关注 MachineX Intelligence 了解更多信息:
参考
揭开数据可观察性的神秘面纱
3 个关于如何开始使用数据工程堆栈最新层的实例

随着公司接收越来越多的数据,数据管道变得越来越复杂,出错的机会也在增加,表现在从破损的仪表板到空值的一切事物中。
以下是您的数据工程团队可能受益于 数据可观察性 (现代数据堆栈的最新层)的 3 个迹象。
一位客户最近问我:“我如何知道我的数据是否可信?”
当我在 Gainsight 担任客户成功副总裁时,这个问题出现了很多次。我工作过的每一个数据组织都是不同的,有他们自己的服务水平协议(SLA)、安全需求和“准确、高质量的数据”的 KPI。然而,在所有这些数据团队之间,出现了一个共同的主题:需要一种更好的方法来监控数据的可靠性并消除数据停机。
数据停机时间是指数据丢失、不准确或出现其他错误的时间段,其范围可以从数据表中的几个丢失值到数据转换过程中的一个失误。随着公司越来越多地利用越来越多的数据源并构建越来越复杂的数据管道,数据宕机的可能性只会增加。
我记得自己在想:如果有一种方法可以让数据团队监控这些不一致并发出警报,就像软件工程师可以通过 New Relic 和 Data Dog 这样的可观察性解决方案来跟踪应用程序停机时间一样,这不是很好吗?
五年前,还没有足够全面的词汇或方法来满足这种不断变化的需求。2020 年,我们终于到了:世界,遇见数据可观测性。
在以前的文章中,我已经讨论了为什么数据可观察性是信任你的数据的基础(换句话说,数据可靠性),但是它看起来像什么呢?
以下是您的数据团队应该投资于数据可观察性的 3 个迹象:
1.有人更改了上游的字段,导致下游数据丢失或部分丢失

端到端数据可靠性平台允许团队探索和了解他们的数据谱系,自动映射上游和下游依赖关系,以及这些资产的健康状况。图片由巴尔·摩西提供。
情况
这是斯蒂芬妮。她是数据科学家。Stephanie 负责建立一个数据集的模型,该数据集是关于她公司的需求生成营销活动的成功的。一天,广告团队的成员 Ken 更改了数据集中的一个字段,导致她最近的 A/B 测试生成了不可靠的结果。不幸的是,斯蒂芬妮无法知道为什么她的结果是错误的,她没有在公司的下一次数据科学全体会议上自豪地展示她的实验结果,而是放弃了实验,从头开始。
解决办法
数据可观察性解决了对数据管道的上游和下游依赖关系缺乏端到端可见性的问题,因此您可以识别数据防火练习发生的位置并快速解决它们。即使当管道破裂和 A/B 测试出错时,您也可以找出错误的根本原因并相应地更新您的实验,从而增强对数据的信任并降低计算成本。
#2:您的 Looker 仪表盘已有 24 小时未更新

数据目录将关于数据资产的所有元数据都放在单一窗口中,因此您可以在单一视图中看到沿袭、模式、历史更改、新鲜度、容量、用户、查询等。图片由巴尔·摩西提供。
情况
在 Stephanie 的公司,营销分析团队使用 Looker 来直观显示纽约时代广场的新广告牌每天会产生多少销售合格线索。在他们的首席执行官和营销副总裁召开第四季度计划会议的前几分钟,他们在 Slack 上 pings Stephanie:“数据都是错的……发生了什么事?!"
她打开 Looker,发现这些通常每 15 分钟更新一次的数字已经 24 小时没动过了!
解决办法
一种良好的数据可观察性方法提供了基于 ML 的新鲜度问题检测,并监控数据的异常情况,实时向您发出警报。一个优秀的数据可观察性策略将完成所有这些工作,并为您的数据健康状况提供一个单一的控制台视图,跨各种数据源对您的元数据进行编目。此外,自动检测减少了人工劳动,并腾出时间来从事将真正为您的公司推动发展的项目。
#3:数据分析师、数据科学家和数据工程师之间的沟通不畅导致了数据消防演习

数据可观察性有助于数据团队之间更好地协作,因为它可以在问题出现时轻松识别和解决问题,而不是花上几个小时。图片由巴尔·摩西提供。
情况
斯蒂芬妮的团队正在建立一个新的数据模型,以更好地了解哪种类型的潜在客户对她公司的产品最感兴趣,并根据地理区域和行业部门进行筛选。这是数据分析师、数据科学家和数据工程师之间的跨团队合作,结果很重要。
当 Stephanie 部署模型时,什么也没有发生。她又试了一次。再一次。还是不行。她不知道的是,芝加哥的一位数据科学家对一个数据集做了一个模式改变,永远改变了她所知道的模型。没有办法知道更新了什么数据,哪里发生了中断,更不用说如何修复它了!
解决办法
一种强大的数据可观察性方法将使团队能够协作地对数据停机事件进行分类和故障排除,使您能够确定问题的根本原因并快速解决问题。也许最重要的是,这种解决方案通过公开有关您的数据资产的丰富信息,从一开始就防止了数据停机事件的发生,以便能够负责任地、主动地进行更改和修改。
虽然数据停机时间因公司(和团队)而异,但数据可观察性会有所帮助。也许你甚至在斯蒂芬妮身上看到了自己,也有一些你自己的好的坏数据的故事来分享!
我洗耳恭听。
对学习更感兴趣?联系 巴尔摩西 并查看我的 数据可观察性办公时间 美国东部时间 11 月 12 日星期四中午 12 点/太平洋标准时间上午 9 点!
揭秘决策树、随机森林和梯度推进
深入探究这些常用算法的数学直觉

分类和回归问题都可以通过许多不同的算法来解决。对于数据科学家来说,了解这些预测算法的优缺点以选择一种适合所遇到问题的算法是至关重要的。在这篇博客中,我将首先深入研究最基本的算法之一(决策树),以便能够解释更强大的基于树的算法背后的直觉,这些算法使用技术来对抗这些简单决策树的缺点。基于树的算法优于线性或逻辑回归,因为它们能够捕捉数据集中可能存在的非线性关系。与诸如(深度)神经网络之类的更复杂的算法相比,随机森林和梯度提升易于实现,具有相对较少的要调整的参数,并且在计算资源方面更便宜,并且(通常)需要更少的数据集。理解这些直觉的主要目标是,通过掌握直觉,在实践中使用和优化算法将变得更容易,并最终产生更好的性能。
决策树
决策树是一种简单的算法,本质上模仿了流程图,使其易于理解。一棵树由根节点、几个树节点和树叶组成。基本上每个节点(包括根节点)都将数据集分成子集。每一个分裂都类似于一个基本的特征-特定的问题:某个条件存在还是不存在?回答所有这些问题,直到到达树的底层,产生当前样本的预测。底层的叶子是决策树的最后一步,代表预测的结果。

简单决策树的示意图
到目前为止,一切顺利:但现在有趣的部分来了。让我们从分类树开始,假设我们有一个样本数据集,其中包含关于气短、咳嗽和发烧的特征,我们希望预测患者是否患有流感。我们如何确定哪个特征应该是根节点,以及如何构建我们的树来最大化预测的准确性?

抽样资料
注意:这个例子将只使用分类特征,然而,树的一个主要优点是它们在数据类型方面的灵活性。
使用训练集从上到下构建决策树,并且在每一层,选择相对于目标变量最好地分割训练数据的特征。为了确定哪个特征分割数据集“最好”,可以使用几个指标。这些度量评估在节点中选择某个特征时出现的子集的同质性。最常用的指标是、【基尼杂质】、信息增益熵。这些指标通常会产生类似的结果【1】,由于计算基尼系数不包括对数的使用,因此可能会稍微快一些。计算基尼系数杂质的目的是测量从集合中随机选择的元素被错误标记的频率。
让我们从根开始注意:要选择哪些特征应该在决策树的顶部,首先将计算所有单个特征的基尼系数。
基尼系数的公式是

其中 c 是类别数,而 Pj 是以类别 j. 作为预测变量的项目的分数,具有 2 个类别(流感或无流感),对于每片叶子,杂质是1-(P-无流感)——(P-流感)。

在我们的例子(见上图)中气短的左叶的基尼杂质 为:1-(49/(49+129))-(129/(49+129))= 0.399。右叶杂质1-(94/(94+31))-(31/(94+31))= 0.372。
最后,根节气短的最终杂质可计算为两片叶子杂质的加权平均值:((49+129)/(49+129+94+31)) 0.399+((94+31)/(49+129+94+31))* 0.372 = 0.388。*
我们也可以对特征咳嗽和发烧这样做,它们分别产生 0.365 和 0.364 的杂质。
由于发热杂质最低,因此作为根节点是预测患者是否患流感的最佳特征。在根节点中选择 fever 作为特征后,数据被分成两个不纯的节点,左边是 144 个样本,右边是 159 个样本。

选择发热作为根节点特征后的数据集
随后,我们为这些创建的子集计算其他特征气短和咳嗽的杂质,以决定哪个特征应该用于下一个节点。这里的杂质为气短作为根节点后的下一个特征是 0.359。我们假设这个杂质小于咳。下一步是比较新添加的节点的杂质与单独在发烧上分裂后的左叶的杂质(原来是 0.395)。因此,将节点气短添加到树的左分支提供了比单独根据发热进行分割更好的分类,并且将被添加到树中。这个过程将继续,直到树中的所有特征都被使用,或者如果随后的分割没有产生杂质的改善。因此,树的左边和右边很可能有不同的架构。
回归树
回归树类似于分类树,因为这些树也是从上到下构建的,然而,为节点选择特征的度量是不同的。可以使用多种指标,但均方误差(MSE)是最常用的指标。

为了简单起见,假设我们有一个数据集,它有一个数字特征(一年中的一天,即 1 月 1 日,是第 1 天)和一个数字目标变量(医院中流感患者的数量),见右图。首先,我们必须确定应该对根节点使用哪种分割。这个过程可以分为几个(迭代)步骤:
1)在两个连续点之间画一条线,将数据分成两个子集(橙色线)。
2)计算这两个点的流感患者的平均数量,并通过该计算的平均值(绿线)画一条水平线
3)计算两个创建的子集的所有数据点的均方误差(灰色虚线)
4)对两个连续点之间的每条可能的线重复步骤 1 至 3。
在根节点中选择具有最低 MSE 的分裂。该根节点将数据分成两个子集,并且对两个创建的子集重复该过程。注意:在具有多个要素的真实数据集内,会计算数据集中所有要素的所有可能分割的 MSE,并在节点中选择 MSE 最低的分割。可以重复这个过程,直到所有点都在单独的叶子中,这将为您的训练数据提供完美的预测,但是对于新的(测试)数据就不那么准确了(换句话说;模型过拟合)。通常通过例如设置分裂所需的最小样本数来避免过拟合。如果多个观察结果出现在一个叶中,则预测值是该叶中所有观察结果的平均值(在我们的示例中是该叶中所有观察结果的平均流感患者)。
装袋增压
模型的准确性是偏差和方差之间的权衡。树很容易构建、解释和使用,然而树有一个方面阻止它们成为预测学习的理想工具,即不准确性【2】。树可以准确地对训练数据集进行分类,但不能很好地推广到新数据集。在接下来的部分中,我将讨论两种基于决策树的算法,并使用不同的方法来提高决策树的准确性:基于 bagging 的随机森林和顾名思义使用 boosting 技术的梯度增强。Bagging 和 boosting 都是集成技术,这基本上意味着这两种方法都将多个弱学习器组合在一起,以创建一个比单个学习器误差更低的模型。这两种方法之间最明显的区别是 bagging 同时并独立地建立所有弱学习器,而 boosting 随后建立模型,并使用先前建立的模型的信息来提高准确性。
注意:bagging 和 boosting 可以使用几种算法作为基础算法,因此并不局限于使用决策树。
随机森林
如前所述,随机森林是一种同时构建决策树的打包(或引导聚集)方法。随后,它将各个生长树木的预测进行组合,以提供最终预测。随机森林可用于回归和分类问题。
首先,必须确定所需的树的数量。所有这些树都是同时生长的。为了防止树是相同的,使用了两种方法。
步骤 1: 首先,为每棵树创建一个自举数据集。这意味着从原始数据中随机选取样本(行)用于自举数据集。对于单个引导数据集,可以多次选择样本(见下图)。

左侧为原始数据集,右侧为引导数据集
步骤 2: 对于每个自举数据集,生成一个决策树。但是对于构建过程中的每一步,只使用了(预定数量的)随机选择的特征(在我们的例子中是 2 )(通常是特征数量的平方根)。例如,为了定义哪个特征应该在根节点中,我们随机选择 2 个特征,计算这些特征的杂质,并选择杂质最少的特征。对于下一步,我们随机选择 2 个其他要素(在我们的示例中,选择根节点后只剩下 2 个要素,但在较大的数据集中,您将在每一步选择 2 个新要素)。类似于构建单个决策树,这些树一直生长,直到杂质不再增加(或者直到预定义的最大深度)。在随机森林中,构建深树并不自动意味着过度拟合,因为最终预测是基于所有组合树的平均预测(或多数投票)的事实。可以使用几种技术来调整随机森林(例如,最小杂质减少或一片叶子中必须有的最小样本数),但我不会在这篇博客中讨论这些方法的效果。
作为引导和随机特征选择的结果,不同的树将具有不同的架构。

用随机森林算法构建的两个具有不同架构的树
随机森林现在可以用来预测新的例子。组合随机森林中所有单个树的预测,并且(在分类问题的情况下)具有最多预测的类是最终预测。
梯度增强
梯度推进是最流行的机器学习算法之一。虽然通过使用 scikit-learn 等库很容易实现开箱即用,但理解数学细节可以简化调整算法的过程,并最终获得更好的结果。boosting 的主要思想是随后构建弱预测器,并使用先前构建的预测器的信息来增强模型的性能。对于梯度推进,这些预测器是决策树。与随机森林相比,在梯度提升中使用的决策树的深度通常要小得多。sci kit-learn RandomForestRegressor 中的标准树深度未设置,而在 GradientBoostingRegressor 中,树的标准修剪深度为 3。这很重要,因为单个树很容易过度拟合数据,而随机森林通过平均所有单个树的预测来解决这个问题,梯度增强建立在先前构建的树的结果上。因此,单个过度拟合的树在梯度增强中可以有很大的效果。由于深度较小,因此在梯度增强过程中构建的单个树可能会有较大的偏差。
在下一节中,我将对使用梯度推进解决回归问题进行数学上的深入探讨,但是它也可以用于分类。用于分类的梯度推进将不在本博客中讨论,但是直觉与用于回归的梯度推进有很多共同之处。如果你想更深入地研究梯度增强进行分类,我推荐你观看 stat quest(https://www.youtube.com/watch?v=jxuNLH5dXCs)的优秀视频。
让我们来看一个例子,其中我们想要使用身高、体重以及患者是否处于禁食状态来预测患者的血糖。

样本数据集
梯度增强使用损失函数来优化算法,scikit-learn 实现中一次观察的标准损失函数是最小二乘 : 1/2 *(观察值-预测值)
拟合梯度推进回归方程的过程可以分为几个步骤。
第一步。回归的梯度推进的第一步是使用以下公式进行初始预测

换句话说,找出误差平方和最低的 γ 的值。这可以通过梯度下降来解决,以找到公式的导数等于 0 的位置。通过使用链式法则,我们知道

等于

对于我们的样本数据,这意味着我们可以通过求解-(5.1-predicted)+-(9.3-predicted)+⋯+-(7.0-预测)=0 来找到最佳的初始预测。这产生了*6 预测=35.4 ,因此最佳初始预测是 35.4/6=5.9 毫摩尔/升。N 注意,这只是目标变量列的平均值。
第二步。如前所述,梯度提升使用之前构建的学习器来进一步优化算法。因此,梯度提升中的树不适合目标变量,而是适合预测值和观察值之间的误差或差异。下一步是使用以下公式计算每个样本的误差:

其中 m 是当前的树(记住我们随后正在构建预定义数量的树),而 n 是样本的数量。这看起来很有挑战性,但实际上并不是。第一部分

它是损失函数相对于预测值的导数。正如我们在步骤 1 中看到的,使用链式法则,这只是–(观察值—预测值),t 初始方程前面的大减号让我们以观察值减去预测值结束。
下标

表示先前树的值用于预测当前树的错误。简而言之,样本的误差是观察值和前一个树的预测值之间的差异。
在下表中,添加了用于构建第一个树的所有样本的误差,这只是预测所有样本的平均血糖。

第一次预测后包含错误的样本数据集

预测样本误差的决策树
第三步。下一步是用预定义的错误最大深度而不是目标变量来拟合决策树。通过修剪树(或设置最大叶子数),一些叶子将以多个错误结束。右边是一个适合错误的树。树叶用 Rj,m 表示,其中 j 是树叶编号, m 是当前树。由于样本数据集很小,树叶 R(1,1) 、 R(3,1) & R(4,1) 都只包含一个样本。 R(2,1) 包括误差为-1.1、-0.8 和-0.8 的三个样本。
第四步。确定每片叶子的输出值。这可以通过我们在步骤 1 中使用的类似公式来完成,

主要区别在于,我们为树 m,中的每片叶子 j 计算最佳预测 γ ,而不是为整个数据集计算一个预测值。此外,为了计算某一叶的最佳预测值,只考虑该叶中的样本:

最后一个区别是,前一棵树的预测使用了一个附加项 γ:

由于损失函数的选择,每片叶子的最佳预测值是该叶子中误差的平均值。对于叶 R(2,1) ,最佳预测值为-0.9(误差的平均值[-1.1,-0.8,-0.8])。
第五步。使用初始预测和所有构建的树对所有样本进行新的预测,使用

,在哪里

是对样本在当前树中的叶子的预测,而 α 是预定义的学习率。设置学习率可以减少单个树对最终预测的影响,并提高准确性。简单地说,用来自当前构建的树的新预测误差来更新对样本的先前预测。为了说明这一点,我们将使用初始预测和学习率为 0.1 的第一个构建的树来预测第一个样本。在我们新构建的树中,这个样本将以-0.9 的预测值出现在第二个叶子中。

。虽然与初始预测的差异很小,但新的预测更接近观察到的血糖。

一个样本包括建立第二棵树后的预测值和误差
第六步。重复步骤 2、3 和 4,直到构建了所需数量的树,或者添加新树并不能提高拟合度。结果是一个梯度推进模型😊。
这篇博客概述了决策树、随机森林和梯度推进背后的基本直觉。如果您使用 scikit-learn 这样的库来实现这些算法,希望这将为您提供一个很好的理解,并帮助您在未来调整模型的参数,并从长远来看获得更高的精度。
关于作者
Rik Kraan 是医学博士,在荷兰数据科学咨询公司 Vantage AI 担任数据科学家。请随时通过rik.kraan@vantage-ai.com联系
【1】基尼指数与信息增益准则的理论比较。劳拉·伊莲娜·雷莱亚努和基利安·斯托菲尔。T4【https://www . unine . ch/files/live/sites/imi/files/shared/documents/papers/Gini _ index _ full text . pdf
【2】统计学习的要素:数据挖掘、推理和预测。特雷弗·哈斯蒂、罗伯特·蒂布拉尼和杰罗姆·弗里德曼。
揭秘甘斯
了解这些迷人的模型如何工作以及为什么工作,以及如何使用 Keras 和 Tensorflow 训练自己的模型。
本文的目的是说明生成对抗网络(GANs)的结构和训练方法,强调 GANs 背后的关键思想,并通过一个工作示例来阐明主题,使用 Tensorflow 和 Keras 在 MNIST 数据集上训练 GAN 以产生手写数字。然后,我们将探索增加发电机输出控制水平的方法。
当我最近开始寻找训练 GANs 的教程时,我发现了许多过于复杂的脚本,这些脚本对训练过程中幕后发生的事情提供了很少的直觉。我希望读者能够清楚地理解为什么这里提供的代码有效,并欣赏它的简单性。熟悉 Keras functional API 以及一些深度学习的一般知识将会很有用。
GAN 概述
首先,让我们讨论一下我们希望在本教程中完成什么。GAN 由两个独立的神经网络组成,一个发生器和一个鉴别器。这两个网络可以有任何你愿意想象的结构,这取决于手头的任务。
生成器的目标是在给定一些随机输入(通常是从标准正态分布中抽取的 100 个数字)的情况下,生成看起来属于任何给定数据集的对象。例如,我们将在本教程中考虑 MNIST 数据集。这个数据集由 28 x 28 个数组组成(这使它成为一个 784 维的数据集),每个数组代表一个手写数字 0-9 的图像。每一类数字都可以被认为是 784 维空间中的一个流形,当且仅当一个图像可以被人类识别为相应的数字时,它才会出现在每个流形上。因此,一个好的生成器必须善于将随机输入映射到这些流形上,这样它只会生成看起来像是属于真实数据集的图像。
第二个网络,即鉴别器,具有相反的目的。它必须学会区分数据集的真实例子和生成器制造的‘假货’。组合结构如下:

作者图片
名字中的“对抗”部分指的是训练 GANs 的方法。在训练中,他们(作为对手)竞争,每个人都试图击败对方。对每批数据交替训练网络。首先,将训练鉴别器将真实数据分类为“真实”,将生成器创建的虚假图像分类为“虚假”。接下来,生成器将被训练产生被鉴别器分类为“真实”的输出。对数据中的每个批次重复这一过程。这确实是一个简单的想法,但却是一个强有力的想法。
有趣的是,生成器将永远看不到任何真实数据,它将简单地学习如何通过反向传播算法学习通过鉴别器传播的梯度来欺骗鉴别器。因此,gan 特别容易受到梯度消失问题的影响。毕竟,如果梯度在到达发生器之前就消失了,它就没有办法学习了!当使用非常深的 GANs 时,这一点特别重要,但我们在这里不应该担心,因为我们使用的网络相对较小。
另一个常见的问题是“模式崩溃”。在某种程度上,这是发电机为了偷懒而开始跳出框框思考的地方。生成器可以简单地学习生成完全相同的输出,而不管输入是什么!如果这个输出对鉴别器来说是可信的,那么生成器已经完成了它的任务,尽管对我们来说是完全无用的。
我们将在本教程中考虑克服模式崩溃的问题,但首先我们将考虑一个非常简单的模型,以便专注于理解训练算法。事不宜迟,我们开始吧。
用 Keras 建立模型
在整个代码中使用了一些参数,为了清楚起见,这里给出了这些参数。
引入一些变量。
我们将使用 tensorflow_datasets 模块提供的 MNIST 数据集。必须加载数据,并将像素值调整到-1 和 1 之间的范围,这是发生器最后一层将使用的双曲正切函数的范围。然后根据 BATCH_SIZE 和 BUFFER_SIZE 参数对数据进行混洗和批处理。我们使用大小为 60,000(数据集长度)的缓冲区,以便完全打乱数据,并使用大小为 128 的批处理。prefetch(1)调用意味着当一批数据用于训练网络时,下一批数据将被加载到内存中,这有助于防止瓶颈。这对于 MNIST 来说可能不是问题,因为每个图像的数据相对较少,但是对于高分辨率图像来说可能会有所不同。
加载、缩放、混排、批处理和获取数据集。
MNIST 的简单性将允许我们抓住具有简单致密结构的 gan。我们将使用一个具有 3 个密集隐藏层的生成器和鉴别器。由于我们需要生成 28 x 28 的图像,最终的图层将有 784 个单元,然后可以将它们重新调整为所需的格式。其他参数可以使用。我们还将在最后一层使用标准的 tanh 激活,为了简单起见,其他层都使用 ReLu 激活。
函数创建一个生成器。
鉴别器是发生器的镜像。这在直觉上是有意义的,因为它试图撤销生成器所做的事情。它将预测“真实”为 1,“虚假”为 0,因此在最后一层使用 sigmoid 激活。我们再次在其他层中使用 ReLu。
函数创建一个鉴别器。
现在,这两个网络可以组合成一个 GAN,就像它们只是层一样。就这么简单!
函数从鉴频器和发生器创建 GAN。
用 Keras 训练 GAN
如前所述,不能使用 Keras 中用于更简单的深度学习模型的 model.fit()方法来训练 gan。这是因为我们有两个不同的网络,必须同时训练,但目标相反。因此,我们必须创建自己的训练循环来迭代批量数据,并分别训练每个模型。以下代码中有一些微妙之处,所以我鼓励读者仔细阅读注释,但要点如下:
- (10–12)鉴别器和 GAN 必须分开编译,我们在编译 GAN 时使鉴别器不可训练。这就允许我们通过调用 gan.train_on_batch()来训练 only 发电机,并且在调用 discriminator.train_on_batch()时训练 only鉴别器。这是 Keras 的一个便利特性,通常被忽略,导致代码不够优雅。
- (25–35)我们训练鉴别器将“真实”图像映射到 1,将“虚假”图像映射到 0。软化这些值,即使用接近 1 和 0 的随机数,是帮助 GANs 学习的标准技巧。
- (40–47)我们通过训练 GAN(鉴别器的权重不可训练)来训练生成器,但是标签被颠倒,也就是将“假”图像映射到 1。这样,我们要求生成器学习如何欺骗鉴别器。
为多个时期创建和训练 GAN 的功能。
通过 100 个时期的训练,我们观察到以下收敛。虽然我们在整个训练中看到不同的数字出现,但它似乎主要停留在 1 号图上,这可能是模式崩溃的一个例子。这是生成器学习从数据集中生成一个类的地方。如果让它训练更长时间,鉴别器可能会学习将该类分类为假的,此时生成器将学习生成另一个类,以此循环继续。由于我们没有努力防止这种行为,我相信我们可以把这个结果算作一个成功,我们显然有一个用于这类神经网络的工作训练方法。

作者提供的图片
提高我们模型的性能—增加功能
虽然这第一次尝试在一定程度上取得了成功,但我们当然可以做得更好。毕竟,我们只使用了数据集的一半!我们忽略了利用现有的标签。只需对上面的代码做一些调整,我们就可以创建一个使用标记数据的 GAN,这样生成器将从我们选择的给定类中产生一个数字。就像生成随机数一样有趣,控制生成的图像会给我们的模型增加一层美丽的精致。这也将有助于 GAN 更快地学习,并有助于防止模式崩溃。该模型的新结构如下:

作者图片
生成器必须像以前一样接受随机噪声作为输入,但也接受它应该生成的随机选择的类。这意味着,一旦经过训练,生成器将从我们选择的任何类中产生一个数字。鉴别器还将接受两个输入,第一个是图像,第二个是相应的类标签。这将允许鉴别器不仅根据图像作为数字的可信度,而且根据数字是否属于给定的类来决定图像是真是假,这将迫使生成器从正确的类中绘制图像,以便执行良好。我们只需要对代码做一些非常简单的调整。
首先,我们需要一个变量来告诉我们数据中有多少特征。因为我们将对标签进行一次性编码,所以每个标签将是一个长度为 10 的向量。我们还必须创建带标签的数据集。
声明新变量和创建新数据集。
下面是我们看到的使用 Keras functional API 与顺序 API 相比的优势。在这个框架中添加多个输入并连接它们是一件小事,如下所示:
创建具有新功能的生成器的函数。
鉴别器也做了类似的调整,在将类标签输入到模型中之后,添加了另一个隐藏层。额外的层是必要的,好像直接连接到输出神经元的级联层鉴别器将缺乏处理由类标签给出的信息的灵活性。
用新特性创建鉴别器的函数。
像以前一样直观地创建 GAN。
创建具有新功能的 GAN 的函数。
最后,培训与之前的想法完全相同,但是增加了额外的输入。由于我们生成数据集的方式,代码看起来非常相似。
创建和训练具有新功能的 GAN 的功能。
这个模型然后像以前一样被训练 100 个时期,进度显示在这里。发生器应该产生一个完整的数字序列,0-9。看来我们又取得了更多的成功!除了数字 9,在训练结束时,我们有一个令人信服的数字序列。

作者提供的图片
探索特征映射
我们也能够观察到甘斯的一个迷人的特征。他们实际上学会了将某些随机输入编码为他们生成的数据的特征。通过一个例子可以很好地看出这一点:

作者图片
每一列中的图像是从相同的随机输入中生成的,但是具有不同的类别标签。很明显,随机输入中编码的是结果数字的特征。例如,在第五列中,所有笔画都很细,而第八列中的所有数字都有粗线笔画。类似地,第 2 列中的所有数字看起来都向右倾斜,而第 3 列中的数字稍微向左倾斜。虽然这些编码对于任何试图解释它们的人来说都是不清楚的,但是通过研究生成器对随机输入样本的行为,可以在一定程度上控制生成的数字的风格。
平均特征
为了演示这一点,我检查了大量输入的生成器输出,并根据生成器产生的输出类型对输入进行了分类。我考虑的类别是“粗笔画,直的”,“粗笔画,向右倾斜”,“细笔画,直的”和“细笔画,向右倾斜”。然后对每个类别进行平均,因此我有四个输入向量,每个类别一个。当这些输入通过生成器时,它们从该类别中产生新的图像,如下所示。在这里,我显示的是 1、4 和 8,因为这些数字显示了最夸张的倾斜。

图片由作者提供;(从左到右)粗直、粗右、细直、细右
缩放功能
我们实际上可以做得更好!如果我们将这些输入乘以一个大于 1 的数,我们可以夸大那个输入的特征,如果我们使用一个小于 1 的数,我们可以减少那个特征。事实上,似乎如果我们乘以负数,我们可以生成具有相反特征的数字!请看下面的 gif——它们代表了当每个类别的输入乘以范围在 2 到-2 之间的标量时,我们的生成器的输出。看看他们是如何以上述夸张的特征开始,以相反的方式结束的!

作者提供的图片;(从左到右)粗直、粗右、细直、细右
我们在这里看到的是 GANs 的一个共同特征。虽然输入可能是随机的,但生成器对它们的解释绝不是随机的。它已经学会使用潜在空间中的某些向量来表示它所绘制的特征。
添加和减去特征
你甚至可以在这个潜在空间里进行有意义的加减运算。如果将粗而直的数字输入添加到细而斜的数字输入中,您会得到什么结果?

作者图片
你得到一个粗斜的数字输入!从粗斜的数字输入中减去粗直的数字输入又如何呢?

作者图片
你得到一个细的,倾斜的数字输入!多酷啊。如果有时间和资源,可以对 GAN 的输出进行更全面的分类,并且可以使用这种方法获得对输出的绝对控制。
将来,我的目标是应用本文中的原则在更复杂的数据集上训练 gan,并探索我获得的特征映射。我使用过的完整代码可以在这个 Github 资源库中找到:
在 GitHub 上创建一个帐户,为 Vonny0123/GAN_Tutorials 开发做贡献。
github.com](https://github.com/Vonny0123/GAN_Tutorials.git)
揭秘插值搜索
搜索算法指南
升级你的搜索游戏!
在这篇文章之前,我已经写过关于二分搜索法的文章。没看过就去看看吧。在本文中,我们将讨论插值搜索,当排序数组中的值均匀分布时,插值搜索是二分搜索法的一种改进。

你可能还记得,二分搜索法已经以 O(log n)时间复杂度运行了。还能有其他表现更好的方法吗?嗯……部分是的。我们将很快深入研究它。
什么是插值搜索?
插值搜索是另一种有效的搜索技术。在阵列元素均匀分布的情况下,这种方法可以超过二分搜索法。插值搜索估计键值在数组中的位置。这可以通过考虑数组中最小和最大的元素以及数组的长度来实现。
它基于这样的想法:如果键值越大(越接近最大的元素),它的位置很可能位于数组的末尾。同样的事情也适用于较小值的键。
它是如何工作的?
进行插值搜索有 6 个主要步骤,分别是:
- 估计数组的中间位置,并将该元素与所需的键进行比较。
- 如果键匹配中间的元素,则返回中间的位置。
- 如果该键小于中间的元素,则该键只能位于左侧子阵列中。聚焦于左侧子阵列
- 否则,我们只将焦点移到右边的子阵列。
- 重复步骤 1、2、3 和 4,直到找到所需的键或检查完每个子阵列。
- 如果数组中没有匹配项,则返回-1
插值搜索示例
像往常一样,在我们转到用不同的编程语言实现之前,将首先提供伪代码。
插值搜索伪码
现在,我们将转移到 3 种不同语言的真实代码,Python、C 和 JavaScript。
Python 中的插值搜索代码
C 语言中的插值搜索代码
JavaScript 中的插值搜索代码
插值搜索的时间复杂度
在较小的阵列中,插值搜索比二分搜索法慢。这背后的原因是插值搜索需要更多的计算。然而,更大的数组和均匀分布的数组是插值搜索的强项。与二分搜索法相比,插值搜索时间复杂度的增长率较小。
插值搜索的最佳情况发生在中间值(我们的近似值)是所需键的时候。这使得最佳情况下的时间复杂度为 O(1)。在最坏的情况下,我们需要遍历数组中的所有元素,导致 O(n)时间复杂度。好消息是对于一般情况,时间复杂度小至 O(log log n)。
结论
总之,学习如何应用插值搜索不仅会丰富你的算法知识,还会丰富你作为程序员的知识。毫无疑问,它将在您的编程工具包中占有一席之地。然而,应该永远记住:
- 类似于二分搜索法,插值搜索只适用于排序数组。
- 您需要直接访问数组的元素。
要成为一名专业的程序员没有简单的方法,唯一可行的途径就是坚持不懈地一个接一个地学习关键概念。所以,如果我能理解这些概念,你也能。
"取得成功的秘诀在于开始行动。"
——马克·吐温
我们一起登顶吧!
问候,
弧度克里斯诺
揭秘加入 Apache Spark

参赛:ixbay.com
SPARK 执行指南
本文专门讨论 Apache Spark 中的 Join 操作,让您对 Spark Join 技术的基础有一个总体的了解。
在典型的数据分析流程中,经常使用连接操作来关联两个数据集。Apache Spark 作为一个统一的分析引擎,也为执行各种各样的连接场景提供了坚实的基础。
在非常高的级别上,Join 对两个输入数据集进行操作,并且该操作通过将属于一个输入数据集的每个数据记录与属于另一个输入数据集的每个其他数据记录进行匹配来工作。在发现匹配或不匹配(根据给定的条件)时,连接操作可以从两个数据集或连接的记录中输出匹配的单个记录。连接的记录基本上表示来自两个数据集的匹配的单个记录的组合。
加入操作的重要方面:
现在让我们了解影响 Apache Spark 中 Join 操作执行的三个重要方面。这些是:
1)输入数据集的大小:输入数据集的大小直接影响连接操作的执行效率和可靠性。此外,输入数据集的相对大小会影响连接机制的选择,从而进一步影响连接机制的效率和可靠性。
2)连接条件:连接输入数据集所依据的条件或子句称为连接条件。该条件通常涉及属于输入数据集的属性之间的逻辑比较。根据连接条件,连接分为两大类,等价连接和非等价连接。
相等联接涉及一个相等条件或需要同时满足的多个相等条件。每个等式条件应用于来自两个输入数据集的属性之间。例如,(A.x == B.x)或((A.x == B.x)和(A.y == B.y))是参与连接操作的两个输入数据集 A 和 B 的 x,y 属性上相等连接条件的两个示例。
非相等联接不涉及相等条件。但是,它们可能允许多个等式条件不能同时满足。例如,(A.x < B.x)或((A.x == B.x)或(A.y == B.y))是参与连接操作的两个输入数据集 A 和 B 的 x,y 属性上的非相等连接条件的两个示例。
3)连接类型:在输入数据集的记录之间应用连接条件后,连接类型会影响连接操作的结果。以下是各种连接类型的大致分类:
内部连接:内部连接只输出输入数据集中匹配的连接记录(在连接条件下)。
外连接:外连接输出除匹配的连接记录外,还输出不匹配的记录。根据输出不匹配记录的输入数据集的选择,外部连接进一步分为左、右和全外部连接。
Semi Join : Semi Join 输出只属于两个输入数据集之一的单个记录,无论是匹配的还是不匹配的实例。如果属于某个输入数据集的记录在不匹配的实例上输出,半连接也称为反连接。
交叉连接:交叉连接通过将一个输入数据集中的每条记录与另一个输入数据集中的每条记录相结合,输出所有可能的连接记录。
基于连接执行的上述三个重要方面,Apache Spark 选择正确的机制来执行连接。
加入执行的各种机制
在理解了执行连接操作的各个方面之后,现在让我们来理解执行连接操作的各种机制。
Apache Spark 总共提供了五种机制来执行连接操作。这些是:
- 无序散列连接
- 广播散列连接
- 排序合并联接
- 笛卡尔连接
- 广播嵌套循环连接
广播散列连接:在“广播散列连接”机制中,两个输入数据集之一(参与连接)被广播给所有执行器。在来自广播数据集的所有执行器上构建哈希表,之后,非广播输入数据集的每个分区独立地连接到作为本地哈希表可用的其他数据集。
“广播散列连接”不涉及任何洗牌阶段,是最有效的。对其可靠性的唯一要求是执行器应该有足够的内存来容纳广播的数据集。因此,当两个输入数据集都大于可配置的阈值时,Spark 会避免这种机制。
Shuffle Hash Join: 在‘Shuffle Hash Join’机制中,首先,将两个输入数据集对齐到一个选择的输出分区方案(要了解更多关于选择的输出分区方案的信息,可以参考我最近出版的名为《Spark 分区指南》的书)。如果一个或两个输入数据集不符合所选的分区方案,则在实际连接之前会执行一个 shuffle 操作来实现一致性。
在确保两个输入数据集符合所选的输出分区后,Shuffle Hash 使用标准哈希连接方法对每个输出分区执行连接操作。这意味着,对于每个输出分区,首先从较小输入数据集的相应分区构建哈希表,然后将较大输入数据集的相应分区与构建的哈希表连接。
与“广播散列连接”相比,在“混洗散列连接”的情况下,对执行器的存储器要求相对较少。这是因为哈希表只建立在较小输入数据集的某个分区上。因此,如果您提供了大量的输出分区,并且您有大量的具有适当内存配置的执行器,那么您可以通过“混洗散列连接”来实现更高的连接操作效率。然而,如果 Spark 需要在一个或两个输入数据集上执行额外的混洗操作以符合输出分区,那么效率将低于“广播散列连接”。
排序合并连接:‘排序合并连接’的初始部分类似于‘混洗哈希连接’。这里,首先,两个输入数据集与选择的输出划分方案对齐。如果一个或两个输入数据集不符合所选的分区方案,则在实际连接之前会执行一个 shuffle 操作来实现一致性。
在确保两个输入数据集符合所选输出分区后,排序合并使用标准排序合并连接方法对每个输出分区执行连接操作。
与“混洗散列连接”和“广播散列连接”相比,“排序合并连接”的计算效率较低,但是,用于执行“排序合并连接”的执行器的内存需求明显低于“混洗散列”和“广播散列”。此外,类似于“混洗散列连接”,如果输入数据集不符合期望的输出划分,则一个或两个输入数据集的混洗操作,视情况而定,增加了“排序合并连接”执行的开销。
笛卡尔连接:笛卡尔连接专门用于执行两个输入数据集之间的交叉连接。输出分区的数量总是等于输入数据集的分区数量的乘积。每个输出分区映射到一对唯一的分区,每对分区由一个输入数据集的一个分区和另一个输入数据集的另一个分区组成。对于输出数据集的每个输出分区,通过对来自映射到输出分区的两个输入分区的数据进行笛卡尔乘积来计算数据。
笛卡尔连接的缺点导致输出分区数量激增。但是如果你需要交叉连接,笛卡尔是唯一的机制。
广播嵌套循环连接:在‘广播嵌套循环连接’中,输入数据集之一被广播给所有的执行器。此后,使用标准嵌套循环连接过程将非广播输入数据集的每个分区连接到广播数据集,以产生输出连接数据。
“广播嵌套循环连接”计算效率最低,因为执行嵌套循环是为了比较两个数据集。此外,它是内存密集型的,因为输入数据集之一需要广播给所有的执行器。
【Spark 如何选择加入机制?
在查看了连接操作的重要方面和连接执行的各种机制之后,现在让我们看看 Spark 是如何选择特定机制的:
Spark 基于以下因素选择执行连接操作的特定机制:
- 配置参数
- 加入提示
- 输入数据集的大小
- 连接类型
- 等价或非等价联接
Spark 在连接 API 中提供了灵活性,可以指定可选的连接提示来完成连接机制。诸如“广播”、“合并”、“混洗 _ 散列”和“混洗 _ 复制 _nl”的连接提示可以与参与连接的数据集一起提供。
以下是 Spark 如何根据上述因素选择各种连接机制的综合描述:
‘广播散列连接’
强制条件
- 仅适用于等同连接条件
- 不适用于“全外部”联接类型
除了强制条件之外,下列条件之一应成立:
- 在左侧输入数据集上提供了“广播”提示,连接类型为“右外”、“右半”或“内”。
- 未提供任何提示,但左侧输入数据集可根据配置'spark . SQL . autobroadcastjointhreshold(缺省 10 MB)' 进行广播,连接类型为“右外”、“右半”或“内”。
- 右侧输入数据集中提供了“广播”提示,连接类型为“左外”、“左半”或“内”。
- 没有提供任何提示,但是根据配置'spark . SQL . autobroadcastjointhreshold(缺省 10 MB)' ,右输入数据集是可广播的,并且联接类型是“左外”、“左半”或“内”。
- 在输入数据集和连接类型上提供的“广播”提示为“左外”、“左半”、“右外”、“右半”或“内”。
- 没有提供任何提示,但是两个输入数据集都是可根据配置'spark . SQL . autobroadcastjointhreshold(缺省 10mb)'【T1]进行广播的,并且联接类型是'左外'、'左半'、'右外'、'右半'或'内'。
‘洗牌哈希加入’
强制条件
- 仅适用于等同连接条件
- 不适用于“全外部”联接类型
- 配置'spark . SQL . join . prefersortmergejoin(默认为真)'被设置为假
除了强制条件之外,下列条件之一应成立:
- 在左侧输入数据集上提供了“shuffle_hash”提示,联接类型为“右外”、“右半”或“内”。
- 未提供任何提示,但左侧输入数据集比右侧输入数据集小得多,并且连接类型为“右外”、“右半”或“内”。
- 右输入数据集中提供了“shuffle_hash”提示,连接类型为“左外”、“左半”或“内”。
- 未提供任何提示,但右侧输入数据集比左侧数据集小得多,连接类型为“左外”、“左半”或“内”。
- 在输入数据集和连接类型上提供的“shuffle_hash”提示为“左外”、“左半”、“右外”、“右半”或“内”。
- 没有提供任何提示,但是两个数据集都相当小,并且联接类型为“左外”、“左半”、“右外”、“右半”或“内”。
‘排序合并连接’
强制条件
- 仅适用于等同连接条件
- 根据等价连接条件确定的连接键是可排序的
- 配置'spark . SQL . join . prefersortmergejoin(默认为真)'被设置为真
除强制条件外,下列条件之一应成立:
- 在任何输入数据集中提供了“merge”提示,并且联接类型可以是任何类型。
- 没有提供任何提示,联接类型可以是任意的。
‘笛卡尔连接’
强制条件
- 联接类型“内部”
除了强制条件之外,下列条件之一应成立:
- 在任何输入数据集中提供了“shuffle_replicate_nl”提示,连接条件可以是相等的或非相等的。
- 未提供任何提示,联接条件可以是相等的或非相等的。
“广播嵌套循环连接”
“广播嵌套循环连接”是默认的连接机制,当没有其他机制可以选择时,则选择“广播嵌套循环连接”作为最终机制,以针对任何连接条件执行任何连接类型。
如果有一个以上的连接机制适合执行,则按照“广播散列连接”优先于“排序合并连接”优先于“混洗散列连接”优先于“笛卡尔连接”的顺序选择优选的连接机制。
在笛卡尔连接和广播嵌套循环连接中,当输入数据集之一可以广播时,广播嵌套循环比笛卡尔连接更适用于内部非对等连接。
最后但同样重要的是,分区对于给定连接机制的执行效率也起着非常重要的作用。要了解更多关于分区的信息,可以参考前面的链接。
希望这个故事能消除你对 Apache Spark 中 Join 执行的所有困惑和疑虑。如果还有任何疑问,请写在评论区或给我发消息。
解开线性搜索之谜
搜索算法指南
升级你的搜索游戏!
搜索,一个我们都非常熟悉的任务。无论是在书架中寻找一本书,找到合适的信用卡使用,还是上网冲浪,我们每次都要进行搜索。

戴维·桑蒂洛在 Unsplash 上拍摄的图片
在编程中,搜索是非常常见的操作。搜索是指在数据结构中找到关键元素位置的行为。这些数据结构可能是链表、数组、搜索树,甚至是哈希表。然而,为了简单起见,我们将讨论数组中的搜索方法。
什么是线性搜索?
线性搜索是最直观的搜索方法。这里没有发生高级操作,只是从最左边的元素开始,遍历每个元素一次。它查看每个元素一次,不跳转。
这类似于在一本书中搜索特定的一页,从第一页开始,一次移动一页,直到到达要搜索的那一页。
它是如何工作的?
线性搜索的步骤如下:
- 从最左边的元素开始,将其与我们正在搜索的元素进行比较。
- 如果匹配,停止并返回元素的位置/索引。
- 移动到下一个元素。
- 重复步骤 1、2 和 3,直到到达最后一个元素。
- 如果数组中没有匹配项,则返回-1。
线性搜索示例
首先,我给你提供一个伪代码。伪代码将帮助你一步一步地理解算法中发生了什么。在你有了思维过程之后,你就可以用你喜欢的编程语言自己编码了。
线性搜索伪码
在这里,我还将为您提供 3 种不同编程语言的代码示例,Python、C 和 JavaScript。
Python 中的线性搜索代码
C 语言中的线性搜索代码
JavaScript 中的线性搜索代码
线性搜索的时间复杂度
线性搜索的最佳情况是当键在第一个位置时,使得最佳情况的时间复杂度为 O(1)。而最坏的情况发生在所需元素位于最后一个位置时。在这种情况下,我们需要将密钥与数组中的所有元素进行比较,在最坏的情况下,时间复杂度为 O(n)。平均来说,我们仍然需要进行大约(n-1)/2 次比较,平均时间复杂度也是 O(n)。
如果你不熟悉时间复杂性分析和大 O 符号,YK 杉(CS Dojo)在 Youtube 上有一个全面的解释。放心先看!
由于线性搜索的时间复杂性,它实际上很少使用,因为其他方法如二分搜索法在大多数情况下性能更好(特别是当元素的数量变得非常大时)。
放弃
尽管线性搜索可能不适合在有序数组中使用,但应该注意的是,它在无序数组中仍然非常有效。总而言之,学习线性搜索是如何工作的,是学习编程至关重要的一步。它将为你学习更高级的概念提供正确的基础。请记住:
"千里之行始于足下。"
——老子
今天就迈出你的第一步!意味着你离目标又近了一步。学习愉快。
问候,
弧度克里斯诺
揭开 MLPerf 推理的神秘面纱

MLPerf 是一个广泛的社区,专注于机器学习(ML)的基准测试,有超过 70 个参与组织(还在增加)。标杆管理是指评估“绩效”(质量、速度、能效等。)的计算机系统使用典型的工作负载(任务、数据集、模型)。与大多数其他 ML 基准不同, MLPerf 包含了在实践中使用 ML 的培训和推理(部署)阶段。
第二轮 MLPerf 培训收到了来自英特尔、英伟达、谷歌、阿里巴巴和富士通的提交材料(v0.6,结果于 2019 年 7 月 10 日公布)。第一轮 MLPerf 推论(v 0.5,结果于 2019 年 11 月 6 日公布)收到了来自 14 家组织的提交材料,包括来自上述公司的 Habana Labs ( 于 2019 年 12 月被英特尔收购)和divideti。

MLPerf 推理 v0.5:分解提交者接受的 595 个结果。
因此, MLPerf 正迅速成为ML 系统的行业基准,并成为发布新产品的理想论坛,其基准测试结果将使分析师、投资者和买家信任。
作为至 MLPerf 推论的顶级撰稿人之一,我经常回答新人的问题。虽然有一份出色的白皮书解释了基准测试套件的基本原理和方法,但我从潜在提交者(硬件设计师、云提供商等)那里得到的问题。)和用户(买家、投资人等。)具有更实际的性质。在这篇文章中,我开始回答一些常见的问题。
下面,在问句中,“我”指的是你,读者,“我们”指的是“你的组织”;在答案中,“我”指的是我,作者,“我们”指的是“MLPerf 社区”(但只有当我认为我可以代表整个社区时)。
为什么要考虑参加 MLPerf?
一个词——信任。
随着在云和边缘加速 ML 的许多选项变得可用,有眼光的买家不再满足于仅仅依靠供应商的销售宣传和营销材料来做出购买决定。相反,购买者要求供应商提供大量细节,例如使用的确切工作负载和优化选项、性能和准确性的权衡、功耗、工具链成熟度等。(例如,参见通用汽车在 2017 年嵌入式视觉峰会上的激励演示。)
MLPerf 旨在通过商定一个通用的严格方法,在系统之间进行有意义和公平的比较。特别是,所有的推理提交必须遵循严格的规则关于允许的模型转换、数据预处理和后处理等等。重要的是,所有的推理提交必须使用所谓的 LoadGen API,用于在一个或多个使用场景(单流、多流、服务器、离线)中,在被测系统(软件+硬件)上生成工作负载(ML 模型)的执行轨迹。
现在是建立信任最重要的一步。所有提交的 MLPerf 都由其他提交者审核,他们可能包括你的直接竞争对手。因此,如果你的提交经得起审查的审查,你的结果将被认为是最值得信赖的。那是金色的!
例如,向提交 MLPerf 推论 v0.5 的三家硬件初创公司已经收获了来之不易的信任:
MLPerf 只针对硬件厂商吗?
正如 Linley Newsletter 所总结的那样,MLPerf 推论 v0.5 的提交来自“云服务提供商、服务器供应商、芯片供应商和专业服务公司”。因此,答案似乎是“基本上是”。
然而,公平的基准测试可以帮助展示的东西没有限制:专业服务(例如作为产品的基准测试)、知识产权(例如最先进的技术)、技能(例如模型设计和优化、再培训)、工具(例如图形编译器)等等。
好,我们如何运行 MLPerf?
MLPerf 不是一个可以简单下载运行的基准,至少今天不是。( MLPerf Mobile 工作组正在朝着开发一款用于智能手机和平板电脑的用户友好基准测试的 Android 应用的方向大步前进,但是 ML 推理的前景显然比移动领域要广阔得多。)
所以要回答这个问题,我们首先应该考虑一下 MLPerf 基准测试定义过程是如何工作的。 MLPerf ( 训练或推理 ) 工作组商定一组代表性的任务,如图像分类和对象检测,以及每个任务的一个或多个代表性的工作负载(模型)。然后,一个或多个人自愿为每个工作负载创建一个参考实现。这有助于明确对模型的要求(例如,理想情况下,应该只有一个用于推断的预训练权重来源)、验证数据集、性能和准确性指标等。
然而,参考实现并不是最快的。事实上,提交者被期望将工作负载移植到他们的目标硬件。通常,他们需要创建一个新的实现,混合 MLPerf LoadGen API 用于发布推理查询和一个特定于硬件的 API 用于处理查询。他们仍然应该模仿参考实现的预处理和后处理行为,以使他们的提交符合标准。
当然,加速推理的核心是特定于硬件的 API。例如,对于 MLPerf 推论 v0.5 ,NVIDIA 使用tensort,Intel 使用 OpenVINO ,dividiti 使用 ArmNN 创建了新的工作负载实现。根据规则,加速实现必须在允许基准测试的开源许可下共享。
当然,创建新的符合 MLPerf 的实现需要提交者付出巨大的努力,但是这对于获得可信度是必要的。好消息是这项工作应该在几轮提交中分摊。它还可以激发更广泛的社区驱动的跨其他平台、工作负载、数据集等的基准测试。
MLPerf 推论只针对计算机视觉工作负载吗?
一点也不!诚然,在用于第 v0.5 轮的 5 个工作负载中,有 4 个是用于图像分类和物体检测的计算机视觉任务。然而,对于 v0.7 回合,引入了新的任务,例如自然语言处理、语音识别和推荐。推理的复杂性也大大增加了:从 ResNet50 中的 2500 万个参数到 DLRM 中的 250 亿个参数。
如果我的客户最喜欢的工作负载不是 MLPerf 推断的一部分,该怎么办?
如果您是潜在的提交者,您可能已经使用客户最喜欢的工作负载为他们执行了一些基准测试。即使此工作负载不是 MLPerf 推断的一部分,您也可以重新利用您在优化此工作负载方面所付出的努力,并在两种情况下展示您的解决方案:
- 工作负载必须仍然执行由 MLPerf 推断定义的任务之一。例如,您可以使用另一个对象检测模型。
- 你必须服从 MLPerf 推论的开师。虽然开放部门放宽了一些规则(例如允许选择任意模型或从封闭部门中重新训练一个模型),但您的提交仍必须使用 LoadGen API 并符合提交格式。
如果我最喜欢的工作负载不是 MLPerf 推理的一部分,该怎么办?
如果你有你最喜欢的工作量(事实上,也许是你唯一真正关心的工作量!),你也可以使用严格的 MLPerf 方法来评估你的潜在供应商。理论上,你只需要推动他们产生符合 MLPerf 的结果,然后看着竞争展开。实际上,他们可能不会让步,特别是如果他们资源有限,或者如果你的请求被认为不够优先。在这种情况下,你仍然可以自己评估它们,或者请一个可信的第三方帮助。
其他值得注意的超越正式 MLPerf 框架的案例包括非公开竞争分析(例如,证明内部研发支出的合理性)或公开营销(例如,通过 MLPerf 提交轮次支持您的产品发布)。在后一种情况下,确保遵守 MLPerf 使用条款。再次,考虑如何提高你的声明的可信度 MLPerf- 风格,完全透明和客观。
在这篇文章中,我试图为潜在的提交者和该基准的用户驱散围绕 MLPerf 推理的神秘气氛。但是由于我仅仅触及了表面,如果有进一步的问题,请随时联系 me ,我会在以后的帖子中尝试回答这些问题。
反复出现的一个问题是严格基准测试的努力和成本。与软件工程相比,它确实比特别的方法花费多几倍。工作流自动化将是制定严格的 ML 基准(跨不同的硬件、软件、工作负载、数据集等)的关键。)每个人都负担得起,同时不损害信誉和信任。
揭秘 ROC 曲线
如何解释以及何时使用接收机工作特性曲线

ROC 曲线是评估和微调分类模型的重要助手。但是,对我们中的一些人来说,理解它们真的很难。我会把这些曲线对于初学者来说难以理解的原因全部列出来,逐一破解背后的奥秘。如果你之前试图解释 ROC 曲线没有成功,这篇文章将帮助你最终理解它们。如果你不熟悉混淆矩阵、灵敏度、特异性、真阳性率等。请参考我以前的文章。

ROC 曲线看起来有点复杂的原因:
1。它们令人生畏的名称接收器操作特性并没有给出任何字面上的暗示来说明其含义
2。当我们试图目视检查曲线时,x 轴为 1-特异性有点令人迷惑。
3。ROC 曲线显示了一个分类模型在所有分类阈值下的性能。它可以用来评估模型的强度。ROC 曲线也可以用来比较两个模型。当我们试图同时理解/应用所有这些概念时,就会变得令人困惑。
4。对角线代表的随机模型到底是什么?这是最糟糕的模型吗?
让我们试着逐一解开这些谜团,了解 ROC 曲线。
1.名称—接收机工作特性曲线
ROC 曲线在第二次世界大战期间首次用于分析雷达信号。偷袭珍珠港后,美国陆军开始了新的研究,以提高从雷达信号中发现日本飞机的速度。不用说,他们不想错过任何一个。他们也不希望把资源浪费在错误的警报上。他们测量了雷达接收机操作员做出这些被称为接收机工作特性的预测的能力。这就是这个名字的由来。曲线的目的类似于我们现在如何使用它来改进我们的机器学习模型。目的是分析预测器的预测能力,以确保检测尽可能多的真阳性,同时尽量减少假阳性。
2。该图—灵敏度对(1-特异性)
ROC 曲线是 y 轴上的真阳性率(TPR)对 x 轴上的假阳性率(FPR)的图。
TPR =灵敏度
FPR = 1-特异性
最好以原始形式理解 ROC 曲线,TPR Vs FPR。一旦你理解了它们,用上面的等式进行替换就很容易了。
为什么我们要比较 TPR 和 FPR?
假设我们有一个二元分类模型,它预测属于“是”和“否”类的观察值的概率。我们选择概率阈值= 0.5。概率> = 0.5 的观察值属于“是”和“概率”<0.5 belong to Class NO. We obtain the following confusion matrix.

Notice in the figure below that TPR and FPR are derived from two separate rows of the confusion matrix. This ensures that the class distribution in the data (prevalence) does not affect the curve. The YESs and the NOs are being looked at separately.

The True Positive Rate looks at the actual YESs and the False Positive Rate looks at the actual NOs.
类,因此,即使 ROC 图包含关于这两类的信息(是和否),这些组也不会相互影响。即使测试数据中类别的患病率/分布发生变化,每个值以及曲线本身也不会发生变化。(不要将此与(可能)影响模型强度的训练数据中的类别分布相混淆。这里我们讨论的是建立模型,然后根据测试数据对其进行评估。检验数据的类别分布不影响 ROC 曲线。)
我们将进一步详细讨论 ROC 曲线,但现在让我们注意 ROC 曲线中的 x 轴是假阳性率。一旦我们理解了曲线及其目的,我们可以很容易地用 1-灵敏度来代替它。
3。ROC 曲线的目的
a)目的 1——分析分类器的强度/预测能力
我们的分类模型的任务是将较高的概率分配给属于“是”类的观察值,将较低的概率分配给属于“否”类的观察值。基本上,如果分配给任一类观察值的概率存在显著差异,我们将能够定义一个阈值,并以较高的置信度预测这两个类。
好的分类器的 ROC 曲线更靠近图的左上角。为什么?因为在一个好的分类器中,我们可以在低 FPR(最佳阈值)下实现高 TPR。不同阈值下的 FPR 和 TPR 将在 b)点中讨论。

绿色曲线显示类别 YES 的分布,红色曲线显示类别 NO 在分类器分配给每个 obs 的概率上的分布。使用阈值 0.5,我们能够正确地对大多数观察结果进行分类。分布有轻微的重叠。重叠案例是在 0.5 时被错误分类的案例。如果我们将阈值移动到 0.6,我们将能够正确地分类几乎 85%的真阳性,并且没有假阳性。当我们将阈值从 0.6 降低到 0.5 时,TPR 将增加,但 FPR 也会增加。(注意,在下面的 ROC 曲线中,我们看不到阈值。)

ROC 曲线—分类器 1
我们可以使用颜色编码的 ROC 曲线,如下图所示,以便能够看到曲线上的每个阈值。右边的颜色条表示每种颜色的阈值。

记得我们讨论过患病率/阶级分布如何不影响 ROC 曲线。前面讨论的分类器 1 将在不平衡数据集中分离类,就像它对上述平衡数据集所做的那样。该分类器的 ROC 曲线仍然是相同的。

即使在对不平衡数据集进行分类时,我们的分类器的 ROC 曲线也保持不变。

差的分类器(如下面的分类器 2)将不能很好地区分这两类,因此其 ROC 曲线将更接近对角线。这意味着更低的 TPR 率(更多的假阴性)和更高的 FPR 率(更多的假阳性)。这就引出了 c 点中讨论的曲线下面积的概念。

由 ROC 曲线中蓝色对角线表示的随机模型是随机分类器,其不具有任何区分两个类别的能力,即两个类别的预测概率重叠(分类器 3)。因此,TPR =任何阈值下的 FPR。

b)目的 2——确定最佳阈值
我们有一个分类模型,它预测一个观察值属于“是”类的概率。这个概率的范围可以从 0 到 1。用于确定该观察的类别的默认阈值 0.5 并不总是最佳阈值。ROC 曲线帮助我们找到 TPR 高而 FPR 低的阈值,即错误分类低。因此,ROC 曲线应该用于确定分类模型的最佳概率阈值。
此外,在很多情况下,误报和漏报的成本是不一样的。这就是 ROC 曲线非常有用的时候。
ROC 曲线显示了 TPR 和 FPR(或假阴性和假阳性)之间的权衡。它描绘了 TPR 与 FPR 在不同阈值的关系。如果我们降低分类阈值,我们会将更多的观察结果分类为阳性,从而增加真阳性。但是这将导致甚至假阳性增加。当我们改变这个阈值时,我们的系统的性能会变化。可以对其进行调整,以调整模型的行为,从而减少一种或另一种类型的误差(FP/FN)。

1.在上面的曲线中,如果你想要一个假阳性率非常低的模型,你可以选择 0.8 作为你的阈值。如果你喜欢低 FPR,但你不想要糟糕的 TPR,你可能会选择 0.5,这是曲线开始向右急转弯的点。
如果你喜欢低的假阴性率/高的 TPR,你可能会决定在 0.2 到 0.1 之间的某个地方,你开始得到进一步提高 TPR 的严重递减回报。
2.请注意阈值为 0.5 和 0.4 时的图表。两个阈值的总生育率都在 0.6 左右,但 FPR 在阈值 0.4 时较高。很明显,如果我们满意 TPR = 0.6,我们应该选择 threshold = 0.5。
c)目的 3 —比较两个模型(使用曲线下面积)
在 ROC 曲线中,对角线代表基线模型/随机分类器。ROC 曲线越接近 ROC 空间的 45 度对角线,模型就越不强大。

AUC——曲线下面积
ROC 曲线下的面积也称为 AUC。AUC 提供了一个模型在所有可能的分类阈值上的综合性能度量。

AUC 代表可分性的程度或度量。它告诉我们这个模型在多大程度上能够区分不同的类。AUC 越高,模型在预测“是”类的概率高于“否”类的概率方面就越好
AUC 值的范围从 0 到 1。预测 100%正确的模型的 AUC 为 1.0;其预测 100%错误的 AUC 为 0.0。

出于以下两个原因,AUC 是可取的:
- AUC 是比例不变的。它衡量预测的排名,而不是它们的绝对值。
- AUC 是分类阈值不变的。它测量模型预测的质量,而不管选择什么分类阈值。
AUC 越大,分类器/模型越好。
4。随机模型是最坏的可能模型吗?
不完全是。随机模型是一个分类器,它随机预测观察值为“是”或“否”。在这种情况下,我们将有 50%的正确预测。AUC 为 0.5,TPR 等于所有阈值的 FPR。但是很明显,这样一个模型对我们没有多大价值。
最差的可能模型是将所有“是”类观测值预测为“否”类,将“否”类观测值预测为“是”类的模型。这种模型的 AUC 将是 0。

总之
每当您构建一个分类模型来预测某个观察值属于某个类别的概率时,绘制其 ROC 曲线来可视化其性能。不要使用默认阈值 0.5。使用 ROC 曲线和领域知识计算出模型的最佳阈值。
当数据中的类别分布不平衡或假阳性和假阴性的成本不同时,ROC 曲线非常有用。它们帮助我们可视化 TPR 和 FPR 之间的权衡,从而帮助我们达到最小化误分类成本的阈值。
ROC 曲线的形状包含许多关于模型预测能力的信息。
不同模型的 ROC 曲线可以直接进行总体比较,也可以针对不同的阈值进行比较。
曲线下面积(AUC)可用作模型技巧的总结,并可用于比较两个模型。
我希望你现在能够更好地利用 ROC 曲线。期待您的回复:)
揭开杂乱物品装载器的神秘面纱
权威指南
自动清理和扩展你的垃圾蜘蛛

来自 Unsplash 的 Nicolasintravel
项目和项目加载器
当从网站上抓取数据时,它可能是混乱和不完整的。现在 scrapy 上的大部分教程都引入了物品的概念。项目为报废的数据提供容器。但是物品装载器在这里起什么作用呢?它们提供了填充项目容器的机制。
项目加载器自动执行常见任务,如在项目容器之前解析数据。它还提供了一种更干净的方式来管理提取的数据,因为你扩大了你的蜘蛛。
要跟进,请阅读 scrapy 文档中的项目。有必要对这个有个了解再继续!
路线图
在本文中,我们将定义什么是与项目相比较的项目加载器。然后我们将讨论项目加载器如何通过处理器来完成这项工作。这些处理器是内置的或定制的。它们为我们提供了在填充项目字段之前解析数据的能力。然后,我们将向您展示项目加载器如何使数据提取更加干净。这是在传送到处理器之前。我们将解释如何让我们自己的处理器超越内置函数,按照我们认为合适的方式改变我们的数据。我们将介绍如何扩展 ItemLoader。这允许我们在网站改变时扩大我们的蜘蛛的功能。
清单
- 定义项目装入者职责
- 定义输入和输出处理器,这是项目装载器的发电站
- 定义 ItemLoaders 方法。这就是 ItemLoaders 为处理器获取数据的方式
- 定义项目装入程序上下文。这是处理器之间共享键和值的一种方式,非常有用
- 定义内置处理器
Identity()、TakeFirst()、Join()、Compose()、MapCompose() - 如何定义项目加载器所需的特定输入和输出处理器。这为您提供了灵活性。您可以为不同的项目字段选择不同的输入和输出处理器。
- 定义 NestedLoader。当所有数据都在一个 HTML 块中时,这是一种清理我们编写项目加载器的方式。
- 如何扩展 ItemLoader 和插件功能。对于可伸缩性和网站变化非常有用。
使用项目装入器填写项目
让我们来看看物品装载器的幕后。为了利用这一点,我们必须创建一个 ItemLoader。这是一个名为 Scrapy.Loader.Itemloader 的类,它有三个主要参数。
- Item:指定我们为蜘蛛创建的一个或多个条目,以便用 ItemLoader 填充。如果没有指定,scrapy 会创建一个名为 default_item_class 的新项目对象
- 选择器:为 Itemloaders 方法使用选择器。如果没有指定,Scrapy 会创建一个新的选择器类。然后给变量 default_selector_class 赋值。
- 用于使用 default_selector_class 构造选择器的响应
句法
ItemLoader([item,selector,response,] **kwargs)
为了开始使用 ItemLoader,我们将它导入到我们的 spider 中。然后,我们导入我们在 spiders items.py 中指定的项目
from scrapy.loader import ItemLoader
from myproject.items import Product
现在让我们看看如何启动 ItemLoader,注意我们在这里没有指定选择器。如果我们不定义默认选择器,Itemloader 实际上会填充它。
def parse(self,response):
l = ItemLoader(Product(), response)
注意事项
1。我们从 parse 函数开始,这是 ItemLoader 实例形成的地方。
2.我们将变量 l 赋给 ItemLoader 类实例。我们在 spiders Items.py 和响应中定义了我们的product() items 实例。
使用 ItemLoader 类的下一步是 ItemLoader 方法。这让我们有能力从我们的网站获取数据,并允许我们操纵它。我们通过一种叫做处理器的东西来操纵它。

Unsplash 的哈勃望远镜
输入输出处理器
对于每个项目字段,项目加载器都有一个输入处理器和一个输出处理器。一旦收到提取的数据,它们就进行处理。在 ItemLoad 方法中定义处理器来解析数据(下一节)。
一旦我们用输入处理器处理了数据。然后,它会将提供给它的任何数据追加到 ItemLoader 中的一个内部列表中。因为这些数据被放入一个列表中,所以允许 ItemLoader 的一个条目字段有多个值。这个内部列表的结果然后被馈送到输出处理器。然后输出处理器的结果被分配给 Item 字段。
处理器是调用数据进行解析并返回解析值的对象。有了它,我们就可以将任何函数用作输入或输出处理器。唯一的条件是处理器函数的第一个参数必须是可迭代的。
Scrapy 还内置了我们将在本文中讨论的处理器。
我们现在可以讨论真正神奇的 ItemLoader 方法了!

来自 Unsplash 的 Slejven Djurakovic
项目加载器方法
ItemLoader 类具有允许我们在项目字段中使用数据之前更改数据的方法。我们将在这里讨论一些重要的方法。有关详细信息,请参考文档。
如果我们看一下 ItemLoader 类,它有几个处理提取数据的函数。最常见的三种是add_xpath()、add_css()、add_value()。
它们都接受一个项目字段名,然后接受一个 xpath 选择器、css 选择器或字符串值。它还允许使用处理器来改变数据。
句法
add_xpath(field_name, xpath,*processors,**kwargs)
add_css(field_name,css, processors,**kwargs)
add_value(field_name,value,processors,**kwargs)
ItemLoader 的核心功能是通过输入处理器实现的。这就是为什么 ItemLoader 方法提供了指定它的选项。
您可以通过指定自己的输入处理器来更改提取的数据。现在,如果没有指定处理器,默认的处理器是。然后只返回提取数据的值。
现在输出处理器接受这个收集的内部列表。这可能会也可能不会被我们自己的输入处理器改变。这提供了要填充的新值。
为了用提取的数据填充条目字段,我们使用 load_item()方法。一旦通过处理程序,这将填充“项目”字段。
现在让我们通过一个简单的例子来看看这在实践中是如何工作的。
def parse(self,response):
l = ItemLoader(Product(), response)
l.add_xpath('Title', //*[@itemprop="name"][1]/text()')
return l.load_item()
笔记
1.我们用我们定义的项目product()和响应来定义我们的项目加载器
2.我们使用add_xpath方法指定条目字段标题和标题的 xpath 选择器。
3.然后我们使用load_item()方法填充这个条目字段

来自 Unsplash 的 Markus Spiske
项目装入程序上下文
在进入内置处理器之前。讨论项目加载器上下文很重要。这些是可以共享的键和值。我们创建的 ItemLoader 将已定义的项目/选择器/响应分配给 loader_context。然后他们可以习惯于改变输入/输出处理器。
一些内置处理器可以使用它,了解这一点很重要。
处理器函数中的loader_context参数允许处理器共享数据。
一个简单的例子
def parse_length(text,loader_context):
unit = loader_context.get('unit','m')
#length parsing code goes herereturn parse_length
现在,您可以通过多种方式更改项目加载器上下文值。
- 修改当前活动的项目加载器上下文
loader = ItemLoader(product)
loader.context['unit'] = 'cm'
2.在项目加载器实例化时(作为关键字参数)
loader = ItemLoader(product, unit='cm')
3.关于输入/输出处理器的项目加载器声明,例如 MapCompose
class ProductLoader(ItemLoader):
length_out = MapCompose(parse_length, unit='cm')
ItemLoader 上下文对于传递我们希望在处理器中使用的键和值非常有用。
内置处理器
现在我们已经确定了项目加载器的基础。让我们来看看 Scrapy 提供给我们的一些样板文件。
在 Scrapy 代码库中,内置处理器的类在一个名为 processes.py 的单独文件中。我们必须导入它们才能使用它们。
from scrapy.loader.processors import BUILTIN PROCESSORS
Scrapy 提供了Identity()、TakeFirst()、Join()、Compose()、MapCompose()、SelectJmes()六个内置处理器。我们将带你经历前五个。
身份()
Identity()是最简单的处理器,它返回值不变。
from scrapy.loader.processors import Identity
proc = Identity()
proc(['one','two','three'])
输出:
['one,'two','three']
这个内置处理器你已经不知不觉用上了。当在我们讨论的 ItemLoader 方法中没有指定处理器时,identity 类实例被赋予变量 default_input_processor 和 default_output_processor。这意味着如果我们不指定处理器,ItemLoader 返回的值不变。
Takefirst()
Takefirst()从接收的值中返回第一个非空值。它被用作单值字段的输出处理器。
from scrapy.loader.processors import TakeFirst
proc = TakeFirst()
proc(['', 'One','Two','Three'])
输出:
'one'
加入()
Join(separator=u’ ’)返回连接在一起的值。分隔符可以用来在每一项之间放置一个表达式。默认为u’’。在下面的例子中,我们输入<br>。
from scrapy.loader.processors import Join
proc = Join()
proc(['One, 'Two', 'Three'])
proc2 = Join('<br>')
proc2(['One', 'Two','Three'])
输出:
'one two three''one<br>two<br>three'
撰写()
Compose()获取一个输入值,并将其传递给参数中指定的函数。如果指定了另一个函数,结果会传递给该函数。这样一直持续下去,直到最后一个函数返回这个处理器的输出值。这个函数是我们用来改变输入值的。Compose()用作输入处理器。
语法是compose(*functions,**default_loader_context)
现在每个函数可以接收一个loader_context参数。这将把活动加载器上下文键和值传递给处理器。现在,如果没有指定loader_context,则指定一个default_loader_context变量。这什么都不能通过。
from scrapy.loader.processor import Compose
proc = Compose(Lambda v: v[0], str.upper)
proc(['hello','world])
输出:
'HELLO'
笔记
- 组合内置处理器被调用
- Proc 由我们用函数指定的 compose 类定义。这种情况下是 lambda 函数和 string upper 方法。每个列表项从小写字母变成大写字母。
地图合成()
很像compose(),但处理方式不同。输入值被迭代,第一个函数应用于每个元素。结果被连接起来以构造一个新的 iterable。然后将它用于第二个函数。最后一个函数的输出值连接在一起,形成输出。
这为创建只处理单个值的函数提供了一种便捷的方式。当字符串对象从选择器中被提取出来时,它被用作输入处理器。
def filter_world(x):
return None if x == 'world else xfrom scrapy.loader.processors import MapCompose
proc = MapCompose(filter_world, str.upper)
proc(['hello', 'world', 'this','is', 'scrapy'])
输出
['HELLO, 'THIS', 'IS', 'SCRAPY']
笔记。
1.我们创建了一个名为filter_world的简单函数
2.Mapcompose被导入
3.过程被分配MapCompose。两个函数filter_world和一个类似函数的 str 方法。
4.然后 Proc 被输入一个 iterable,每一项都被传递给filter_world,然后应用一个 string 方法。
5.注意查看第二个项目‘world’如何被输入到filter_world函数。这将返回 none,该函数的输出将被忽略。现在可以在下一个项目中进行进一步的处理。正是这一点给了我们这样的输出,项目“世界”被过滤掉了。

来自 Unsplash 的大卫·拉托雷·罗梅罗
声明自定义项目装入器处理器
我们可以像声明项目一样声明项目加载器处理器。也就是使用类定义语法。
from scrapy.loader import ItemLoader
from scrapy.loader.processors import TakeFirst, MapCompose, Joinclass ProductLoader(ItemLoader):
default_output_processor = Takefirst()
name_in = MapCompose(unicode.title)
name_out = Join()
price_in = MapCompose(unicode.strip)
笔记。
- ProductLoader 类扩展了 ItemLoader 类
_in后缀定义输入处理器,_out后缀声明输出处理器。我们将 Item 字段(在本例中为 name)放在后缀之前,以定义我们希望流程处理哪个字段。name_in分配一个MapCompose实例,并定义了函数 unicode.title。这将用于名称项字段。name_out被定义为Join()类实例price_in被定义为一个Mapcompose实例。为价格项目字段定义函数unicode.strip。
也可以在项目字段中声明处理器,让我们看看它是如何工作的。
import scrapy
from scrapy.loader.processors import Join, MapCompose, Takefirst
from w3lib.html import remove_tagsdef filter_price(value):
if value.isdigit():
return valueclass Product(scrapy.Item):
name = scrapy.Field(input_processor=MapCompose(remove_tags), outputprocessor=Join(),) price = scrapy.Field(input_processor=MapCompose(remove_tags, filter_price), outprocessor=Takefirst(),)
笔记
- 我们导入内置处理器和另一个移除标签的包。
- 我们定义了
filter_price函数,如果输入是一个数字,它将被返回。 - 然后,我们通过扩展 Scrapy 来定义项目。项目分类。
- Name 被定义为 ItemField。我们指定应该使用哪些输入和输出处理器。
- 价格被定义为 ItemField。我们指定应该使用哪些输入和输出处理器。
- 价格有两个被调用的函数,即
remove_tags和filter_price。filter_price是我们定义的函数。
现在,我们可以在蜘蛛的 data.py 文件中使用 ItemLoader 实例。注意,我们已经通过我们的 spider 中的 items.py 指定了我们的输入和输出处理器。
from scrapy.loader import ItemLoader
il = ItemLoader(item=Product())
il.add_value('name',[u'Welcome to my', u'<strong>website</strong>'])
il.add_value('price', [u'€', u'<span>1000</span>'])
il.load_item()
输出:
{'name': u'Welcome to my website', 'price': u'1000'}
注释
1。我们现在导入 ItemLoader 类
2。我们用创建的项目字段定义项目加载器
3。我们使用add_value方法,定义名称项字段,并传递一个包含字符串的列表。
4。我们使用add_value方法来定义价格项目字段,并传递另一个包含两个项目的列表。
5。当我们添加第一个值字符串时,它的标签被移除,两个项目被连接在一起
6。当我们添加第二个值时,第一项被忽略,因为它不是一个字符串,我们将数字变为 1000。
7。load_item()方法给了我们一个条目字段名和修改后的数据的字典。这被输入到项目字段中。
现在,输入和输出处理器的优先顺序是从 1 号到 3 号。
1.项目加载器特定于字段的属性 field_in 和 field_out
2.字段元数据(输入处理器和输出处理器关键字参数)
3.项目加载器默认itemLoad.default_input_processor()和itemLoad.default_output_processor()

来自 Unsplash 的 Brian Kostiuk
嵌套加载程序
当你想要抓取的信息在一个大的块中时,我们可以使用一个嵌套的加载器来提高可读性。它允许我们通过创建相对路径来缩短 ItemLoader 方法的路径。这可以让你的零碎项目更容易阅读,但不要过度使用它!
Loader = ItemLoader(item=Item())
footer_loader = loader.nested_xpath('//footer/)
footer_loader.add_xpath('social','a[@class="social"]/@href')
loader.load_item()
笔记
- 我们像前面一样实例化一个 Itemloader 类
- 我们为嵌套的加载程序定义了一个变量。我们指定了
nested_xpath()方法,它接受一个选择器。在这种情况下我们给它//footer/。 - 我们使用 footer_loader 来访问 ItemLoader 方法。这意味着我们不必多次指定页脚选择器。在这种情况下,我们调用
add_xpath()方法,定义项目字段和我们想要的相对 xpath 选择器。这样我们就不必一直编写 xpath 选择器的//footer/部分
4.我们像以前一样调用load_item()方法将它输入到我们的项目字段 social 中。
重用和扩展项目加载器
我们可以使用继承的属性来扩展我们的项目加载器。这提供了无需创建单独的 ItemLoader 的功能。当网站改变时,这变得特别重要。这就是项目加载器的力量,当网站改变时,我们可以按比例增加。
当需要不同的输入处理器时,我们倾向于扩展 ItemLoader 类。使用 Item.py 来定义输出处理器更加定制化。
from scrapy.loader.processors import MapCompose
from myproduct.ItemLoaders import ProductLoaderdef strip_dashes(x):
return x.strip('-')class SiteSpecificLoader(ProductLoader):
name_in = MapCompose(strip_dashes, ProductLoader.name_in)
笔记
- 我们导入地图合成流程
- 我们还导入了一个
ProductLoader,这是我们定义的 ItemLoader
3.然后我们创建一个函数strip_dashes来删除破折号
4.然后我们在SiteSpecificLoader中扩展ProductLoader
5.我们将字段输入处理器的名称定义为MapCompose。我们传入strip_dash函数并调用 ProductLoader name_in方法。
然后我们可以在我们的SiteSpecificLoader中使用name_in输入处理器。与所有其他的ProductLoader样板。
Scrapy 让你能够为不同的站点或数据扩展和重用你的项目加载器。
摘要
在这里,您已经了解了项目和项目加载器之间的关系。我们已经展示了处理器如何习惯于能够解析我们提取的数据。ItemLoader 方法是我们从网站获取数据进行更改的方式。我们已经讨论了 scrapy 拥有的不同内置处理器。这也让我们可以为项目字段指定内置或新的处理器。
相关文章
揭秘用 Scrapy 登录的过程。
towardsdatascience.com](/scrapy-this-is-how-to-successfully-login-with-ease-ea980e2c5901) [## 如何使用 Python 下载文件
了解如何使用 Python 下载 web 抓取项目中的文件
towardsdatascience.com](/how-to-download-files-using-python-ffbca63beb5c)
关于作者
我是一名医学博士,对教学、python、技术和医疗保健有浓厚的兴趣。我在英国,我教在线临床教育以及运行网站www.coding-medics.com。
您可以通过 asmith53@ed.ac.uk 或 twitter 这里联系我,欢迎所有意见和建议!如果你想谈论任何项目或合作,这将是伟大的。
如需更多技术/编码相关内容,请在此注册我的简讯。
揭秘支持向量机
理解基础数学的快速指南

介绍
监督学习描述了一类涉及使用模型来学习输入示例和目标变量之间的映射的问题。对于分类问题,目标变量可以是类标签,对于回归问题,目标变量可以是回归变量值。有些模型既适用于回归也适用于分类。我们将在这个博客中讨论的一个这样的模型是支持向量机,缩写为 SVM。我的目的是简单明了地向你提供 SVM 的内部运作。
事不宜迟,让我们开始吧。🚗
让我们假设我们正在处理一个二元分类任务。

图 1
可能有无限多的超平面可以将这两类分开。你可以选择其中任何一个。但是这个超平面能很好地预测新查询点的类别吗?你不认为离其中一个班级很近的飞机偏向另一个班级吗?直观上,区分两个类别的最佳方法是选择一个超平面,该超平面与任一类别中的最近点等距。
这就是 SVM 所做的!

图 2
SVM的核心思想:
选择将+ve 点与-ve 点尽可能分开的超平面π。
设π是分开这两类的超平面,π₊和π₋是平行于π的两个超平面,使得
π₊是当我们平行于π移动时得到的平面,它与π最近的+ve 点接触
π₋是我们平行于π移动时得到的平面,它接触到π的最近点

图 3
d =差额= dist(π₊,π₋)
- SVM 试图找到一个使利润最大化的π。
- 随着边距的增加,泛化精度也会增加。
支持向量:
位于π₊或π₋上的点称为支持向量。

图 4
SVM 的数学公式
π:边际最大化超平面
π: wᵀx+ b =0
比方说,
π₊ : wᵀx + b =+1
π₊上或正方向上远离它的任何一点都标为正
π₋ : wᵀx + b =-1
π₋上或负方向远离它的任何一点都标为负
在这种情况下,差额为

图 5
所以,我们的优化问题变成了

图 6:硬利润 SVM
现在,这可能看起来不错,但是,它只适用于我们的数据是线性可分的。如果不是,那么我们就不能解决上面的优化问题,我们就不能得到最优的 w 和 b。
让我们设想一个场景,其中数据不是线性可分的:

图 7
由于这四点,我们的优化问题将永远得不到解决,因为这些点 yᵢ(wᵀx+b 不≥ 1。
这是因为我们的优化问题过于严格,它只解决线性可分的数据。这种方法被称为硬利润。
那么,我们能修改它吗?我们能不能让它宽松一点,这样它就可以处理几乎线性可分的数据?

图 8
我们所做的是使松弛变量 ζ ᵢ (zeta)对应于每个数据点,使得对于位于+ve 区域的+ve 点和位于-ve 区域的-ve 点,
t5】ζᵢ= 0。
这给我们留下了错误分类的点和边缘内的点。
ζ ᵢ的意思
以 f 图 7 中的点 4 为例, ζ ᵢ = 2.5
这意味着在这种情况下点 4 从其正确的 hyperplane(π₊向相反的方向偏离了 2.5 个单位)。
类似地,在这种情况下,点 1 距离其正确的 hyperplane(π₋2.5 个单位)在相反的方向。
随着ζᵢ的增大,该点在 方向更加远离正确的超平面 方向。

图 9
修正优化问题

图 10:SVM 的原始形态
我们来分解一下
首先,约束条件:
我们知道,

图 11
现在,

图 12
和

图 13
c 是超参数。
我们可以直观地把优化问题想成:

图 14
- 如果 c 较高,损失项将被赋予更大权重,这将导致数据过度拟合。
- 如果 c 较低,将给予正则化项更大权重,这将导致数据拟合不足。
SVM 的双重形式

图 15
等等!我们是如何得到这种双重形式的呢?
嗯,这都与优化有关,如果我们深入其中,我们将偏离我们的目标。让我们在另一个博客中继续这个双重形式。
为什么我们需要这种双重形式?
对偶形式有时更容易解决,如果对偶间隙很小,我们会得到类似的结果。特别是对 SVM 来说:对偶形式非常重要,因为它开启了一种通过内核函数解释支持向量机的新方法(我将在本博客的后半部分告诉你)。
注意:在对偶形式中,所有的 xᵢ都以点积的形式出现,不像原始形式中所有的 xᵢ都以独立的点出现。
αᵢ可以被认为是拉格朗日乘数
从双重形式观察:
- 对于每一个 xᵢ,都有相应的αᵢ
- 所有 xᵢ都以点积的形式出现
- 我们对新点的分类方式发生了变化:

图 16
- 支持向量的αᵢ > 0,非支持向量的αᵢ =0。
这意味着只有点才是重要的支持向量,这就是将该模型命名为支持向量机的原因。
现在,以双重形式

图 17

图 18
因此,如果给定一个相似矩阵,我们可以使用对偶形式而不是原始形式。这就是 SVM 的魅力所在。通常,这个 similarity(xᵢ,xⱼ)被 K(xᵢ,xⱼ)代替,其中 k 被认为是核函数。
内核技巧及其背后的直觉
用内核函数 K(xᵢ,xⱼ代替 similarity(xᵢ,xⱼ)被称为内核化,或者应用内核技巧。
你看看,无非就是计算 xᵢ和 xⱼ.的点积那么,它有什么了不起的呢?
让我们以下面的数据集为例。

图 19
很明显,这两个类别不能用线性模型来区分。
现在,用特征

图 20
你看到了吗?应用适当的特征变换和增加维数使我们的数据线性可分。
这就是内核 SVM 所做的。它将原始特征映射到一个更高维度的空间中,在该空间中找到边际最大化超平面,并将该超平面映射到原始维度空间中,以获得非线性决策表面,而无需实际访问该更高维度的空间。
所以,
线性支持向量机:在 xᵢ's 空间中寻找边缘最大化超平面
核 SVM:在 xᵢ's 的变换空间中寻找边缘最大化超平面
因此,核 SVM 也能够解决非线性可分数据集。
让我们来看看 SVM 使用的一些玉米粒
多项式核
它被定义为:

图 21
在哪里
d=数据的维度
c =常数
对于二次核,设 c=1,即

图 22
维度= 2

图 23
这可以被认为是两个向量 x₁'和 x₂'的乘积,其中:

图 24
新维度= d' = 6
因此,内核化与特征转换是相同的,但通常是在内部隐式完成的。
径向基函数(RBF 核)
它是最受欢迎的内核,当你不知道选择哪个内核时,你可以选择这个😉
它被定义为:

图 25
d 的效果:
当 d 增大时,指数部分的分子减小,或者换句话说,K 值或相似度减小。
σ的影响:

图 26:来源 Google
如果您注意到,当σ = 0.3 时,图表在 x=2 时接近 0。当σ =1 时,x=4 时接近 0,当σ=10 时,x=11。这表明,当σ增加时,即使两个点相距很远,它们的相似性得分也会大于 0。
没明白吗?
假设有两个点,x₁和 x₂,距离为 4 个单位。如果我们应用σ = 0.3 的 RBF 核,则核函数 K 值或相似性值将为 0。如果σ = 1,K 值将非常接近 0,但如果σ = 10,K 值将约为 0.4 左右。
现在,RBF 内核背后的直觉-
还记得我们在使用多项式内核时得到的 6 维映射函数吗(参见图 24)?现在让我们试着找出一个 RBF 核的映射函数。
为了简化数学,假设数据的原始维数为 2,指数部分的分母等于 1。在这种情况下,

图 27
如果我们试图找出 RBF 核的映射函数,这将把我们引向一个无限向量。这意味着 RBF 核将我们的数据带入无限维空间,计算相似性得分并返回它,这就是为什么如果你无法确定选择哪个核,RBF 核将是最安全的选择。😎
SVM 回归
到目前为止,我们已经了解了如何使用 SVM 执行分类任务。但是 SVM 不仅仅局限于此。它也可以用来执行回归任务。怎么会?我们去看看吧!
首先,让我们看看支持向量回归机(SVR)的数学公式

图 28
放心吧!我会为你打破它。

图 29
SVR 的工作方式是,它试图找到一个最适合数据点的超平面,同时保持容限= ε(超参数),这意味着所有点都应该在超平面两侧的ε距离内。
这里最小化裕量意味着我们要找到一个超平面,它以低容限来拟合数据。
注意:平方是为了使函数变得可微,并适于优化。人们可以对 SVC 做同样的事情。
这个提法有什么问题?
这里的问题是我们太严格了,我们期望这些点位于超平面的ε距离内,这在现实世界中并不经常发生。在这种情况下,我们将无法找到所需的超平面。那么,我们该如何着手呢?
与我们在 SVC 中处理该问题的方式相同,我们将引入两个松弛变量ζ(ζ)用于法线方向的点,引入ζ*(ζ星)用于法线相反方向的点,以允许一些点位于容差范围之外,但会有损失。

图 30
所以数学函数现在变成了:-

图 31:SVR 的原始形式
其中 C 决定了所需的严格程度。C 值越大,超出边界的点受到的惩罚越多,这可能导致数据过度拟合。C 值越小,对超出边界的点的惩罚就越小,这可能会导致数据拟合不足。
就像在 SVC 中一样,图 31 显示了 SVR 的原始形式。已经观察到对偶形式更容易解决,并且我们也可以使用核技巧来寻找非线性超平面。
正如我已经说过的,对偶形式的表述有点棘手,涉及到解决约束优化问题的知识。我们不会谈论那么多细节,因为那会转移我们对 SVM 的注意力。
支持向量回归机的对偶形式

图 32:双重形式的 SVR
不好意思!我不是故意吓你的。这是通过使用拉格朗日乘子来解决优化问题而获得的。
对于一个新的点,我们计算产值的方法是:-

图 33:SVR 的函数值
你注意到 xᵢ以点积的形式出现了吗?是的,和我们在 SVC 中得到的一样。我们可以用我上面已经提到的相似度或核函数来代替这个点积。应用内核技巧也有助于我们拟合非线性数据。
SVM 的案例
- 特征工程和特征转换
这是通过如上所述找到正确的内核来隐式完成的
2.决策面
对于线性 SVM:决策面只是一个超平面
对于内核 SVM:这将是一个非线性的表面
3.相似度函数/距离函数
SVM 的原始形式不处理相似性函数。然而,由于点积形式的 xᵢ的存在,对偶形式可以容易地处理它。
4.特征重要性
如果特征不共线,则权重向量 w 中的特征权重确定特征重要性。在特征共线的情况下,可以使用前向特征选择或后向特征消除,这是确定任何模型的特征重要性的标准方式。
5.离群值
它们确实影响 SVM,但是,与其他模型如逻辑回归相比,影响较小。
6.偏差-方差
它取决于 SVM 对偶形式中 c 的值。
如果 c 较高,将给予误差项更大的权重,因此模型可能过拟合数据,如果 c 较小,将给予误差项更小的权重,并且模型可能欠拟合数据。
7.高维度
支持向量机被设计成即使在高维空间也能很好地工作。参考图 14,该图显示了 SVM 的数学公式中已经存在一个正则项,这有助于处理高维度。你可能会说像 KNN 这样的其他模型在高维情况下不太适用,那么支持向量机有什么特别之处呢?这是因为 SVM 只关心找到最大限度的平面,它不关心点之间的相对距离。
SVM 的优势
- 它有一个正则项,有助于避免数据的过度拟合
- 它使用内核技巧,帮助处理非线性数据(在 SVR 的情况下)和非线性可分离数据(在 SVC 的情况下)
- 当我们不知道数据的时候,SVM 是非常好的。
- 适用于文本、图像和树等非结构化和半结构化数据。
- 即使当训练样本包含错误时,它也能工作,从这个意义上说,它是健壮的
SVM 的局限性
- 选择正确的内核是一项艰巨的任务。
- SVM 算法有几个需要正确设置的超参数,以实现任何给定问题的最佳分类结果。可能导致问题 A 的分类精度极佳的参数,可能导致问题 B 的分类精度不佳。
- 当数据点数量很大时,训练 SVM 需要很长时间。
- 对于核支持向量机,很难解释权重向量(w)。
参考
- https://alex.smola.org/papers/2004/SmoSch04.pdf
- https://www.saedsayad.com/support_vector_machine_reg.htm
- https://statin fer . com/204-6-8-SVM-优势-劣势-应用/
- http://www.cs.uky.edu/~jzhang/CS689/PPDM-Chapter2.pdf
揭开二项分布的神秘面纱
本文的目的是介绍二项式分布背后的一些重要统计概念,并说明其在流行病学和/或医疗保健数据科学中的一个主要应用。
伯努利试验
在我们进入二项分布之前,理解伯努利试验是很重要的。伯努利试验是概率论和统计学中使用的术语。这是一个随机的试验,有两种可能的结果。这两种结果可以是“成功”也可以是“失败”。理解这一点的最好方法是通过例子。我列举了三个与流行病学领域(病毒抗体测试)、机器学习(二元分类预测)和普通概率论(掷硬币)相关的例子。
- 概率论喜欢掷硬币,而掷硬币可以被认为是伯努利试验。掷硬币的结果要么是正面,要么是反面——所以我们有两种结果。
- 流行病学的一个例子是对一个随机的病人进行病毒抗体测试。测试结果可能是“阳性”也可能是“阴性”——所以我们有两种结果。这又是一次伯努利试验。
- 从机器学习/人工智能的角度来看,在二分类问题的情况下,预测也可以被视为伯努利试验。
你现在可能有这样的感觉,伯努利试验在实际场景中经常发生,这是真的。这就是为什么伯努利试验及其相关的概率分布如二项式分布在实践中有很多应用。
概率分布
好吧,对于那些不知情的人来说,触及概率分布背后的直觉是有意义的。简单来说,概率分布就是一个随机变量可能值的分布。它总是用一个图来表示,这个图实际上就是一个直方图,x 轴表示随机变量的值,y 轴表示随机变量取相应变量的概率。

概率分布的例子。X 轴代表随机变量的值。在这里,这个变量的值在 40 到 80 之间。Y 轴表示从总体中抽取的随机样本具有相应值的概率。
现在一个可能的问题是什么是随机变量?随机变量是可以从随机实验中获取或存储值的变量。通常,随机变量是用一个大写字母来表示的,(例如:- X)。
为什么我们对概率分布感兴趣?
概率分布使我们能够从样本数据中推断科学实验。科学实验的最终目的是检验某个假设,并利用样本数据推断该假设是否成立。样本只是整个人口的一小部分代表(人口是世界上所有可能结果的集合),获得人口的数据根本不实际。相反,我们提取样本,并利用样本从样本中推断出人群的发现。这种推断几乎总是通过使用概率分布来完成的。所以概率分布是统计学中最广泛使用的概念之一,几乎在每个科学领域都有应用。一般来说,根据产生概率分布的随机变量的类型,有两种类型的概率分布。这些分别是离散和连续随机变量的离散概率分布和连续概率分布。我不会深入讨论离散和连续随机变量的细节,但二项式分布是一种离散概率分布,因为二项式随机变量是一种离散变量(即它只能取整数),而流行的正态分布是一种连续概率分布。
伯努利分布
顾名思义,伯努利分布就是伯努利试验的概率分布。这是所有概率分布中最简单的一种,因为它是单次试验,只有两种结果,我们只需要知道得到每种结果的概率。请记住,伯努利试验中的“失败”概率是“成功”概率的补充,因为这是两个相互排斥的事件,并且在一次试验/实验中只能出现其中之一。例如,在掷硬币时,如果我们假设硬币是公平的,那么获得正面的概率是 0.5,等价地,获得反面的概率是 1- 0.5 = 0.5。
让我们定义一个随机变量 X,它取一次掷硬币的成功次数(假设得到头就是成功),这是一次伯努利试验。这里, X 只能有两个可能的值——0 和 1。那就是你要么得到一个头,要么得到一条尾巴。如果硬币是公平的,成功和失败的概率都是 0.5。同样,如果硬币不公平,成功的概率可能不是 0.5。相反,它可能是 0.4、0.6、0.7、0.2——可以是任何值。因此,伯努利概率分布取决于成功的概率,通常由字母 p,表示,其中 p 是 0 和 1 之间的值,包括 0 和 1。伯努利分布所依赖的唯一参数是 p.

伯努利分布。X 轴代表 X,伯努利随机变量。它只能取 0 或 1,因为它是单次试验,并且试验只能导致 0 次成功或 1 次成功。p 是 0.5,0.6,0.8 和 0.2 如果你顺时针方向走
二项随机变量和二项分布
伯努利试验总是一次试验。如果我们在一个实验中进行多次伯努利试验会怎么样?比如, n 的次数?作为流行病学领域的一个例子,你不认为随机测试 1000 名受试者的新冠肺炎听起来很相似吗?是的,它是。我们现在不讨论新冠肺炎部分,但这只是为了提醒大家,二项式实验在实际情况中非常普遍。
我们来定义一个随机变量 X,代表这 n 次试验/实验的成功次数?如果伯努利试验重复 n 次,那么该试验作为一个整体被称为二项式试验。这里,每个单独的试验/实验都是伯努利试验。但与我们之前的伯努利示例中的 X 不同,这里的 X 代表二项式实验中的成功次数,该实验由 n 个伯努利试验组成。让我们从一个例子开始,开始学习任何新东西的最好方法。我们可以考虑掷硬币的例子。我们抛硬币三次,而不是之前在伯努利试验中提到的一次。所以这里的 n 是 3。我们的 X 是整个二项式实验的成功次数。这里,n 是 5,并且它们中的每一个可以有 2 个结果(头或尾),因此我们有一组 2 = 8 个可能的结果,而不是在伯努利试验的情况下只有 2 个。
这 8 个结果是:{H,H,H},{H,H,T},{H,T,H},{H,T,T},{T,H,H},{T,H,T},{T,H,T},{T,T,H},{ T,T,T,T }其中 H 代表正面,T 代表反面。我们的 X 是一个二项式随机变量,这意味着它代表了在 n 次试验中的成功次数。所以它可以取 0,1,2 或者 3。现在,我们要为随机变量 X 构建一个二项式分布。这意味着我们需要计算 X 的每个可能值的概率。让我们从 X = 2 的情况开始,即在 3 次投掷中正好观察到 2 个头部的概率。我们来定义一下 p ,每次个人投掷(一次伯努利试验)的成功概率(获得人头)等于 0.4(硬币没那么公平!).
两个头可以出现在:HHT、HTH 和 THH。单次试验得到人头的概率,也就是 p,是 0.4。序列 HHT 因此具有 0.4 * 0.4*0.6 的概率。对于所有三种可能出现两个头的情况,每个单独序列的概率为:
- HHT——0.4 * 0.4 * 0.6
- HTH — 0.40.60.4
- THH——0.6 * 0.4 * 0.4
你可以看到一个模式,不管 H 和 T 的顺序,得到任何一个序列的概率都是相同的,总是等于 0.4 * 0.6。由于我们有三个看似合理的序列,我们可以将(0.4 *0.6)乘以 3,得到在三次试验中恰好得到两个头的概率。甚至这个数字“3”在这里也可以通过排列和组合很容易地计算出来。这里的问题是有多少次你可以从三个样本中选择两个项目。这无非就是流行的 n 为 3,r 为 2 的 nCr 题。在这个例子中,3C2 不过是 3!

现在,我们也可以用下面的表达式来表示在三次投掷中恰好获得两个头的概率:

同样,我们也可以很容易地计算出 P(X=0),P(X=1)和 P(X=3)。
P(X=0) = 0.216
P(X=1) = 0.432
P(X=2) = 0.288
P(X=3) =0.064
注意,如果你把上面的四个概率加起来,等于 1。
一般来说,在 n 次固定且独立的伯努利试验中获得 k 次成功的概率,即二项式概率,可以写成如下形式:

二项分布的概率质量函数
上述函数也称为二项式分布的概率质量函数(PMF)。对于任何离散分布,都会有一个与之相关的 PMF,而对于二项式分布,PMF 恰好是上述函数。
如果你看看上面的二项式分布的 PMF 公式,你可以看到,如果 n 是 1,这个方程就变成了伯努利分布的 PMF。
回到我们之前的掷硬币的例子,我们现在已经计算了 3 次试验中所有可能成功的概率。因此,让我们构建二项式实验的概率分布,其中 n 为 3,p 为 0.4。

二项随机变量的概率分布,其中 n 是 3,p 是 0.4
一般来说,二项分布取决于两个参数。这些是 n 和 p,记住伯努利分布只取决于 p,因为在伯努利试验中 n 总是 1。如果随机变量 X 遵循二项式分布,那么它在数学上由以下符号表示
x~Binom(n,p)
如果一个实验是二项式实验,注意该实验需要满足的条件也很重要。这些条件是:
- 实验由 n 个相同的试验组成,并且 n 总是固定。
- 每次试验都有两种结果,称为成功和失败。
- 表示为 p 、的成功概率在不同的试验中保持不变。
- n 试验是独立的。也就是说,任何试验的结果都不会影响其他试验的结果。这是有替换样本的时候。
如果实验必须是二项式实验,则所有条件都要满足。但是也有违反条件 3 和更常见的条件 4 的情况。例如,如果您在不替换的情况下进行采样(即,在每次单独试验后移除您挑选的样本),则 p 不会保持不变,试验也不会相互独立。然而,对于大样本量和 p. 的非极值,这通常不是问题
二项分布和正态分布有什么关系?
这是假设你对所有概率分布之母的正态分布有所了解。那么二项分布和正态分布有什么关系呢?
让我们看一些二项式分布图,n 的值不同,p 为 0.5。

p = 0.5 时不同 n 值的二项式分布
让我们来看看二项分布,当每次试验的概率有点极端时,比如说 0.1

p = 0.1 时不同 n 值的二项式分布
在这两种情况下,你可以看到二项式分布看起来或多或少像正态分布中的钟形曲线!当 p 为 0.5 时尤其如此。这种特性被称为正态分布的近似值。这是一个非常有用的现象,因为通过这种近似,你可以从你的样本数据中得到关于人口的推论。请注意,对于 p 的极值,正态近似并不完全正确。在 p 为 0.1 的第二个示例中,您可以看到分布有点偏斜,不像 p 为 0.5 时那样对称。尽管如此,正态近似法在大多数情况下都适用,并且在处理二项式比例(如疾病流行率)时,有一些方法(如连续性校正)可以调整正态近似法的偏差。
我不喜欢在生物统计学中使用小抄,因为它们会导致不良实践,并误导那些寻找简单出路的人。永远记住,统计学没有免费的午餐。话虽如此,如果你总是持保留态度,那么出于实用目的,拥有某种备忘单有时还是有用的。比如在二项式分布中,你可以说正态近似在 np 和 n(1-p)的最小值大于等于 5 的情况下效果很好。
二项式分布的正态近似与统计学中的中心极限定理密切相关,这种现象也被称为德莫维尔—拉普拉斯定理
对于那些想知道更多关于 中心极限定理【CLT】的人来说,那里有成吨的材料。我还开发了一个 交互式 RShiny 仪表板,展示了 CLT 的概念。
二项随机变量 E(X)的期望值
上面两张图也说明了二项分布中的一个显著现象。仔细看可以发现最大概率发生在 X = np 的一点,比如第二个数列,当 n 为 30 时(这里 p 固定为 0.1),np 得 3。你可以看到这里的酒吧的高度是最高的。无论你的 n 还是 p,这都会在所有的图中看到,这个值不过是 X 的期望值,通常用 E(X)来表示。你可以把它想成一个平均值,或者出于实用目的的平均值。当 X 实际等于或接近 E(X)时概率最高。这意味着如果你的样本量不是很小,一个随机无偏样本很可能包含等于 E(X)的成功次数,因为这是概率最高的地方。
总体中样本量足够大的随机无偏样本更有可能包含等于或接近总体中实际成功次数的成功次数。
二项分布的均值和方差
根据定义,随机变量的期望值是 X 的单个值与其相应概率的加权和。在这种概率分布的情况下,期望值和平均值可以被认为是基本相同的。

上述两个均值和方差方程可用于构建一个新的随机变量,该随机变量遵循均值为 0、标准差为 1 的标准正态分布(因为正态近似性质),方法是将 X 的每个值减去其均值,然后除以其标准差。现在,可以假设这个新变量遵循均值为 0、标准差为 1 的标准正态分布。这使我们能够构建检验统计(参见我的早期出版物“揭开 p 值的神秘面纱”以了解详情)并因此获得 p 值,从而使我们能够进行假设检验。我不想谈论细节。我在这里的目的是让概念和直觉变得清晰。
二项分布的应用与一个与假设的新冠肺炎患病率估计研究相关的例子
我认为现在有必要说明二项分布在流行病学中的一个非常常见的应用。
例如,让我们说在你的国家新冠肺炎的实际流行率是大约 1%。这个数值其实是未知的(我们不知道真实的患病率!),所以流行病学家通常做的是在随机样本中进行血清流行率研究。为什么?因为了解这种疾病的实际流行情况来指导重要的决策是非常重要的。
但是在整个人群中进行这项研究是不实际的,所以他们宁愿选择一个随机的样本,比如说 1000 人。因此,从人群中随机抽取一名受试者,对其进行新冠肺炎病毒测试。这个过程可以认为是伯努利试验!现在当你对 1000 名受试者做这个实验时,它变成了一个二项式实验!此处的成功数只是 COVID 测试呈阳性的受试者人数。你可以争辩说,这里的试验不是独立的,因为一旦一个受试者接受了测试,他就不会被“替代”,因此这不是一个有替代的抽样。因为这不是替换抽样,所以每个受试者被检测为阳性的概率是不同的。话又说回来,就像之前说的,除非你的样本量太小,否则你不用太担心这个。
现在,这就是问题所在。如果您的研究是一项没有偏见的理想研究,并且您的 1000 名受试者样本是整个人群的真实代表,那么最有可能的情况是,由于前面描述的特性,该样本中测试为阳性的受试者人数大约为 10 (n*p = 1000 * 1%= 10)。这意味着从您的样本中,您对真实流行率(人口流行率)的估计是 10 除以 1000,也就是 1%,这就是实际流行率!现在,在实际场景中,你可能不会得到精确的 1%,但是有可能你仍然会得到一个更接近真实值的值。这就是置信区间和 p 值的来源,在大多数情况下,这些值是根据正态近似的性质来估计的。
估计一种疾病的真实流行程度有更多的细微差别。我上面讨论的只是最基本的。如前所述,如果真实患病率实际上接近 0(这并不罕见)或 1,那么正常近似值可能无法达到预期效果。还有其他方法可以解决这个问题,但这超出了本文的讨论范围。此外,你的诊断/筛查测试永远不会完美。可能会有假阳性和假阴性。在估计患病率时,也有通过调整测试灵敏度和特异性来解决这个问题的方法(关键词:罗根·格莱登估计器)。在进行研究和阅读血清流行病学期刊出版物时,了解这些注意事项非常重要。
预测分析和机器学习中二项分布的关联
机器学习或人工智能中最常见的用例是二元分类问题。也就是说,您希望训练和验证一个算法,该算法预测特定观察值是否属于一个类(0 或 1 个场景)。最基本的算法是逻辑回归模型。例如,你想预测,给定一个动物的图像,它是否是一只狗。这里,算法最终输出概率值,使得在给定输入特征(图像的像素值)的情况下,图像中的动物是狗的概率。另一个例子是,您希望预测出院后 30 天内再次住院的风险。这里的“风险”只不过是给定患者特征(人口统计、病史、生化特征等)后 30 天内再次入院的概率。).
在所有这些情况下,因变量(又名目标变量、响应变量)是一个二元变量,可以取 0 或 1。该变量实际上遵循伯努利分布(当 n 为 1 时,它就是二项式分布),逻辑回归模型的目标是在给定输入特征的情况下,估计成功的“p”。
邓艾—数据预处理
理解 ML
如何对 ML 比赛的数据进行预处理?基于邓艾的例子。
本文基于我在 DrivenData 平台 上参加 邓艾比赛。我的得分在 0.2%以内(截至 2020 年 6 月 2 日,14/9069)。
在本文中,我假设你已经熟悉了邓艾——埃达。你不需要读它来理解这里的一切,但是如果你读了,就会容易得多。
为什么要对数据进行预处理?
当设计 ML 模型时,我们必须记住其中一些是基于梯度法的。梯度的问题在于它在归一化/缩放数据上表现得更好。让我举个例子:

梯度下降的例子。
在左侧,我们有一个由两个要素组成的数据集,其中一个要素的比例比另一个要素大。在这两种情况下,梯度方法都有效,但是当要素位于相似的比例上时,达到最佳效果所需的步骤要少得多(右图)。
什么是正常化,什么是缩放?
正常化
在标准意义上,规范化是指调整值分布范围以适应 < -1,1 > 的过程(id 不必精确到-1 比 1,但在同一数量级内,因此范围)。通过从集合中的每个值中减去平均值,并将结果除以标准偏差来完成标准归一化。

缩放
你可以看到它被称为“最小-最大归一化”,但缩放是另一个值调整以适应范围,但这次范围是 < 0,1 > 。

归一化还是缩放?
您可以对特征执行两种类型的操作。您可以标准化或缩放其值。选择哪一个取决于特性本身。如果您认为要素具有一些正值和负值,并且这些值很重要,则应该执行规范化。在负值没有意义的特征上,应该应用缩放。
并不总是非黑即白。让我们考虑一个特征,比如温度。取决于你选择的刻度(开尔文或摄氏/华氏),温度可能会有不同的解释。开尔文温标是绝对热力学温标(从绝对零度开始,不能低于绝对零度)。另一方面,我们有使用 IRL 的标度,负数对我们有意义。当温度降到摄氏零度以下时,水就结冰了。华氏温标也是如此,它的 0 度描述了盐水(盐在水中的浓缩溶液)的冰点。直截了当的选择是缩放开尔文,并使摄氏和华氏温度正常化。这并不总是奏效。我们可以在邓艾的数据集上展示它:

有些温度在开氏温标上,有些在摄氏温标上。这在这里并不重要。如果您仔细观察,您应该能够按类型对这些温度进行分组:
- 绝对最小值温度
- 没有绝对最小值的温度(可以是负值)
第一个例子是 station_diur_temp_rng_c 。这就是所谓的日温度变化,它定义了一段时间内最低和最高温度之间的变化。该值不能为负值(因为最小值和最大值之差不能小于 0)。这就是我们应该使用缩放而不是归一化的地方。
再比如再分析 _ 空气 _ 温度 _k 。它是空气温度和重要特征。我们无法定义温度可能达到的最小值。如果我们真的希望每个城市都有一个任意的最低温度,我们永远不能低于这个温度,但这不是我们想要做的。在训练模型时,像我们这样的问题中的温度这样的东西可能有另一种意义。温度值可能有一些积极和消极的影响。在这种情况下,温度低于 298K 可能会对一些病例产生积极影响(蚊子减少)。这就是为什么我们应该对这个使用规范化。
检查整个数据集后,我们可以得出要归一化、缩放的特征列表,并从我们的特征列表中复制:
标准化特征
'reanalysis_air_temp_k'
'reanalysis_avg_temp_k'
'reanalysis_dew_point_temp_k'
'reanalysis_max_air_temp_k'
'reanalysis_min_air_temp_k'
'station_avg_temp_c'
'station_max_temp_c'
'station_min_temp_c'
缩放特征
'station_diur_temp_rng_c'
'reanalysis_tdtr_k'
'precipitation_amt_mm'
'reanalysis_precip_amt_kg_per_m2'
'reanalysis_relative_humidity_percent'
'reanalysis_sat_precip_amt_mm'
'reanalysis_specific_humidity_g_per_kg'
'station_precip_mm'
'year'
'weekofyear'
复制的特征
'ndvi_ne'
'ndvi_nw'
'ndvi_se'
'ndvi_sw'
为什么要复制?
如果我们看看 NDVI 指数的定义,我们可以决定没有理由缩放或标准化这些值。NDVI 值已经在 < -1、> 范围内。有时我们可能想像这样直接复制值。尤其是当原始值与我们的归一化特征处于同一数量级时。它可能是< 0,2 >或< 1,4 >,但它不会给模型带来问题。
代码
现在,我们必须编写一些代码来预处理我们的数据。我们将使用 sklearn 库中的 StandardScaler 和 MinMaxScaler 。
作为函数的输入,我们希望发送 3 或 4 个变量。在处理训练集时,我们发送 3 个变量:
- 训练数据集(如熊猫数据帧)
- 要规范化的列列表
- 要缩放的列列表
当我们处理训练数据时,我们必须为缩放/标准化过程定义数据集。该数据集用于获取平均值或标准差等值。因为在处理训练数据集时,我们没有任何外部数据集,所以我们使用训练数据集。在第 19 行,我们使用StandardScaler()对选择的列进行规范化:
StandardScaler 在初始化时不需要任何参数,但它需要缩放数据集以适应。我们可以只通过两次new_data就可以了,但是我们需要为测试数据集创建另一个预处理。
接下来,我们要做同样的事情,但是用的是MinMaxScaler()。
这一次,我们传递一个名为feature_range的参数,以确保我们的比例在范围< 0,1 >内。和前面的例子一样,我们传递缩放数据集来适应和转换所选的列。
最后,我们返回转换后的new_data和另外的train_scale用于进一步的预处理。但是等一下!什么进一步的预处理?请记住,我们不仅要处理训练数据集,还要处理测试数据集。我们必须对它们应用相同的数据处理,以使模型具有相同的输入。如果我们简单地以同样的方式对测试数据集使用preproc_data(),我们将应用完全不同的标准化和缩放。原因是因为归一化和缩放是通过.fit()方法完成的,并且该方法使用一些给定的数据集来计算平均值和其他所需的值。如果您使用的测试数据集可能具有不同的值范围(由于全球变暖等原因,夏天很热。)您在测试数据集中的值 28C 将使用不同的参数进行标准化。让我给你看一个例子:
训练数据集:

测试数据集:

使用训练数据集中的平均值和标准差对测试数据集进行归一化,得到:
[0.11,0.11,0.91,1.71,0.91,0.11,1.71]
但是,如果您使用测试数据集中的平均值和标准差,您最终会得到:
[−1.04,−1.04,0.17,1.37,0.17,−1.04,1.37]
你可能认为第二个更好地描述了数据集,但这只适用于只处理测试数据集的情况。
这就是为什么在构建我们的模型时,我们必须像这样执行它:
结论
我们刚刚完成了一个非常标准的数据集标准化过程。理解标准化和缩放之间的区别很重要。另一件可能更重要的事情是归一化的特征选择(不同温度特征的例子),你应该总是试图理解你的特征,而不仅仅是应用一些来自互联网的硬编码规则。
我必须提到的最后一件事(你可能已经想到了)是训练和测试数据集中的数据范围之间的差异。您知道测试数据的标准化应该使用来自训练数据的变量来完成,但是我们不应该调整过程以适应不同的范围吗?假设训练数据集的温度范围在 15℃和 23℃之间,测试数据集的温度范围在 18℃和 28℃之间。这难道不是我们模型的问题吗?实际上不是:)模型并不真的关心这样的小变化,因为它们是在逼近连续函数(或分布),除非你的范围相差很大(来自不同的分布),否则你不应该有任何问题。
最初发布于https://erdem . pl。
邓艾—如何对待数据科学竞赛?(EDA)
理解 ML
一步一步解释如何应对类似的竞争。哪些是我们应该重点关注的,哪些是应该忽略的?

蚊子 CC BY-NC-ND 2.0。来源: flickr 用户赛诺菲巴斯德
本文基于我在 DrivenData 平台 上参加 邓艾大赛。我的得分在 0.2%以内(截至 2020 年 6 月 2 日,14/9069)。这里提出的一些想法是严格为这样的比赛设计的,可能没什么用。
在开始之前,我必须提醒您,对于更高级的数据工程师来说,有些部分可能是显而易见的,这是一篇很长的文章。你可以一节一节地读,或者只挑选你感兴趣的部分:
更多零件即将推出…
问题描述
首先,我们需要讨论比赛本身。邓艾的目标是(实际上,此时此刻甚至是,因为 DrivenData 的管理部门决定让它成为“正在进行的”比赛,所以你可以参加并亲自尝试)根据天气数据和位置预测特定周内的登革热病例数。每个参与者都有一个训练数据集和测试数据集(非验证数据集)。 MAE ( 平均绝对误差)是一个用于计算得分的指标,训练数据集覆盖了 2 个城市 28 年的周值(1456 周)。测试数据较小,跨越 5 年和 3 年(取决于城市)。
对于那些不知道的人来说,登革热是一种蚊子传播的疾病,发生在世界的热带和亚热带地区。因为它是由蚊子携带的,所以传播与气候和天气变量有关。
资料组
如果我们看一下训练数据集,它有多个特征:
城市和日期指示器:
- 城市 —城市缩写: sj 代表圣胡安 iq 代表伊基托斯
- week_start_date —以 yyyy-mm-dd 格式给出的日期
NOAA 的 GHCN 每日气候数据气象站测量:
- 最高温度温度 —最高温度
- 车站最低温度 —最低温度
- station_avg_temp_c —平均温度
- station_precip_mm —总降水量
- station _ diur _ temp _ RNG _ c—日温度范围
波兰卫星降水测量(0.25x0.25 度刻度):
- 降水量 _ 降雨量 _ 毫米 —总降水量
NOAA 的 NCEP 气候预报系统再分析测量值(0.5x0.5 度尺度):
- 再分析 _sat_precip_amt_mm —总降水量
- 再分析 _ 露点温度 _k —平均露点温度
- 再分析 _ 空气温度 _k —平均空气温度
- 再分析 _ 相对湿度 _ 百分比 —平均相对湿度
- 再分析 _ 比湿度 _ 克/千克 —平均比湿度
- 再分析 _ 降水量 _ 千克/平方米 —总降水量
- 再分析 _ 最高空气温度 _k —最高空气温度
- 再分析 _ 最小空气温度 _k —最低空气温度
- 再分析 _ 平均温度 _k —平均气温
- 再分析 _tdtr_k —日温差
卫星植被——归一化差异植被指数(NDVI)——NOAA 的 CDR 归一化差异植被指数(0.5x0.5 度标度)测量:
- ndvi_se —城市质心东南方向的像素
- ndvi_sw —城市质心西南方向的像素
- ndvi_ne —城市质心东北方向的像素
- ndvi_nw —城市质心西北的像素
此外,我们还有每周总例数的相关信息。
很容易发现,对于数据集中的每一行,我们都有多个描述相似类型数据的特征。有四个类别:
-温度
-降水
-湿度
- ndvi(这四个特征指的是城市中不同的点,所以它们不是完全相同的数据)
因此,我们应该能够从输入中删除一些冗余数据。我们不能随机选择一个温度。如果我们只看温度数据,范围(最小值、平均值、最大值)和类型(平均露点或昼夜)之间是有区别的。
输入示例:
week_start_date 1994-05-07
total_cases 22
station_max_temp_c 33.3
station_avg_temp_c 27.7571428571
station_precip_mm 10.5
station_min_temp_c 22.8
station_diur_temp_rng_c 7.7
precipitation_amt_mm 68.0
reanalysis_sat_precip_amt_mm 68.0
reanalysis_dew_point_temp_k 295.235714286
reanalysis_air_temp_k 298.927142857
reanalysis_relative_humidity_percent 80.3528571429
reanalysis_specific_humidity_g_per_kg 16.6214285714
reanalysis_precip_amt_kg_per_m2 14.1
reanalysis_max_air_temp_k 301.1
reanalysis_min_air_temp_k 297.0
reanalysis_avg_temp_k 299.092857143
reanalysis_tdtr_k 2.67142857143
ndvi_location_1 0.1644143
ndvi_location_2 0.0652
ndvi_location_3 0.1321429
ndvi_location_4 0.08175
提交格式:
city,year,weekofyear,total_cases
sj,1990,18,4
sj,1990,19,5
...
分数评估:

数据分析
在开始设计模型之前,我们需要查看原始数据并修正它。为了实现这个目标,我们将使用熊猫图书馆。通常,我们可以直接导入.csv文件,并在导入的数据帧上工作,但有时(尤其是当第一行没有列描述时)我们必须提供列的列表。
import pandas as pd
pd.set_option("display.precision", 2)
df = pd.read_csv('./dengue_features_train_with_out.csv')
df.describe()
Pandas 有一个名为describe的内置方法,可以显示数据集中列的基本统计信息。

自然,这种方法只对数字数据有效。如果我们有非数字列,我们必须先做一些预处理。在我们的例子中,唯一的分类列是城市。该列只包含两个值 sj 和 iq ,我们将在稍后处理它。
回到主桌。每行包含不同种类的信息:
- 计数 —描述非 NaN 值的个数,基本上有多少值是正确的,不是空数
- 平均值 —整列的平均值(用于归一化)
- std —标准偏差(也适用于标准化)
- 最小值->-最大值-显示包含值的范围(对缩放有用)
让我们从计数开始。知道数据集中有多少条记录有缺失数据(一条或多条)并决定如何处理它们是很重要的。如果你看一下 ndvi_nw 值,13.3%的情况下是空的。如果您决定用像 0 这样的任意值替换丢失的值,这可能是一个问题。通常,这个问题有两种常见的解决方案:
- 设置一个平均值值
- 做插补
插值(处理缺失数据)
当处理系列数据时(就像我们所做的那样),从相邻数据中插值(仅从相邻数据中求平均值)比用整个集合的平均值替换更容易。通常,系列数据在系列中的值之间有一定的相关性,使用邻居会得到更好的结果。我给你举个例子。
假设您正在处理温度数据,并且您的整个数据集由从 1 月到 12 月的值组成。全年的平均值将是全年大部分时间里缺失天数的无效替代。如果你从 7 月开始计算天数,那么你可能会得到类似于 [28,27,-,30] (或者 [82,81,-,86] 的值,对于那些喜欢英制单位的人来说)。如果那是一个伦敦,那么年平均温度是11 摄氏度(或 52 华氏度)。在这种情况下使用 11 条接缝是错误的,不是吗?这就是为什么我们应该使用插值而不是平均值。通过插值(即使在有更大间隙的情况下),我们应该能够获得更好的结果。如果你计算值,你应该得到(27+30)/2=28.5 和(28.5+30)/2=29.25,所以最后我们的数据集看起来像【28,27,28.5,29.25,30】,比【28,27,11,11,30】好得多。
将数据集分割成城市
因为我们已经介绍了一些重要的内容,所以让我们定义一个方法,该方法允许我们将分类列( city )重新定义为二进制列向量并插入数据:
def extract_data(train_file_path, columns, categorical_columns=CATEGORICAL_COLUMNS, categories_desc=CATEGORIES,
interpolate=True):
# Read csv file and return
all_data = pd.read_csv(train_file_path, usecols=columns)
if categorical_columns is not None:
# map categorical to columns
for feature_name in categorical_columns:
mapping_dict = {categories_desc[feature_name][i]: categories_desc[feature_name][i] for i in
range(0, len(categories_desc[feature_name]))}
all_data[feature_name] = all_data[feature_name].map(mapping_dict)
# Change mapped categorical data to 0/1 columns
all_data = pd.get_dummies(all_data, prefix='', prefix_sep='')
# fix missing data
if interpolate:
all_data = all_data.interpolate(method='linear', limit_direction='forward')
return all_data
所有常量(如 CATEGORICAL _ COLUMNS)都在 本要诀 中定义。
该函数返回一个数据集,该数据集包含两个名为 sj 和 iq 的二进制列,它们具有真值,其中 city 被设置为 sj 或 iq 。
绘制数据
绘制数据以直观地了解数值在系列中的分布是很重要的。我们将使用一个名为 Seaborn 的库来帮助我们绘制数据。
sns.pairplot(dataset[["precipitation_amt_mm", "reanalysis_sat_precip_amt_mm", "station_precip_mm"]], diag_kind="kde")

训练数据集中的再分析最小空气温度 k
这里我们只有数据集的一个特征,我们可以清楚地区分季节和城市(平均值从大约 297K 下降到大约 292K 的点)。
另一件有用的事情是不同特征之间的对相关性。这样,我们就能够从数据集中移除一些冗余的要素。

降水成对图
正如您所注意到的,我们可以立即删除其中一个降水特征。起初这可能是无意的,但因为我们有来自不同来源的数据,同类数据(如降水量)不会总是彼此完全相关。这可能是由于不同的测量方法或其他原因。
数据相关性
当处理大量特征时,我们不需要像那样为每一对绘制配对图。另一种选择是计算叫做的相关性分数。不同类型的数据有不同类型的相关性。因为我们的数据集只包含数字数据,所以我们可以使用名为.corr()的内置方法来为每个城市生成相关性。
如果存在不应被视为二进制的分类列,您可以计算 克莱姆的 V 关联度量 来找出它们与其余数据之间的“相关性”。
import pandas as pd
import seaborn as sns
# Importing our extraction function
from helpers import extract_data
from data_info import *
train_data = extract_data(train_file, CSV_COLUMNS)
# Get data for "sj" city and drop both binary columns
sj_train = train_data[train_data['sj'] == 1].drop(['sj', 'iq'], axis=1)
# Generate heatmap
corr = sj_train.corr()
mask = np.triu(np.ones_like(corr, dtype=np.bool))
plt.figure(figsize=(20, 10))
ax = sns.heatmap(
corr,
mask=mask,
vmin=-1, vmax=1, center=0,
cmap=sns.diverging_palette(20, 220, n=200),
square=True
)
ax.set_title('Data correlation for city "sj"')
ax.set_xticklabels(
ax.get_xticklabels(),
rotation=45,
horizontalalignment='right'
);

SJ 市的特征相关性
你可以对 iq 城市做同样的事情,并比较两者(相关性不同)。
如果你看这张热图,很明显哪些特征是相互关联的,哪些是不关联的。你应该知道正相关和负相关(深蓝和深红)。不相关的特征是白色的。存在多组正相关的特征,并且不出所料,它们指的是相同类型的测量(在 station_min_temp_c 和 station_avg_temp_c 之间的相关性)。但不同种类的特征之间也有相关性(如再分析 _ 比 _ 湿度 _ 克 _ 每 _ 千克和再分析 _ 露点 _ 温度 _k )。我们还应该关注 total_cases 和其余特性之间的相关性,因为这是我们必须预测的。
这一次我们运气不佳,因为没有什么与我们的目标有很强的相关性。但是我们仍然应该能够为我们的模型选择最重要的特性。查看热图现在没什么用,所以让我切换到条形图。
sorted_y = corr.sort_values(by='total_cases', axis=0).drop('total_cases')
plt.figure(figsize=(20, 10))
ax = sns.barplot(x=sorted_y.total_cases, y=sorted_y.index, color="b")
ax.set_title('Correlation with total_cases in "sj"')

与 sj 市目标值的相关性
通常,在为我们的模型挑选特征时,我们选择与我们的目标具有最高绝对相关值的特征。由你来决定选择多少功能,你甚至可以选择所有的功能,但这通常不是最好的主意。
查看目标值在我们的数据集中是如何分布的也很重要。我们可以用熊猫轻松做到这一点:

sj 总例数直方图

智商 总例数直方图
平均一周的案件数量相当低。只是偶尔(一年一次),病例总数会跳到某个更高的值。在设计我们的模型时,我们需要记住这一点,因为即使我们设法找到了“跳跃”,我们也可能在很少或没有案例的几周内损失很多。
什么是 NDVI 值?
最后我们要讨论的是本文中的一个 NDVI 指数 ( 归一化差异植被指数)。这个指数是植被的指标。高负值对应于水,接近 0 的值代表岩石/沙子/雪,接近 1 的值代表热带森林。在给定的数据集中,每个城市有 4 个不同的 NDVI 值(每个值代表地图上的一个不同角落)。
即使整体 NDVI 指数对于理解我们正在处理的地形类型非常有用,如果我们需要为多个城市设计一个可能会派上用场的模型,但在这种情况下,我们只有两个城市的气候和在地图上的位置是已知的。我们不必训练我们的模型来确定我们正在处理哪种环境,相反,我们可以为每个城市训练两个单独的模型。
我花了一些时间试图利用这些值(特别是在这种情况下插值很难,因为我们在这个过程中使用了大量的信息)。使用 NDVI 指数也可能产生误导,因为数值的变化不一定与植被过程的变化相对应。
如果你想看看这些城市,请参考圣胡安,波多黎各和伊基托斯,秘鲁。
结论
此时,您应该知道我们的数据集是什么样子的。我们甚至没有开始设计第一个模型,但已经知道一些功能没有其他功能重要,其中一些只是重复相同的数据。如果您需要从整篇文章中吸取一点经验,那就是“首先尝试理解您的数据!”。
参考资料:
最初发布于https://erdem . pl。
使用 XGBoost 和 LSTM 预测登革热
新加坡的登革热

每年有超过 5000 万人感染登革热病毒,这是一种由伊蚊传播的疾病,会导致高烧、皮疹和肌肉疼痛。在严重的情况下,病毒甚至会引起休克和出血,导致虚弱的受害者死亡。在新加坡,每天平均有 80 人感染登革热,在严重疫情期间,这一数字会飙升至 600 多人。
该图显示了 2012 年至 2019 年新加坡登革热病例的趋势。

2012 年至 2019 年新加坡的登革热感染病例
从图表中,我们观察到登革热病例通常会经历大约 3-4 个月的高峰,并需要大约相同的时间才能恢复到原始值。这一数据在很大程度上与登革热是一种容易暴发的传染性疾病相一致。然而,为了充分理解这些数据,我们必须研究影响登革热爆发的因素。
预测的重要性
利用各种数据集,我们能够建立一个机器学习模型来预测新加坡的登革热趋势。我们的方法考虑了前几周感染登革热的现有人数和气象数据,因为这些是导致登革热传播的因素。
问题陈述
我们的机器学习模型的目的是能够提前 8 周预测登革热,因为这将允许政府卫生组织和公众采取必要的预防措施,防止登革热的传播。有了预测登革热发生的良好预测模型,这使得公共卫生组织和个人能够为登革热在新加坡的传播做好准备、进行管理和控制。
数据集
3 个不同的数据集用于训练预测模型
登革热感染 —登革热是一种传染病,严重依赖于现有感染登革热的人数。蚊子可以被感染登革热的人感染。因此,现有的感染人数也是现有的感染登革热的蚊子数量的一个因素。
降雨数据——伊蚊在死水中产卵,暴雨期间蚊子数量可能会激增
温度数据— 雌性伊蚊的最佳进食温度为 28 度,此时它们最活跃。这个最佳区域之外的温度会导致较低的喂食率,从而降低感染率。
这些数据集是从新加坡的不同地理区域收集的。在某些地区,发现了缺失的数据。对于这些缺失的数据,我们以如下方式进行处理:
- 如果在某个特定区域有相对较大比例的数据缺失,我们将从数据集中删除该区域/因子。
- 对于剩余的数据集,我们用平均值代替缺失值。

温度与登革热爆发之间的轻微相关性
模特培训
我们选择使用的模型是一个堆叠的 XGBoost 和 LSTM 神经网络。首先,我们仅在登革热数据上使用 XGBoost 算法来训练模型,以便能够预测数据中爆发和恢复的潜在趋势。我们的数据集相对较小,只有 413 行,使用像神经网络这样的高方差算法可能会在开始时过度拟合数据。因此,我们仅使用 LSTM 层来调整预测中的任何残留误差,并微调我们的结果。
XGBoost
XGBoost 是由陈天琦和 Carlos Guestrin 开发的一种集成机器学习算法,使用决策树和随机森林进行预测。集成机器学习是一种结合相同或不同类型算法的多个模型的预测能力的系统。集成学习有两种主要类型,bagging 和 boosting。Bagging 指的是聚合根据随机数据采样训练的不同模型,并取预测值的平均值。例如,在整个数据集的随机样本上训练 10 个决策树。总计将是 10 次预测的平均值。然而,Boosting 是按顺序建立模型的,每个后续的模型都从其前一个模型的错误中学习,并创建一个新的模型来纠正错误。例如,第二个决策树将预测第一个决策树的错误,因此最终的预测将是两个预测的总和。
XGBoost 使用增强决策树来得出最终预测。然而,它使用一种称为梯度下降的特殊算法来有效地减少误差。为了进一步利用机器的全部计算能力,XGBoost 算法优化了硬件和软件,以确保在最短的时间内以最高的效率训练模型。
LSTM 神经网络

LSTM 层的性能改进
在将 XGBoost 应用于我们的数据集之后,我们训练一个长短期记忆网络来最小化我们的模型的剩余误差。LSTM 网络是递归神经网络(RNN)的变体,用于解决输入/输出序列。今天,LSTMs 被用于最先进的应用程序,如 Google Translate 和其他自然语言处理任务。鉴于我们正在处理的时间序列预测问题是一个序列问题,LSTMs 是一个很好的学习算法。

LSTM 电池简图
LSTM 网络对于评估序列是有用的,因为它们能够存储关于称为单元状态的序列的信息。该信息可以被传递到网络中的下一个 LSTM 单元,或者如果序列中的下一个元素包含更重要的信息,则该信息可以被覆盖。网络具有内置存储器的能力允许它学习更复杂的行为。
https://colah.github.io/posts/2015-08-Understanding-LSTMs/
交叉验证
我们将整个数据集分为两部分,从 2012 年 1 月到 2018 年 6 月,这是训练集,而剩余的数据用作测试集来评估我们的模型。
使用 5 重 K 重交叉验证来学习学习算法的最佳超参数。

K-Fold 交叉验证的数据集划分
训练集被分成 5 个部分,模型对 80%的数据进行训练,并使用均方误差损失度量对最后 20%的数据进行评估。然后,具有最低误差的模型将用于评估测试集,以查看模型的最终误差。这个过程是为了防止数据泄漏,以确保模型总是基于全新的数据进行评估,并且能够很好地进行概括。
最重要的超参数是输入算法的数据的回顾周期。通过我们的测试,我们确定 55 周的回顾期是最佳的。这可能是由于持续约 55 周的爆发和恢复周期,这对预测很重要。

最大似然算法的回顾期
模型评估

最后,该模型用于预测 2018 年 6 月起的登革热数据。使用相同的均方误差指标,我们获得了大约 5872 的适度误差。从图中可以看出,该模型能够以相对较高的准确度预测重大疫情,并且没有滞后时间。这对于决策者能够先发制人地阻止疾病爆发非常有用。
Github 链接:【https://github.com/reoneo97/datathon3-denga
团队成员:Neo Zheng Jie Reo,Jonathan Chua En Zhe,Joshua Seetoh Dewei
本文是新加坡国立大学(理学院)与 Terra 联合举办的 Datathon 3.0 机器学习竞赛的一部分。艾
去噪有噪声的文档
计算机视觉技术

作者图片
无数的科学论文、历史文献/人工制品、食谱、书籍都以论文的形式储存,无论是手写的还是打印的。随着时间的推移,纸张/纸币往往会通过指纹、纸张纤维的弱化、灰尘、咖啡/茶渍、磨损、起皱等积累噪音/灰尘。有几种用于保存和清洁的表面清洁方法,但是它们有一定的局限性,主要的一个是:原始文件可能在处理过程中被改变。
我与迈克尔·拉里和卡提克亚·舒克拉一起处理来自 加州大学欧文分校 NoisyOffice 数据集 的嘈杂文档数据集。对脏文档去噪使得能够创建原始文档的更高保真度的数字再现。对文档去噪的几种方法,如中值滤波、边缘检测、膨胀&腐蚀、自适应滤波、自动编码和线性回归,被应用于测试数据集,并对它们的结果进行评估、讨论和比较。

来源: UCI
中值滤波
中值滤波是最简单的去噪技术,它遵循两个基本步骤:首先,使用核大小为 23 x 23 的中值滤波获得图像的“背景”,然后从图像中减去背景。只有“前景”会保留下来,清除背景中存在的任何噪声。在这种情况下,“前景”是文本或文档的重要细节,“背景”是噪音,文档元素之间的空白。

中值滤波流水线
边缘检测、膨胀和腐蚀(EDE 方法)
边缘检测方法识别图像亮度急剧变化的点,以将它们组织成边缘。
Canny 边缘检测特别有助于提取边缘
在使用这些技术之前,图像被处理以去除噪声边缘。首先应用膨胀,通过向边界添加像素使线条变粗。请注意,这会导致“填充”文本,而污点周围的边缘保持中空。然后,通过应用相反的操作,腐蚀,可以完全去除细线,同时保留较粗的线。

边缘检测流水线
自适应阈值
脏图像的另一个特征是文本比噪声更暗。在暗噪声中,里面的文本甚至更暗。
因此,目标是保留局部最暗的像素
阈值处理将强度高于阈值的所有像素设置为 1(背景),其余像素设置为 0(前景)。在自适应阈值处理期间,没有单一的全局阈值:为每个像素计算阈值。为了确定阈值,我们使用高斯阈值。阈值是相邻像素强度的加权和,其中权重是高斯窗口

自适应阈值流水线
线性回归
我们不是一次模拟整个图像,而是尝试预测图像中每个像素的清除强度,并通过使用线性回归将一组预测的像素强度组合在一起来构建清除图像。在创建了 y 值的向量和 x 值的矩阵之后,最简单的数据集就是 x 值只是脏图像的像素亮度。
除了在极端情况下,脏图像和干净图像的亮度之间存在线性关系。当 y 接近 1 时,x 值分布很广,这些像素可能代表需要去除的污点。线性模型已经做了亮度和对比度校正。对于简单的最小二乘线性回归来说,这是相当好的性能!

线性回归的强度图

线性回归管道
自动编码器
自动编码器是由编码器和解码器组成的神经网络。编码器将输入数据压缩成低维表示。解码器重构该表示,以获得尽可能模拟输入的输出。这样,自动编码器学习输入数据的最显著的特征。
自动编码器与主成分分析(PCA)密切相关。如果自动编码器中使用的激活函数在每一层中是线性的,则潜在变量出现在瓶颈(网络中最小的层,aka。代码)直接对应于来自 PCA 的主分量
网络由 5 个卷积层组成,从图像中提取有意义的特征。在前四次卷积中,我们使用 64 个内核。每个核具有不同的权重,在输入层上执行不同的卷积,并产生不同的特征图。因此,卷积的每个输出由 64 个通道组成。
编码器使用最大池进行压缩。滑动滤波器在输入图像上运行,以构建更小的图像,其中每个像素是原始图像中由滤波器表示的区域的最大值。解码器使用上采样将图像恢复到其原始尺寸,只需简单地重复层输入的行和列,然后将其馈送到卷积层。
批量标准化减少了协方差移动,即各层之间激活分布的差异,并允许模型的每一层独立于其他层进行学习。
Model: "model_1"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
image_input (InputLayer) (None, 420, 540, 1) 0
_________________________________________________________________
Conv1 (Conv2D) (None, 420, 540, 32) 320
_________________________________________________________________
pool1 (MaxPooling2D) (None, 210, 270, 32) 0
_________________________________________________________________
Conv2 (Conv2D) (None, 210, 270, 64) 18496
_________________________________________________________________
pool2 (MaxPooling2D) (None, 105, 135, 64) 0
_________________________________________________________________
Conv3 (Conv2D) (None, 105, 135, 64) 36928
_________________________________________________________________
upsample1 (UpSampling2D) (None, 210, 270, 64) 0
_________________________________________________________________
Conv4 (Conv2D) (None, 210, 270, 32) 18464
_________________________________________________________________
upsample2 (UpSampling2D) (None, 420, 540, 32) 0
_________________________________________________________________
Conv5 (Conv2D) (None, 420, 540, 1) 289
=================================================================
Total params: 74,497
Trainable params: 74,497
Non-trainable params: 0
_________________________________________________________________

自动编码器管道
结果
来源:吉菲
中值滤波

中值滤波结果
边缘检测、膨胀和腐蚀

边缘检测结果
自适应阈值

自适应阈值结果
线性回归

线性回归结果

自动编码器结果
性能指标
PSNR

PSNR 比较结果
均方根误差

RMSE 比较结果
UQI

UQI 比较结果
体系结构
在观察了各种计算机视觉、机器学习和神经网络的结果后,我们想到将其部署为一个软件工具——“去噪器”,它托管在 AWS 上

去噪器架构
密码
以下是比较研究的完整代码以及 AWS 上托管的应用程序:
使用图像处理、机器学习、神经网络和自动编码器从嘈杂的文档中去除污点…
github.com](https://github.com/gandalf1819/Denoise-Noisy-Docs)
参考
[1] F. Zamora-Martinez,S. Espan ̃a-Boquera 和 M. J. Castro-Bleda,
应用于文档增强的基于行为的神经网络聚类,载于:计算和环境智能,第 144- 151 页,Springer,2007 年。
[2] Z. Wang,A. C. Bovik“通用图像质量指数”, IEEE 信号处理通讯,第 9 卷,第 3 期,第 81–84 页,2002 年 8 月
[3]加州大学欧文分校 NoisyOffice 数据集:https://archive.ics.uci.edu/ml/datasets/NoisyOffice
神经网络可解释性研究综述
从简单的激活地图到复杂的地图集和网络视图
在这篇文章中,我们将对深度神经网络(DNN)的密集层和卷积层的可解释性进行比较,仍然专注于图像分类任务,使用 MNIST 或 CIFAR-10 数据集作为例子。但首先,让我们简单解释一下什么是可解释性,为什么需要可解释性。

劳拉·奥克尔在 Unsplash 上的照片
在第一部分中,我们以 MNIST 标准数据集为例,展示了卷积神经网络比密集神经网络性能更好、更纤细。如果这只是一个“运气”的问题怎么办:它在这个数据集上工作得很好,但如果数据集是不同的,或者手头的任务(即分类手写数字)正在发生变化(例如分类机器生成的数字),就不会这样了。网络到底学到了什么?这些问题没有确定的答案。然而,在可解释性和对立的例子的保护伞下,有一个关于这个主题的积极研究的整个领域。
可解释性
DNN 是基于简单的数学运算,然而,在几个隐藏层上具有非线性激活的神经元的组合导致不能用数学公式评估的模型。DNN 的这一特性被 Roscher 称为缺乏透明性。解决这个问题的方法是通过可解释性,可解释性在同一篇文章中定义为:
“可解释性的目的是用人类可以理解的术语呈现 ML 模型的一些特性。[……]解释可以通过可理解的代理模型获得,这种模型近似于更复杂方法的预测。”
决策树很容易理解,因为可以看到每个决策变量-阈值的重要性。在深度神经网络中,没有这种决策工件,需要其他工具来检查网络内部。
直接检查
给定一个神经网络,我们可能会试图检查每一层的权重。这种方法有两个障碍。
首先,权重的数量很快就达到了数千,并且在最大的网络上达到了数亿。权重聚合是必需的,自然且不完美的统计工具是直方图。还有待发现聚合是如何进行的:按神经元单位还是按层?
密集网络的两个层的权重直方图
鉴于它们的参数共享特性,卷积神经网络(CNN)有一个优势:卷积层的权值比稠密等效层低得多(见第 1 部分)。此外,给定卷积滤波器的图像/信号处理背景,表示它们的权重比密集层的权重的原始列表更有意义。不过,这只适用于小型网络和第一层。
32 lenet 5 第一层的卷积滤波器权重
第二,只看一层的重量掩盖了各层之间的所有相互作用。我们回到上面提到的透明度问题。 Tensorflow Playground 具有这种相互作用的表示,其在层之间绘制漩涡,其宽度与连续神经元之间的相互作用成比例。但是,这种方法很难规模化。
神经网络的张量流操场表示
活化和梯度方法
观察网络的另一种方式是基于刺激:在图像分类网络的情况下是输入图像。
激活图是第一种基于刺激的解释方法:给定一幅图像或一小组图像,显示处理该图像时每个神经元的输出。这主要适用于 CNN,因为它们保留了图像的 2D 结构,并且只能根据前几层中的几何伪影(边缘、角)来解释。
来自 CIFAR-10 的一幅马图像上 32 个卷积单元的激活图
自 2007 年以来,人们开发了更强大的方法,所有这些方法都基于同一个想法的梯度和变化:从一个给定的神经元单位或层,激活它的最佳输入是什么?
在这些方法中,我们可以列举:
Erhan 和 Simonyan 的显著图基于反向传播到网络图像输入的梯度上升(下图中的橙色路径)。训练过程是相反的。在训练期间,图像是地面真实的一部分,并且网络权重被优化。如果要检查的神经元是网络的输出,我们将回到常规的深度神经网络优化,但具有冻结的层权重(下图中的蓝色路径)。

显著图原理
显著性图接近于对立的例子,因为有可能创建对网络有意义(即预测给定类别)但对我们的眼睛没有意义的图像。这里是一个例子,其中为 CIFAR-10 的 10 个类别中的每一个计算显著性,然后将其添加到 Concord 平面的图像中。对于大多数类别,CNN 预测显著性类别的裕度较大(概率超过 70%):
从 CIFAR-10 数据集向协和平面添加显著性
初始输入图像(通常称为基线或先验)可以是中性灰色、随机噪声或我们想要检查的图像类别。在最后一种情况下,图像被修改,就像通过漫画。Nguyen 列出的更多最近的出版物一直在研究提高显著图的质量。主要的创新在于通过采样和聚集类来优化基线,以及正则化、增加图像中心上的梯度上升的焦点的惩罚和平滑度。
Nguyen 在 2019 年对显著性图进行了审查
不过,这是神经网络的一个非常详细的视图,我们缺乏对类和层的概述。
降维
分类神经网络正在输出一个非常精炼和精简的度量:每一类的概率,更概括为概率最大的那一类的指标。基于这些,通常的度量是准确度,其仅计算匹配的预测类别相对于实际类别的数量。正如我在巴黎电信的一位老师所说:
“分类神经网络的最后一层是一个非常简单的检测器,即 logistic 或多类回归(softmax)中的一种。该网络的强大之处在于,它是一个高度非线性的复杂函数,需要对该检测器的输入进行整形。”
许多信息出现在最后一层的输入端。它提供了对网络行为的洞察。然而,问题和以前的技术一样:维度非常高,不容易表示。
一套通用的降维技术被用于将这些高维空间显示为 2D(或 3D)空间中的流形:
t 分布随机邻居嵌入(t-SNE)
“t-分布式随机邻居嵌入(t-SNE)是一种(获奖)的降维技术,特别适合于高维数据集的可视化。该技术可以通过 Barnes-Hut 近似实现,从而可以应用于大型真实数据集。我们将它应用于多达 3000 万个例子的数据集。”
一致流形逼近和降维投影(UMAP)
UMAP 是一种新颖的流形学习降维技术。UMAP 是从基于黎曼几何和代数拓扑的理论框架中构建的。结果是一个实用的可扩展算法,适用于现实世界的数据。在可视化质量方面,UMAP 算法与 t-SNE 算法具有竞争力,并且可以说保留了更多的全局结构,具有更好的运行时性能。此外,UMAP 对嵌入维度没有计算限制,这使其成为机器学习的通用降维技术。”
如果我们看一下简单的 MNIST 数字数据集,我们可以用 UMAP 直接处理它:
UMAP 投影到 2D 的 MNIST 9 位数 28x28 像素图像数据集
这些颜色对应于真实数字类别。我们已经看到了类簇的很好的分离,但是有重叠的部分。
如果我们重用第 1 部分的密集网络并处理 softmax 层输入,我们会看到类簇被更好地分离并且更紧凑:
MNIST 的 UMAP 视图经过密集网络处理,直至最后一层输入
使用这个用散景制作的漂亮的显示器,我们可以检查边界上的样本,可能会分类错误

放大具有密集网络的错误分类的 5 位数
使用 LeNet5 CNN 架构执行相同的 UMAP 投影:

由 LeNet5 网络处理直到最后一层输入的 MNIST UMAP 视图
CNN 可以更好地分离集群,使 CNN 在密集网络上更具优势。
美国有线电视新闻网提供了一组边界样本的详细信息:

使用 LeNet5 CNN 放大错误分类的 0
网络和数据集概述
这些技术中的大多数应用于神经元单元水平,并应用于一个或几个图像。我们显然缺少整体网络视图和域(数据集)视图。
由 Carter 等人提出的激活地图集正在解决数据集概述的挑战。显著图是在数据集的大样本上计算的,并使用 t-SNE 或 UMAP 进行聚类。

卡特等人的激活地图集。来自谷歌大脑和 OpenAI
我们已经创建了一个 Github 项目,深度神经网络查看器,来处理玩具网络上的网络视图。这个项目是年轻的,不完整的,但已经提供了一些不错的看法和 CNN 和 DNN 的检查。这将在以后的文章中更详细地介绍。
CIFAR-10 简单 CNN 上的 DNN 观众截图
该方法不同于 Tensorboard 图或 Netron 图,它们显示网络拓扑,但不将其与实际性能和参数(权重、梯度)联系起来。
结论
我们回顾了一些实际的技术来检查深度神经网络的内容,并对其结果(分类)进行解释。我们已经表明,卷积网络(CNN)更容易检查,因为它们在卷积层中保留了图像的 2D 结构。在我们的例子中,我们已经观察到,当用 UMAP 投影表示最后一层的输入时,CNN 在密集 DNN 上的性能增益是可见的。
在这篇文章中,我们专注于一个单一的任务,图像分类,这是由深度神经网络处理的许多任务之一。已经列出了许多不同的工具和方面,并显示了它们的限制。深度神经网络的可解释性是一个非常广阔的活跃研究领域,对这些系统行为和鲁棒性的更多证明的需求仍然是趋势。我们可能会在以后的帖子中进一步处理它。
本帖中使用的笔记本
以下是本文中使用的笔记本,来自数据科学分步指南库:
- 密集和 LeNet5 设计,权重直方图: CnnVsDense-Part1.ipynb
- 激活地图:CNN visualization-1-activations . ipynb
- 显著图:CNN visualization-2-salice maps . ipynb
- UMAP 图表:CnnVsDense-part 2-visualization . ipynb
使用 Pytorch 的密集视频字幕
如何在一个视频中为不同的时间段制作多个字幕

介绍
深度学习任务 视频字幕 ,过去几年在计算机视觉和自然语言处理的交叉领域相当流行。特别是, 密集视频字幕 ,这是一个子领域,已经在研究人员中获得了一些牵引力。密集视频字幕的任务是从未经剪辑的视频中定位感兴趣的事件,并为每个事件生成单独的文本描述。
模型
密集视频字幕具有挑战性,因为它需要视频的强上下文表示,并且能够检测局部事件。大多数模型通过将这个问题分解为两步来解决:从视频中检测事件提议,然后为每个事件生成句子。当前最先进的算法 具有建议生成器的双模式变换器 (BMT) 提出组合两个输入通道,以便进行密集视频字幕:视频和音频信息。它在 ActivityNet 字幕数据集 上实现了最先进的性能,该数据集由数千个视频和与特定时间范围相关联的字幕组成。

BMT 建筑(来源)
BMT 架构包括三个主要组件:双模态编码器、双模态解码器,以及最后的建议生成器。
首先,视频的音频和视频分别使用和进行编码。在特征提取之后,VGG 和 I3D 特征被传递到双模式编码器层,在那里音频和视觉特征被编码成本文所称的音频参与的视觉和视频参与的音频。这些特征然后被传递给提议生成器,该生成器接收来自两种设备的信息并生成事件提议。****
在事件提议生成之后,根据事件提议来修剪视频。从特征提取开始,每个短剪辑被再次传递到整个中。提取音频和视频特征,传递到双模式编码器,然后传递到双模式解码器层。这里,解码器层接受两个输入:来自双模式编码器的最后一层的输出,以及最后生成的字幕序列的 手套嵌入 。最后,解码器对内部表示进行解码,并基于概率分布生成下一个单词,该单词被添加到先前的字幕序列中。
履行
在本文中,我们将向您展示如何使用预训练的 BMT 来执行密集的视频字幕给定的视频。不需要模型训练。
步骤 1:下载 Repo 并设置环境
通过以下方式下载论文的官方知识库:
**git clone --recursive [https://github.com/v-iashin/BMT.git](https://github.com/v-iashin/BMT.git)
cd BMT/**
下载 VGG 和 I3D 模型和手套嵌入。脚本会将它们保存在./data和./.vector_cache文件夹中。
**bash ./download_data.sh**
用所有需要的库和依赖项设置一个conda环境:
**conda env create -f ./conda_env.yml
conda activate bmt
python -m spacy download en**
第二步:下载视频
现在,你可以得到你想要的视频。例如,我将从 Youtube 上获得一个关于最近全球冠状病毒疫情的短片。我得到了这个一个:

疫情 Youtube 视频(来源)
您可以使用在线下载程序下载 Youtube 视频,但请谨慎使用,风险自担!下载后,你可以把它保存在你喜欢的地方。我在BMT项目文件夹下创建了一个test文件夹,将下载的视频复制到test文件夹。
**mkdir test
# copied video to the test directory**

下载视频后(图片由作者提供)
步骤 3:特征提取(I3D 和 VGGish)
获得视频后,现在是提取 I3D 特征的时候了,首先创建conda环境,然后运行 python 脚本:
**cd ./submodules/video_features
conda env create -f conda_env_i3d.yml
conda activate i3d
python main.py \
--feature_type i3d \
--on_extraction save_numpy \
--device_ids 0 \
--extraction_fps 25 \
--video_paths ../../test/pandemic.mp4 \
--output_path ../../test/**
使用类似的过程提取 VGGish 特征:
**conda env create -f conda_env_vggish.yml
conda activate vggish
wget https://storage.googleapis.com/audioset/vggish_model.ckpt -P ./models/vggish/checkpoints
python main.py \
--feature_type vggish \
--on_extraction save_numpy \
--device_ids 0 \
--video_paths ../../test/pandemic.mp4 \
--output_path ../../test/**
运行上述脚本后,I3D 和 VGGish 特性将保存在test目录中。保存的特征包括 RGB 视觉特征(pandemic_rgb.npy)、光流特征(pandemic_flow.npy)和音频特征(pandemic_vggish.npy)。

特征提取后(图片由作者提供)
步骤 4:在视频上运行密集视频字幕
导航回主项目文件夹,然后激活之前设置的bmt环境。最后,我们可以使用下面的命令运行视频字幕:
**cd ../../
conda activate bmt
python ./sample/single_video_prediction.py \
--prop_generator_model_path ./sample/best_prop_model.pt \
--pretrained_cap_model_path ./sample/best_cap_model.pt \
--vggish_features_path ./test/pandemic_vggish.npy \
--rgb_features_path ./test/pandemic_rgb.npy \
--flow_features_path ./test/pandemic_flow.npy \
--duration_in_secs 99 \
--device_id 0 \
--max_prop_per_vid 100 \
--nms_tiou_thresh 0.4**
prop_generator_model_path和pretrained_cap_model_path指定建议生成器模型路径和字幕模型路径。因为我们正在使用两个预训练模型,所以我们可以将其直接链接到之前保存预训练模型的路径。vggish_features_path、rgb_features_path和flow_features_path是保存相应特征的路径,duration_in_secs是以秒为单位的视频持续时间,device_id是要使用的 GPU 号,max_prop_per_vid是要搜索的最大建议数(超参数),最后nms_tiou_thresh是非最大抑制阈值参数。
结果
执行密集视频字幕后,以下是打印的结果:
**[
{'start': 2.9, 'end': 25.2, 'sentence': 'A person is seen sitting on a table and leads into a woman speaking to the camera'},
{'start': 0.0, 'end': 61.9, 'sentence': 'A man is seen speaking to the camera and leads into several shots of people working on a building'},
{'start': 0.0, 'end': 12.7, 'sentence': 'A woman is sitting in a chair talking to the camera'},
{'start': 78.6, 'end': 100.0, 'sentence': 'The man then takes the cube and shows the cube off the table'},
{'start': 0.2, 'end': 5.2, 'sentence': 'A man is sitting on a chair with a woman sitting on a chair and talking'},
{'start': 38.8, 'end': 100.0, 'sentence': 'A man is seen speaking to the camera and leads into several shots of people working out and speaking to the camera'}
]**
结果给出了开始和结束时间的列表,以及描述该时间段内视频内容的句子。在观看并与视频本身进行比较后,我必须说,该模型在理解视频和考虑音频方面表现得相当好!
这可以应用于任何视频,所以请随意尝试~!这篇文章是基于官方知识库的,所以一定要去看看。
结论
本文向您展示了如何使用预先训练好的模型为单个视频中的不同时间段生成多个字幕。该模型的性能被证明是相当好的,并且有更多的改进可以在将来应用于该模型和密集视频字幕任务。
有关深度学习的更多教程,请随时查看:
**** [## 使用 Pytorch 的 BERT 文本分类
文本分类是自然语言处理中的一项常见任务。我们应用 BERT,一个流行的变压器模型,对假新闻检测使用…
towardsdatascience.com](/bert-text-classification-using-pytorch-723dfb8b6b5b) [## 使用 Pytorch 微调用于文本生成的 GPT2
使用 Pytorch 和 Huggingface 微调用于文本生成的 GPT2。我们在 CMU 图书摘要数据集上进行训练,以生成…
towardsdatascience.com](/fine-tuning-gpt2-for-text-generation-using-pytorch-2ee61a4f1ba7) [## 控制语言模型的文本生成
控制机器生成文本的样式和内容的实际操作方法
towardsdatascience.com](/controlling-text-generation-from-language-models-6334935e80cf) [## 基于 Pytorch 的 LSTM 文本分类
一步一步的指导你如何在 Pytorch 中建立一个双向 LSTM!
towardsdatascience.com](/lstm-text-classification-using-pytorch-2c6c657f8fc0) [## 用 NLTK 进行文本预处理
NLTK 教程 NLP 预处理:小写,删除标点,标记化,停用词过滤,词干,和…
towardsdatascience.com](/nlp-preprocessing-with-nltk-3c04ee00edc0)
参考资料:
[## 更好地利用视听线索:使用双模式转换器的密集视频字幕
密集视频字幕旨在定位和描述未剪辑视频中的重要事件。现有的方法主要是…
arxiv.org](https://arxiv.org/abs/2005.08271) [## 沃伊申/BMT
这是我们论文的 PyTorch 实现:更好地使用视听提示:具有双模式的密集视频字幕…
github.com](https://github.com/v-iashin/BMT) [## BMT -弗拉迪米尔·雅辛
密集视频字幕旨在定位和描述未剪辑视频中的重要事件。现有的方法主要是…
v-iashin.github.io](https://v-iashin.github.io/bmt) [## 视频中的密集字幕事件
大多数自然视频包含大量事件。例如,在一个“弹钢琴的人”的视频中,该视频也可能…
arxiv.org](https://arxiv.org/abs/1705.00754) [## 视频中的密集字幕事件
A.添加上下文可以生成一致的标题。b .比较在线模型和完整模型。c .上下文可能会添加更多…
cs.stanford.edu](https://cs.stanford.edu/people/ranjaykrishna/densevid/) [## 视频字幕深度学习研究综述
陈,,蒋玉刚第二十八届国际人工智能联合会议论文集
www.ijcai.org](https://www.ijcai.org/Proceedings/2019/877)****
基于密度的算法
对两种基于密度的算法的理解:DBSCAN 和 OPTICS

像划分方法或层次聚类这样的聚类方法在寻找任意形状的聚类时是无效的。基于密度的聚类方法在发现任意形状的聚类方面是有效的,并且防止了离群值和噪声。
当使用基于密度的方法时,对象聚类简单地基于密度的概念。并且根据密度,使用该方法创建不同类型的算法,例如,如果通过使用邻域对象的密度创建聚类,则使用 DBSAN 算法,或者如果根据密度函数创建聚类,则使用 DENCLUE。而光学是基于密度的,这产生了数据收集结构的增强顺序。
基于密度的噪声应用空间聚类
DBSCAN 通过计算固定半径邻域或 ɛ 中的点的数量来估计密度,并认为只有当两个点位于彼此的邻域内时它们才是连通的。因此,该算法使用两个参数,如ɛ和 MinPts。ɛ表示一个点的 Eps 邻域,MinPts 表示 Eps 邻域中的最小点。所以ɛ和 MinPts 是由用户指定的参数
有几个要点需要记住:
核心点: 作为核心点的是 Eps 邻域中的某个特定点,该点的值大于 MinPts 的精确点数。
****噪声点:不属于核心或边界的点称为噪声点。

密度点
算法
输入:n 个待聚类对象和全局参数 ɛ 和 MinPts 。
输出:物体的集群
1.任意选择一个点 P.
2。检索从 P wrt ɛ和 MinPts 可到达的所有点密度。
3。如果 P 是一个核心点,则形成一个簇。
4。如果 P 是边界点,那么不存在密度可达的点,DBSCAN 移动到下一个点。
5。这个过程一直持续到所有的点都被处理完。
当然,使用 DBSAN 有一些优点和缺点,例如:
优点 - DBSCAN 可以使用 MinPts 参数找到任意形状的聚类
-数据库中的点的顺序不敏感
-处理噪声和异常值
缺点
-在密度差异较大的情况下不能很好地执行
-不适合涉及各种密度的情况
光学
光学系统的工作原理类似于 DBSCAN 的扩展。唯一的区别是它不分配聚类成员,而是存储处理点的顺序。所以对于每个对象商店:核心距离和可达性距离。订单种子被称为构成输出订单的记录。
核心距离:p 的ɛ-neighborhood 中出现的ɛ的最小值就是核心距离。当然,它需要保存最少的 MinPts 对象。
可达距离:p 与 q 之间的可达距离定义为从 q 到 p 密度的最小半径值。
算法
1.随机选择一个未访问的点 P
2。选择从 P . w . r . t . Eps,MinPts 可达的所有点的密度。
3。分配核心距离&可达性距离=空值
4。如果 P 不是核心点
5。移动订单种子列表中的下一点
6。如果 P 是核心点
7。对于每个物体 q,在 P
8 的ɛ邻域中。从 P
9 更新可达性距离。如果 q 未被访问,将 q 插入订单种子
10。直到没有不被访问的对象
注:以上算法摘自《基于密度的大数据聚类算法综述》。
优点
- 它不需要密度参数。
- 聚类顺序对于提取基本的聚类信息很有用。
缺点
——它只产生一个集群排序。
- 它不能处理高维数据。
注: 认为只存在上面解释的这两种基于密度的算法是不好的。还有其他这类算法在这里没有提到,例如 DENCLUE,但最流行的是 DBSCAN,因为它被认为是最简单的基于密度的方法。
结论
本文旨在简要解释基于密度的方法。因此,总而言之,基于密度的方法满足这些要求:
——产生实际上只发生在空间数据上的非球形聚类。术语空间数据用于表示点、线和多边形。在空间数据簇中形成的簇可以具有任意形状。
-大型数据库对后续全效率的需求。
-检测和减少噪音和离群值的能力。
光学和 DBSCAN 不是实现基于密度的方法的唯一算法。尽管我提到了它们,但这并不意味着只需要使用这些算法。然而,这些算法是最受欢迎的,每种基于密度的算法都有其优点和缺点,因此在使用它之前,您需要查看数据集,首先了解数据集,看看该类型的算法是否符合您的需求。
参考
T.米兰达·拉克什米、约瑟芬·萨哈纳、普拉桑娜·文卡特桑。基于密度的大数据聚类算法综述
数据聚类:算法和应用(查普曼和霍尔/CRC 数据挖掘和知识发现系列,第 113-117 页
Apache 气流中 Dag 之间的依赖关系

仅在两个上游 DAG 成功完成后运行“再见”任务的 DAG。这篇文章解释了如何在 Apache Airflow 中创建这样的 DAG
在 Apache Airflow 中,我们可以有非常复杂的 Dag,包含几个任务,以及任务之间的依赖关系。
但是,如果我们有跨 DAG 的依赖关系,并且我们想创建 DAG 中的 DAG,该怎么办呢?通常,我们会尝试将所有有依赖关系的任务放在同一个 DAG 中。但是有时您不能修改 Dag,并且您可能仍然希望在 Dag 之间添加依赖关系。
为此,我们可以使用外部任务传感器。
该传感器将查找 DAG 和任务的过去执行,并将匹配那些与我们的 DAG 共享相同的 execution_date 的 DAG。然而,名字 execution_date 可能会引起误解:它不是一个日期,而是一个瞬间。因此,它们之间相互依赖的 Dag 需要在同一时刻运行,或者以恒定的时间量一个接一个地运行。总之,我们需要在执行日期和时间上保持一致。
让我们看一个例子。我们有两个上游 DAG,我们希望在前两个 DAG 成功完成后运行另一个 DAG。
这是第一个 DAG。它只有两个虚拟任务。
第二个上游 DAG 和这个很像,这里就不展示代码了,不过你可以看看 Github 里的代码。
重要的一点是两个 DAG 具有相同的计划和开始日期(请参见 DAG 1 和 DAG 2 中的相应行)。请注意,dag 每分钟都在运行。那只是为了这个演示。在真实环境中,这将是一个非常高的频率,所以如果您为自己的 Dag 复制粘贴一些代码,请小心。
当两个上游 DAG 都成功时,将执行下游 DAG。这是下游 DAG 的代码:
一些需要注意的要点。计划和开始日期与上游 Dag相同。这对于该 DAG 响应上游 DAG 是至关重要的,即,在上游 DAG 的运行和该 DAG 的运行之间添加依赖性。
如果执行日期不匹配,但我仍然想添加一个依赖项,该怎么办?如果开始日期相差固定的时间量,您可以使用外部任务传感器的执行 _delta 参数。更多详情,查看 ExternalTaskSensor 的文档。
Airflow 的文档包括一篇关于跨 DAG 依赖的文章:https://air flow . Apache . org/docs/stable/how to/operator/external . html
如果我想根据前面 Dag 的结果在不同的下游 Dag 上进行分支,该怎么办?为此,您可以使用分支操作符和 XCOM 在 Dag 之间传递值。
ExternalTaskSensor 将仅接收与“感应到的”DAG 相对应的成功或失败状态,但不接收任何输出值。如果需要根据任务中计算出的值进行分支,可以使用branch python operator(https://air flow . Apache . org/docs/stable/concepts . html # branch
上游 DAG 必须在 XCOM 中发布值,下游 DAG 需要向分支操作符提供回调函数。这个回调函数将使用上游的 task_id 读取 XCOM,然后它将返回这个任务之后要继续执行的任务的 id (在分支操作符之后的下游要执行的潜在任务列表中)——我将在以后的文章中用代码片段介绍这个例子!
当您无法修改现有 Dag 时,这并不意味着您无法在这些 Dag 之间创建依赖关系。这篇文章展示了如何创建这些依赖关系,即使您不控制上游 DAG:添加一个依赖于使用 ExternalTaskSensor 的新 DAG(每个上游 DAG 一个传感器),将 DAG 之间的依赖关系编码为传感器任务之间的依赖关系,在与上游 DAG 相同的时间表中运行编码依赖关系的 DAG,如果 DAG 的时间表移动了恒定的时间量,则使用相应的 execution_delta 配置传感器。
全栈 PyTorch 人群规模估计量
查理·麦基,杰森·戴尔和但丁·德鲁卡
演示
请尝试我们的人群规模估计器的演示:https://app 3-qhrzckmpq-UE . a . run . app
你可以从 ShanghaiTech 数据集中选择一些图片,也可以上传自己的图片。如果你选择上传自己的图像,它必须是 JPG/JPEG 格式,并且小于 100KB。
您可以按如下方式检查图像尺寸:
计算机:
- 窗口:资源管理器→选择图像(窗口底部)。
- Mac:按住 Control 键并点击→“获取信息”→“大小”
手机:
- iPhone:确保图像不是截图,然后你可以“选择大小”的图像(屏幕底部)。选择“小”并上传。
- 安卓:看看这篇博文,https://www . quora . com/How-do-I-reduce-the-size-of-photos-in-Android
介绍
在这篇文章中,我将解释我的西部人工智能项目团队如何开发一个 web 应用程序来估计给定图像中人群的大小。
我们从 2019 年 9 月开始的目标是部署一个可以预测人群规模的机器学习模型。我们实现了我们的目标,并能够在由女王人工智能中心主办的加拿大人工智能本科生会议上展示我们的项目。
人群规模估计是机器学习社区中的一个热门话题。它有多种应用,包括人群控制、客户管理和城市规划。我们的模型可以应用于学校环境,测量课堂出勤率或建筑物占用率。
最终产品


上图是我们部署的 web 应用程序。web 主机从用户那里获取 JPG 格式的本地图像,然后估计人群的大小(人数)。
目的
这篇文章的目的是:
- 展示我们的项目:尺寸。人工智能
- 深入了解当今的人群识别和机器学习
- 提供部署机器学习模型的教程
议程
这篇文章的结构如下:
- 机器学习、计算机视觉和人群规模估计简介
- 当前人群规模估计方法
- 我们的方法:CSRNet
- 培训、测试和验证(Google Colab/Python3)
- 部署(Flask/Google 云)
- 下一步、来源和西方人工智能
机器学习、计算机视觉和人群规模估计的介绍
人工智能(AI)和机器学习(ML) 含义不同。机器学习是一种人工智能,涉及统计分析和问题分类。流行的机器学习应用包括自然语言处理(NLP)和计算机视觉(CV)。这些应用程序由机器学习算法驱动,包括 K 近邻(kNN)、回归和神经网络。
让我们关注神经网络。神经网络是由我们大脑的结构松散地启发的。在大脑中有一个神经元网络,每个神经元存储一些信息。神经元通过轴突相互连接,轴突可以在神经元之间传递信号。在人工神经网络中,神经元由组织成层的节点表示。

来自:s . Logan:“理解神经网络的结构”
第一层节点可以采用某种形式的输入,每一层的处理都将有助于对输入进行分类。最后一层表示容易解释的输出。
例子:计算机想要确定一幅图像中包含一只狗还是一只猫。图像将被分解成像素,每个像素将由一个 RGB 比例值(0–255)表示。RGB 值是第一层节点的输入。之后的每一层可以代表图像内的某种类型的特征检测;眼睛的重叠,头的大小与耳朵的大小的比较…等等。最后一层节点汇总了前几层的所有信息并做出决策。
机器学习的“学习”部分,包括迭代通过许多标记有元数据的例子,这些元数据已经被人类分类。神经网络经历反向传播过程,其中网络的误差被最小化。对于提供的每个示例,网络将进行预测,然后用提供的元数据验证其预测,并得出误差成本(预测-实际)。反向传播的目标是通过调整网络来最小化这种误差。
这背后的数学比我刚才解释的更复杂。如果你仍然感兴趣,可以看看 Jayson(项目经理),神经网络的简单分类器介绍。
人群规模估计
人群规模估计使用神经网络对人群中的人进行分类,然后合计检测到的人数。目前有三种人群规模估计方法:检测、回归和密度。
- 检测:专注于物体检测;识别人的特征(例如:头、肩、身体等)。这种方法通常对人数较少的人群更准确。
- 回归:使用一个人更广泛的特征,把更多的注意力放在边缘细节上。当面对更密集的人群时,这优于检测模型。
- 密度:(见下面的密度图示例)密度图不是聚焦于单个人,而是追踪人群。这是对密集人群最准确的方法,也是我们选择的模型 CSRNet 使用的方法。


密度图(右)
CSRNet
拥挤场景识别网络(CSRNet) 是由伊利诺伊大学厄巴纳-香槟分校的计算机科学家在 2018 年提出的人群规模估计模型。
CSRNet 利用 VGG-16 图像分类网络作为前端部分,因为它具有灵活有效的架构。VGG-16 使用各种激活功能(用于提取层间节点输出)和其他超参数(层/节点配置),包括 ReLU 和 SoftMax。ReLU 是机器学习中的标准,意思是校正的线性单元。SoftMax 不太常见,但值得注意。SoftMax 的目标是把数字变成概率,把分类两极分化。这在最后一层的影像分类中非常有用,因为它为任何分类场景提供了概率。由于我们的目标是输出一个密度图,而不是一个热分类,CSRNet 的后端结构用更多的卷积层取代了全连接和 SoftMax 层。

VGG-16 结构
扩展内核:在后端,使用扩展卷积层来代替最大池,以便保持输出维度并增加感受域。膨胀核是一个标准的卷积核,由一个膨胀因子分散(见下文)。膨胀的核不会降低图像质量,这一点很重要,因为密度图的尺寸越大,我们的估计就越准确。
膨胀的卷积有助于生成我们的密度图:


增大膨胀系数:1 → 2 → 3
结果 : CSRNet 取得了比其他流行的人群规模估计网络更好的 MAE 和 MSE 结果。

对于更多的上下文, MAE 是平均绝对误差。平均绝对误差是每个训练图像的绝对误差的平均值。MSE 是均方误差。MSE 不同于 MAE,因为它更强调大误差。

培训、测试和验证(Google Colab/Python3)
既然女王的学生都走了——我们来编码吧!我们使用了来自 Analytics Vidhya 的教程:构建你自己的人群计数模型。我们将所有的预处理、训练、测试和验证脚本存储在一个 Google Drive 文件夹中。在 Google Drive 中,我们能够使用 Google Colab 笔记本来创建和共享我们的模型。在某些情况下,所有脚本都是用 Python 3 或 Python 2 编写和编译的。为了训练我们的模型,我们还安装了 CUDA GPU。
我们使用了上海科技馆的数据集,因为它具有摄像机视角的广度、人群规模的多样性以及大量的注释数据。该数据集包含近 1200 张图片和超过 330,000 个带注释的头像。
Google Drive 中的培训和测试的最终目标是生成我们经过培训的模型。PT 文件(PyTorch 文件),我们可以上传到我们的前端界面。为了达到这个目标,我们必须编译并运行:
- 地面真实生产脚本
- 培训脚本
- 验证脚本
地面实况生成脚本:该脚本的目的是将数据集提供的地面实况转换成可用于训练的密度图。
下面你可以看到一个输出的例子。将地面实况转换成密度图。


显示密度图中的原始预测计数:
np.sum(groundtruth) # Output -> 166.15
训练脚本:训练脚本遍历我们所有的训练数据集图像,并提高每个历元之间的准确性(历元是对数据的一次迭代)。
使用我们的第一个数据集运行训练脚本的示例代码:
root = "/content/gdrive/My Drive/Western AI - Intro to Computer Vision Project/CSRNet Crowd Counting Model/Data/"!python2 '/content/gdrive/My Drive/Western AI - Intro to Computer Vision Project/CSRNet Crowd Counting Model/train.py' '/content/gdrive/My Drive/Western AI - Intro to Computer Vision Project/CSRNet Crowd Counting Model/part_A_train.json' '/content/gdrive/My Drive/Western AI - Intro to Computer Vision Project/CSRNet Crowd Counting Model/part_A_test.json' 0 0
以下是其中一个训练时期(第 15 个)的快照:

在时间和资源允许的情况下,我们能够为 100 个完整的时期训练我们的模型。在监控训练时,我们注意到 MAE 在每个时期都有轻微的改善。如果你看上面的输出,第 15 个纪元的 MAE 是 70.621。这意味着平均误差是 70.621 人(+/-)。第一纪元的 MAE 是 250,所以我们取得了一些进展。根据数据集的大小(1200 张图片)和每个人群的总规模(330,000 人),每个人群中平均有 275 人。考虑到大规模的人群,我们的误差是令人满意的。
验证脚本:该脚本采用我们训练过的模型,并确定每个测试示例的平均误差和百分比误差。(注意:这是验证脚本的抽象版本)
checkpoint = torch.load('/content/gdrive/My Drive/Western AI - Intro to Computer Vision Project/CSRNet Crowd Counting Model/model.pt')model.load_state_dict(checkpoint['state_dict'])import numpy as np
mae = []
for i in xrange(len(img_paths)): ... mae.append(abs(np.sum(groundtruth)))
print i, mae[i]
结果各不相同,但最终测试的平均平均误差为 90.19。这与来自训练脚本的 MAE 值有很好的相关性,并且不表明我们的训练集有任何显著的过拟合/欠拟合。以下是一些结果的片段:



我们运行了这个验证脚本的一个类似变体,它给出了我们的模型误差/准确性。上述 MAE 值对应于 15.3%的总测试误差(两个测试集:A 和 B)。这意味着我们的模型有 84.7%的准确率。
Model.pt: 经过训练和测试后,我们将模型导出到一个. pt 文件(PyTorch ),可以部署到 Flask 上。model.pt 文件包含存储在大规模字典对象中的所有网络参数和权重。

调配(烧瓶)
您可以在这里查看我们的 Flask 部署的 GitHub 库:https://github.com/jaysondale/Size.AI-Deployment
Flask 是一个 Python web 框架,采用易于扩展的理念(https://www.fullstackpython.com/flask.html)构建。启动您自己的 web 应用程序就像运行具有以下结构的“app . py”Python 文件一样简单:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello, World!'
if __name__ == '__main__':
app.run()
在我们的部署框架中,有 5 个关键组件 :
- App—启动我们的本地主机端口 5000
- 推论——初始化我们的模型并做出预测
- commons—引用我们的模型文件
- Model.pt —我们训练过的模型
- 模板—包含索引和结果模板(渲染结果页面)


在 Cameo 系统建模器中设计的 UML
App(' App . py '):hello _ world 函数(如上)返回要在 web app 中显示的内容和功能。在我们的例子中,我们需要接受来自用户的图像并返回一个预测。当处理用户输入时,我们需要使用 HTTP 方法。“GET”呈现我们想要的模板,“POST”注册可以执行操作(上传文件)的用户。在这里,您可以看到“app.py”文件中的“上传文件”功能:
def **upload_file()**:
if request.method == 'POST':
absolute_path = os.path.abspath("../")
if 'file' not in request.files:
return redirect(request.url)
file = request.files['file']
if not file:
return
print("GETTING PREDICTION")
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'],filename))
prediction = **get_prediction**(file)
return **render_template**('result.html', Prediction=prediction, File=filename)
return render_template('index.html')
推论(' inference.py'): 初始化我们的模型,并从中获得一个预测。应用程序脚本从用户处发送了一个文件作为参数。get_prediction 函数将图像发送到模型并输出结果:
model = get_model() **# initialize model**def get_prediction(file):
img = transform(Image.open(file).convert('RGB')).cpu()
output = model(img.unsqueeze(0))
prediction=int(output.detach().cpu().sum().numpy()) **# prediction**
print("Predicted Count: ",int(output.detach().cpu().sum().numpy()))
return prediction
Commons ('commons.py'): 引用我们的 model.pt 文件。我们从 PyTorch 导入并初始化 CSRNet,然后加载我们的状态字典(来自训练的权重和偏差):
def get_model():
model = CSRNet() **# original CSRNet**
model.load_state_dict( torch.load('/Users/charliemackie/CSRNET_DEPLOYMENT/SIZE.AI/Pytorch/model (2).pt', map_location='cpu')) **# local reference to model.pt**
model.eval()
return model
'/Users/charliemackie/CSR net _ DEPLOYMENT/SIZE。AI/Pytorch/model (2)。“pt”是保存在我们的项目目录中的 Model.pt 的路径。
模板:有我们的自定义 HTML 和 CSS 模板,将显示我们的用户界面。这些文件结合了文本标签、按钮和标题。最重要的部分是显示我们的预测,它嵌入在文本正文中,如下所示:
<h2 class="h5 mb-3 font-weight-normal"><i>**{{Prediction}}**</i></h2>
所有这些组件一起工作,我们有我们的功能烧瓶应用程序!
部署(谷歌云)
我们的部署过程利用了谷歌云的三个核心特性:云存储、构建和运行。创建基于云的 web 系统的第一步是将我们的 flask 应用程序容器化,这意味着它将包含在任何给定的计算机系统上运行的所有要求和命令。运行时,云平台被编程为监听 IP 地址为 0.0.0.0:8080 的特定网络端口。这个 IP 和端口被直接硬编码到 flask 应用程序中。将以下文件添加到 flask 应用程序目录中,以完成容器化过程:
需求(“Requirements . txt”):这个文件包含应用程序运行所需的所有 python 模块。
Docker(“Docker file”):这个文件包含一系列启动 flask 应用程序的 CLI 命令。
Dockerfile 文件内容:
FROM python:3
RUN apt-get update -y
RUN apt-get install -y python-pip python-dev build-essential
COPY . /app
WORKDIR /app
RUN pip install -r requirements.txt
ENTRYPOINT [“python”]
CMD [“app.py”]
YAML(“Cloud build . YAML”):这个文件与 Google Cloud 命令行界面(CLI)一起使用,并提供额外的构建参数(这包括构建目的地)。
Yaml 文件内容:
steps:
- name: ‘gcr.io/cloud-builders/docker’
args: [‘build’, ‘-t’, ‘gcr.io/size-ai/app’, ‘.’]
- name: ‘gcr.io/cloud-builders/docker’
args: [‘push’, ‘gcr.io/size-ai/app’]
images: [‘gcr.io/size-ai/app’]
一旦添加了这些文件,容器化的应用程序需要被压缩并上传到 Google 云存储中,以便在 web 服务中使用。一旦上传,Google Cloud Build 将遵循 cloudbuild.yaml 提供的步骤,并构建一个基于云的应用程序,该应用程序将准备好进行部署。在 size-deployment 目录中执行了以下命令来完成这两项任务。
$ gcloud builds submit
默认情况下,gcloud 接口会查找“cloudbuild.yaml”并完成上传和构建过程。一旦构建完成,就会在 Google Cloud Run 中创建一个 web 服务来托管容器化的应用程序。在配置服务时,我们使用了 2gb 和 900 秒的最大内存和超时余量,让用户有机会上传最高质量的图像。一旦选择了构建版本,我们的应用程序就成功地部署在 Google Cloud 上了!
Google Cloud dashboard(下图)让我们可以分析许多有用的指标,包括:请求计数、请求延迟、容器 CPU 利用率和容器内存利用率。通过“请求计数”指标,我们可以查看已经运行的应用程序的每个实例。

下一步,西方人工智能和来源
下一步:
- 调整超参数 : 我们希望尝试调整网络以获得更好的结果。超参数可能意味着层数、层大小或激活函数。目前,我们运行现成的 VGG-16/CSRNet 结构——有许多修改的可能性。我们强调的一些领域包括调整学习率和/或在增强型 GPU 上使用更长的训练时间。我们想在不久的将来在对数尺度上测试不同的学习速度。
- 优化器选择:我们的模型目前使用随机梯度下降(SGD)优化器。这意味着小批量大小为 1,并且在每个训练示例之后执行梯度下降。我们已经讨论了用 Adam 优化器或 RMSprop 进行试验。一旦我们实现了一个新的优化器,我们将有更多的超参数需要优化,包括调整我们的学习率。
- 大规模部署:由于模型的大小,我们的 web 应用程序目前是有限的。一个潜在的解决方案是使用迁移学习来训练更有效的模型版本。我们受到了 Geoffrey Hinton 的启发,他在 CUCAI re: Transfer Learning 上向我们展示了开发轻量级 ML 模型的方法。如果我们做到了这一点,我们可以考虑发布一款 IOS 应用。
西方艾:
Western AI 是西部大学第一个由学生领导的组织,旨在为校园人工智能创建一个社区。这意味着我们正在为有兴趣接触人工智能的学生建立一个基础,让他们相互认识,学习真正的技能,并培养对理解人工智能在各种行业和经济中的全球影响的重要性的认识。
仅在大学学生会(USC)批准运营的第一年,我们就正式吸纳了 170 多名学生成员,并与众多教授、行业专家和其他学生组织合作,在令人印象深刻的短时间内创建了一个非常强大的社区。我们相信有这么大的发展空间,有无数的机会。
来源:
CSRNet 的 Vidhya 实施:
[## 这是破纪录的人群!一个必读的教程来建立你的第一个人群计数模型,使用…
人工智能和机器学习将在未来十年成为我们最大的帮手!今天早上,我在…
www.analyticsvidhya.com](https://www.analyticsvidhya.com/blog/2019/02/building-crowd-counting-model-python/)
烧瓶中的 PyTorch:
点击这里查看演示。如果你想检查一个超级简单的 API 服务器,那么检查这个 repo。从…安装它们
github.com](https://github.com/avinassh/pytorch-flask-api-heroku)
CSRNet 原始论文:
[## CSRNet:用于理解高度拥挤场景的扩展卷积神经网络
我们提出了一个用于拥挤场景识别的网络,称为 CSRNet,以提供数据驱动和深度学习的方法…
arxiv.org](https://arxiv.org/abs/1802.10062)
非常感谢我的西部人工智能团队:安迪·马夫鲁迪斯,萨姆·韦勒,帕拉斯·阿胡贾,丹特·德卢卡和杰森·戴尔。
如有任何问题或意见,请随时联系杰森或我。
邮箱:Cmacki43@uwo.ca,Jdale29@uwo.ca
领英:【https://www.linkedin.com/in/charlie-mackie-749ba314b/https://www.linkedin.com/in/jaysondale/T4
将 Dockerized Flask 应用程序部署到 Google 云平台
云部署
使用 Cloud Run 和 SQL 实例将 Dockerized Python 应用程序部署到 Google 云平台的简短指南。

照片由安德里亚斯·韦兰在 Unsplash 上拍摄
在本文中,我们将介绍如何使用 Pipfile.lock 将应用程序部署到云,并将应用程序连接到云数据库。有关虚拟环境的更多信息或开始使用环境和包管理器 Pipenv,请查看本文 !
部署问题
由于缺乏对虚拟环境的了解或经验,新开发人员通常在系统级别安装所有东西。用 pip 安装的 Python 包放在系统级。以这种方式为每个项目检索需求会在您的机器上创建一个无法管理的全局 Python 环境。虚拟环境允许你划分你的软件,同时保持一个依赖清单。
Pipenv 是一个用于虚拟环境和包管理的工具,它允许开发人员创建更容易部署、构建和修改的独立软件产品。
Pipenv 是什么?
Pipenv 将软件包管理和虚拟环境控制结合到一个工具中,用于安装、删除、跟踪和记录您的依赖关系;以及创建、使用和管理您的虚拟环境。Pipenv 本质上是将 pip 和 virtualenv 包装在一个产品中。
对于应用程序部署,GCP 可以从 Pipfile 构建环境。当我们添加和删除依赖项时,Pipenv 将自动更新我们的 Pipfile。
Docker 和 docker 文件

卡梅伦·文蒂在 Unsplash 上拍摄的照片
Docker 是将应用程序投入生产的最佳方式。Docker 使用 docker 文件来构建容器。构建的容器存储在 Google Container Registry 中,在那里可以部署它。Docker 容器可以在本地构建,并将在任何运行 Docker 的系统上运行。
GCP 云构建允许您使用 docker 文件中包含的指令远程构建容器。远程构建很容易集成到 CI/CD 管道中。由于 Docker 使用大量 RAM,它们还节省了本地计算时间和能量。
这是我们在这个项目中使用的 docker 文件:
示例 Dockerfile 文件
每个 docker 文件的第一行都以FROM.开始,这是我们导入操作系统或编程语言的地方。下一行以 ENV 开始,将我们的环境变量 ENV 设置为APP_HOME / app.
这些行是 Python 云平台结构的一部分,你可以在 文档 中读到更多关于它们的内容。
WORKDIR行将我们的工作目录设置为/app。然后,复制行使本地文件在 docker 容器中可用。
接下来的三行涉及设置环境并在服务器上执行它。RUN命令可以跟随着您想要执行的任何 bash 代码。我们使用RUN来安装 pipenv。然后使用 pipenv 安装我们的依赖项。最后,CMD行执行我们的 HTTP 服务器 gunicorn,将我们的容器绑定到 $PORT,为端口分配一个 worker,指定该端口使用的线程数量,最后将应用程序的路径声明为app.main:app。
您可以添加一个.dockerignore文件来从您的容器映像中排除文件。.dockerignore用于将文件保存在容器之外。例如,您可能不希望在您的容器中包含您的测试套件。
要排除上传到云构建的文件,添加一个.gcloudignore 文件。由于 Cloud Build 将您的文件复制到云中,您可能希望忽略图像或数据以降低存储成本。
如果你想使用这些,一定要查看[.dockerignore](https://docs.docker.com/engine/reference/builder/#dockerignore-file)和[**.gcloudignore**](https://cloud.google.com/sdk/gcloud/reference/topic/gcloudignore)文件的文档,但是,要知道模式和.gitignore是一样的!
应用部署
我们需要对我们的项目文件做一些最后的修改,为部署做准备。
我们需要将 gunicorn 和 Pymysql 添加到 Pipfile 中,如下所示。
pipenv install gunicorn pymysql
Git 将您之前创建的 Pipfile、Pipfile.lock 和 Dockerfile 添加到您的存储库中。
Docker 图像和 Google 容器注册表
现在,一旦我们准备好 docker 文件,通过从包含 docker 文件的目录运行以下命令,使用云构建来构建您的容器映像:
gcloud builds submit --tag gcr.io/**PROJECT-ID**/**container-name**
注意:用您的 GCP 项目 ID 替换项目 ID,用您的容器名称替换容器名称。您可以通过运行命令gcloud config get-value project查看您的项目 ID。
该 Docker 图像现在可在 GCP 集装箱注册处或 GCR 访问,并可通过云运行的 URL 访问。
使用 CLI 部署容器映像
- 使用以下命令进行部署:
gcloud run deploy --image gcr.io/**PROJECT-ID**/**container-name** --platform managed
注意:用您的 GCP 项目 ID 替换项目 ID,用您的容器名称替换容器名称。您可以通过运行命令gcloud config get-value project来查看您的项目 ID。
2.将提示您输入服务名称和区域:选择您所选择的服务名称和区域。
3.您将被提示允许未认证的调用:如果您想要公共访问,响应y,并且n 限制对同一 google 项目中的资源的 IP 访问。
4.稍等片刻,直到部署完成。如果成功,命令行会显示服务 URL。
5.通过在 web 浏览器中打开服务 URL 来访问您部署的容器。
使用 GUI 部署容器映像
现在我们已经在 GCR 存储了一个容器映像,我们已经准备好部署我们的应用程序了。访问 GCP 云运行并点击创建服务,确保按要求设置计费。

选择您想服务的地区,并指定一个唯一的服务名称。然后通过分别选择未经身份验证或经过身份验证,在对应用程序的公共访问和私有访问之间进行选择。
现在我们使用上面的 GCR 容器图像 URL。将 URL 粘贴到空白处,或单击“选择”并使用下拉列表查找。检查高级设置以指定服务器硬件、容器端口和附加命令、最大请求数和扩展行为。
当您准备好构建和部署时,请单击创建!

从 GCR 选择一个容器图像
您将进入 GCP 云运行服务详细信息页面,在此您可以管理服务、查看指标和构建日志。

服务详情
单击 URL 查看您部署的应用程序!

呜哇!
恭喜你!您刚刚将打包在容器映像中的应用程序部署到云运行。Cloud Run 自动并水平地扩展您的容器映像以处理收到的请求,然后在需求减少时缩小规模。您只需为请求处理过程中消耗的 CPU、内存和网络资源付费。
也就是说,当你不想付费时,一定要关闭你的服务!
GCP 数据库的建立和部署
转到云控制台并设置计费(如果您还没有设置的话)。现在您可以创建一个 SQL 实例。
选择您想要使用的 SQL 方言,我们正在使用 MySQL。

设置实例 ID、密码和位置。
将 MySQL 实例连接到您的云运行服务
与任何配置更改一样,设置新的云 SQL 连接会导致创建新的云运行版本。要将云服务连接到云数据库实例:
- 去云茹 n
- 配置服务:
如果您正在向新服务添加云 SQL 连接:
- 您需要将您的服务容器化并上传到容器注册中心。
- 点击创建服务。
如果您正在向现有服务添加云 SQL 连接:
- 单击服务名称。
- 点击部署新版本。
3.启用连接到云 SQL:
- 点击显示可选设置:

- 如果要在项目中添加云 SQL 实例的连接,单击添加连接后,从下拉菜单中选择所需的云 SQL 实例。
- 如果您正在使用来自另一个项目的云 SQL 实例,请在下拉列表中选择连接字符串,然后以 PROJECT-ID:REGION:INSTANCE-ID 格式输入完整的实例连接名称。
4.点击创建或部署。
无论哪种情况,我们都希望我们的连接字符串看起来像下面这样。
mysql://ael7qci22z1qwer:nn9keetiyertrwdf@c584asdfgjnm02sk.cbetxkdfhwsb.us-east-1.rds.gcp.com:3306/fq14casdf1rb3y3n
我们需要对 DB 连接字符串进行更改,以便它使用 Pymysql 驱动程序。
在文本编辑器中,删除mysql并在它的位置添加mysql+pymysql,然后将更新后的字符串保存为您的 SQL 连接。
mysql+pymysql://ael7qci22z1qwer:nn9keetiyertrwdf@c584asdfgjnm02sk.cbetxkdfhwsb.us-east-1.rds.gcp.com:3306/fq14casdf1rb3y3n
请注意,您不必使用 GCP 的 SQL。如果使用的是第三方数据库,可以将连接字符串作为 VAR 而不是 Cloud SQL 添加,并输入您的连接字符串。
隐藏连接字符串。包封/包围(动词 envelop 的简写)
在本地创建一个名为.env的新文件,并为您的云数据库添加如下所示的DB_CONN,连接字符串。
DB_CONN=”mysql+pymysql://root:PASSWORD@HOSTNAME:3306/records_db”
注意:运行pipenv shell可以让我们接触到这些隐藏的环境变量。同样,我们可以用 os 访问 Python 中的隐藏变量。
MySQL_DB_CONN = os.getenv(“DB_CONN”)
确保将上面的行添加到您的 database.py 文件中,以便它准备好连接到云!
这个。env 文件现在包含敏感信息,应该被添加到您的.gitignore中,这样它就不会出现在公开可见的地方。
既然我们的应用程序和数据库都在云中,让我们确保我们的系统正常工作。
正在加载数据库
一旦可以看到 GCP 上列出的数据库,就可以用加载脚本加载数据库了。以下要点包括我们的 load.py 脚本。
load.py
让我们运行这个加载脚本,看看我们是否可以发送到我们的数据库。
首先,运行以下代码进入您的虚拟环境。
pipenv shell
然后运行 load.py 脚本。
python load.py
访问远程应用程序地址,查看您的数据是否已添加到云数据库。如果您遇到任何问题,请务必检查您的构建日志以查找回溯!
关于这个加载过程或以模块化方式设置你的应用程序的更多说明,请访问我们的Medium guide to building a data API!那篇文章详细解释了上面的代码。
结论
在本文中,我们学习了一些关于使用 pipenv 进行环境管理以及如何对应用程序进行 Dockerize 的知识。然后,我们介绍了如何在 Google 容器注册表中存储 Docker 容器,并使用云构建 CLI 和 GUI 部署容器。接下来,我们建立了一个云 SQL 数据库,并将其连接到我们的应用程序。最后,我们讨论了一种装载数据库的方法,在本地运行 load.py。请注意,如果您的应用程序本身收集数据,您只需要部署应用程序和数据库,然后部署的应用程序将在收集数据时填充数据库。
这里有一个到 GitHub 库的链接,里面有我们这个项目的代码。请务必查看这段代码,看看我们是如何设置整个代码库的!
使用计算引擎将 Dockerized Streamlit 应用程序部署到 GCP
使用 Docker 和 Google 云平台将简单的 streamlit 应用程序部署到云的指南(GCP)

照片由 Boudewijn 在 Unsplash 上直播
使用 Streamlit 框架构建原型很简单,至少可以在您自己的计算机上运行。与更广泛的受众分享更加复杂。
Streamlit 使我们能够以最少的努力和零成本创建干净的应用程序。我们在这里使用的应用程序非常简单,因为本文将重点关注部署。我们将按照本文中列出的步骤,将 Streamlit 应用程序部署到 Google 云平台计算实例中。
这里有一个链接,链接到包含我们项目代码的 GitHub 库。注意,我们使用 Pipenv 来管理我们的依赖关系。
切换到后端目录。运行 pipenv install — dev 来安装 env。运行 pipenv shell。运行预提交安装到…
github.com](https://github.com/edkrueger/streamlit-template)
什么是 Streamlit?
Streamlit 是一个免费的开源应用框架,为数据科学家和机器学习工程师快速创建伟大的 Python 应用提供了一种简单的方法。Streamlit 固执己见的本性使构建前端变得容易。最后,Streamlit 可以让数据应用的实验和生产以及机器学习分析更容易进行和迭代。
查看他们在 GitHub 上的工作。
streamlit-用 Python 构建数据应用程序的最快方法-streamlit/streamlit
github.com](https://github.com/streamlit/streamlit)
Docker 和我们的 docker 文件
Docker 是将应用程序投入生产的最佳方式。Docker 使用 docker 文件来构建容器。构建的容器存储在 Google Container Registry 中,可以在这里进行部署。Docker 容器可以在本地构建,并将在任何运行 Docker 的系统上运行。
这是我们在这个项目中使用的 docker 文件:
Dockerfile 文件
Dockerfile 的第一行以FROM.开始,这是我们导入操作系统或编程语言的地方。
接下来的两行涉及设置环境并在服务器上执行它。COPY行使本地文件requirements.txt在 docker 容器中可用。RUN命令可以跟随着您想要执行的任何 bash 代码。我们使用RUN来安装我们的依赖项。然后ENV,将我们的环境变量ENV 设置为APP_HOME / app。这模仿了我们的项目目录的结构,让 Docker 知道我们的应用程序在哪里。
这些行是 Python 云平台结构的一部分,你可以在谷歌的云 文档 中读到更多关于它们的内容。
WORKDIR行将我们的工作目录设置为$APP_HOME。然后,COPY 行将剩余的本地文件放在 docker 容器中。
docker 文件中的最后一行在$PORT.运行我们的应用程序
用 Docker 构建和运行
这里我们将解释如何用 Docker 构建我们的容器。请注意,我们的 Dockerfile 位于backend目录中。
- 进入
backend目录。 - 使用
docker build . -t streamlit-app构建

成功构建
docker build命令将 docker 文件的每一行视为一个“步骤”,并提供一个终端输出,指示每个步骤何时运行,如上所示。
既然我们的容器是在我们的虚拟机上构建的,我们就可以运行我们的 Streamlit 应用程序了。
- 使用
docker run -p 80:8080 -e PORT=8080 streamlit-app运行
注意:这将在容器内部的端口 8080 和容器外部的端口 80 上运行应用程序。为了在容器外部引用它,URL 是[http://localhost/](http://localhost/)
您可能会收到如下所示的错误。

虚拟机告诉我们端口 80 已经被使用
如果是这种情况,将内部端口80更改为另一个数字,例如85,并运行docker run -p 85:8080 -e PORT=8080 streamlit-app。

应用程序正在运行
部署到 GCP 计算引擎
如果您在本地开发,您将需要安装云软件开发工具包 CLI 工具。
发送反馈 Google Cloud Next '20: OnAir |从 7 月 14 日起每周二按需探索精选内容…
如果你在云机器上开发,很可能已经配置了这些工具。打开终端,输入以下命令。
- 运行
gcloud init选择您的账户和项目
这将多次提示您响应终端中的提示,以选择项目和虚拟机(VM)。
- 运行
export PROJECT=$(gcloud config get-value project)获取并保存您的项目 id。 - 跑
export GCR_TAG=gcr.io/$PROJECT/my-app去拿 GCR 的标签。
这允许我们将GCR_TAG作为环境变量引用,以便以后重用。
- 运行
gcloud builds submit --tag $GCR_TAG将构建提交给 GCP 云构建。

建立成功
这将在云构建中的另一台机器上构建我们的容器。一旦这个构建完成,我们的容器就可以在 Google 容器注册中心(GCR) 中使用我们指定的标签了。
- 运行
echo $GCR_TAG查看 GCR 标签。

现在,为了将我们的 dockerized 应用程序部署到虚拟机,我们遵循以下步骤。
- 转到 GCP 用户界面中的“计算引擎”并选择“创建实例”

- 在选项中,选中复选框“将容器映像部署到此虚拟机实例”
- 在“容器图像”字段中粘贴 GCR 标签。

在 GCP 上创建实例
若要公开部署,请选择“允许 HTTP 流量”
- 点击“创建”
- 运行
export GCR_TAG=<GCR TAG>。
确保用您的标签替换GCR_TAG。
- 运行
docker run -p 80:8080 -e PORT=8080 $GCR_TAG。
您不应该在新虚拟机上遇到任何端口错误。如果确实如此,请务必终止该进程,这样就可以将80保持为默认端口。否则,您的本地主机地址将是您指定的内部端口。
如果成功,您将看到两个 URL 填充了您的终端。

现在,使用 GUI 并单击“连接”下的下拉菜单,然后选择“在浏览器窗口中打开”

这将打开一个新的终端如下所示。我们再次需要我们的GCR_TAG,并且可以用命令docker image ls检索它。

我们的 docker 图像
一旦我们有了GCR_TAG,我们使用export保存它,然后用行docker run -p 80:8080 -e PORT=8080 $GCR_TAG重新运行我们的应用程序。

使用 Docker 运行我们的应用程序
请注意,我们无法在终端显示的 URL 中找到我们的应用程序。要查看我们的应用程序的运行情况,我们将使用 GUI 并找到那里显示的 URL。

运行应用程序的外部 URL
如果你访问网址,你会看到你的应用程序!请注意,这是公开的。

复杂性
请注意,这是“不安全”的,意味着没有 HTTPS 握手发生。如果网站不安全,用户在页面上输入的任何信息(如姓名、地址、信用卡详细信息)都不会受到保护,很容易被窃取。然而,在安全的网站上,代码是加密的,因此任何敏感信息都很难被发现。
当您使用完实例时,一定要关闭它们,因为它们只向您收取运行时间的费用。
结论
现在我们知道了如何将一个 streamlit 应用程序 Dockerize 并将其部署到 GCP。Streamlit 非常适合快速 POC 模型和内部仪表盘,现在我们有办法在云中测试我们的 Streamlit 应用程序!
感谢您的阅读!你能部署一个 Streamlit 应用程序吗?
在 Heroku 上部署一个 Flask 应用程序,并将其连接到 JawsDB-MySQL 数据库
使用 Heroku 将 MySQL 数据库和 Python 应用程序部署到云的简要指南
作者: Edward Krueger 数据科学家兼讲师和 Douglas Franklin 助教兼技术作家。

Gerald schmbs 在 Unsplash 上拍摄的照片
在本文中,我们将介绍如何使用 Pipfile.lock 将一个应用程序部署到云,并将该应用程序连接到云数据库。有关虚拟环境的更多信息或开始使用环境和包管理器 Pipenv,请查看本文!
部署问题
由于缺乏对虚拟环境的了解或经验,新开发人员通常在系统级别安装所有东西。用 pip 安装的 Python 包放在系统级。以这种方式为每个项目检索需求会在您的机器上创建一个无法管理的全局 Python 环境。虚拟环境允许你划分你的软件,同时保持一个依赖清单。
Pipenv 是一个用于虚拟环境和 Python 包管理的工具,它允许开发人员创建更易于部署、构建和修改的独立软件产品。
Pipenv 是什么?
Pipenv 将软件包管理和虚拟环境控制结合到一个工具中,用于安装、删除、跟踪和记录您的依赖关系;以及创建、使用和管理您的虚拟环境。Pipenv 本质上是将 pip 和 virtualenv 包装在一个产品中。
什么是 Heroku?
Heroku 提供许多软件产品,我们需要 Heroku 云平台服务来托管一个应用程序,并需要 JawsDB 来使用 MySQL 数据库。别担心,创建一个帐户并使用这些功能是免费的!
我们将使用 Heroku GUI 部署一个数据库和一个 Python 应用程序。
云数据库的优势
在我们之前的部署中,我们使用了 SQLite 数据库。当使用 SQLite 数据库时,每次应用程序重新部署都会重置您的数据库。Heroku 的 JawsDB 允许我们的数据通过应用程序更新来保持。此外,使用 JawsDB 可以托管、配置、修补和管理数据库。
准备部署
Heroku 允许我们从 GitHub 分支部署应用程序。一旦我们有了一个 Pipfile 被推送到 GitHub 的工作应用程序,我们就可以对存储库做一些最后的修改,为部署做准备了。一定要把你的 Pipfile 放在项目的根目录下,这样 Heroku 就可以找到它了!
注意:接下来的这些变化允许我们的应用程序在 Unix 系统上运行。Gunicorn 与 PC 不兼容,因此如果您使用的不是 Linux 或 Unix 机器,您将无法在本地测试这些更改。
安装 gunicorn
Gunicorn 是一个 Python WSGI HTTP 服务器,它将为 Heroku 上的 Flask 应用程序提供服务。通过运行下面的代码行,您将 gunicorn 添加到您的 Pipfile 中。
*pipenv install gunicorn*
添加 Procfile
在项目根文件夹中创建一个Procfile,并添加下面一行:
*web: gunicorn app:app*
第一个app代表运行您的应用程序的 python 文件的名称或者应用程序所在的模块的名称。第二个代表您的应用程序名称,即 app.py。此 Procfile 与 gunicorn 和 Heroku 的 Dynos 配合使用,可以远程为您的应用程序提供服务。
Heroku 云数据库的建立和部署
建立一个 Heroku 帐户如果你还没有,不要担心,我们在这里展示的所有功能都是免费的!
转到您在 Heroku.com 上的应用,然后单击资源。然后在 addons 框中输入“JawsDB MySQL ”,如下所示。

选择免费版本,然后单击 provision。太好了,我们现在已经为我们的应用程序部署了一个 MySQL 数据库。接下来,我们需要将这个新数据库集成到我们的应用程序逻辑中。
首先,让我们用下面的代码将 Python SQL 库 Pymysql 添加到我们的 Pipfile 中。
*pipenv install pymysql*
现在让我们获取连接字符串,并为 pymysql 修改它。转到设置并查看配置变量。您会发现一个类似下面的连接字符串。
*mysql://ael7qci22z1qwer:nn9keetiyertrwdf@c584asdfgjnm02sk.cbetxkdfhwsb.us-east-1.rds.amazonaws.com:3306/fq14casdf1rb3y3n*
我们需要对 DB 连接字符串进行更改,以便它使用 Pymysql 驱动程序。
在文本编辑器中,删除mysql并在它的位置添加mysql+pymysql,然后保存更新后的字符串。
*mysql+pymysql://ael7qci22z1qwer:nn9keetiyertrwdf@c584asdfgjnm02sk.cbetxkdfhwsb.us-east-1.rds.amazonaws.com:3306/fq14casdf1rb3y3n*
您需要将它添加到 Heroku 上的配置变量中。为此,请转到设置,然后配置变量并更新连接字符串。
隐藏连接字符串。包封/包围(动词 envelop 的简写)
创建一个名为.env的新文件,并为您的云数据库添加如下所示的DB_CONN,连接字符串。
*DB_CONN=”mysql+pymysql://root:PASSWORD@HOSTNAME:3306/records_db”*
注意:运行pipenv shell可以让我们访问这些隐藏的环境变量。同样,我们可以用 os 访问 Python 中的隐藏变量。
*SQLALCHEMY_DB_URL = os.getenv(“DB_CONN”)*
确保将上面的行添加到您的 database.py 文件中,以便它准备好连接到云!
应用部署
一旦我们有我们的应用程序测试和工作在本地,我们把所有的代码推到主分支。然后在 Heroku 上,去部署一个新的 app 看看下面的页面。

选择 Github 并搜索您的存储库
接下来在 Heroku 上,选择 GitHub,输入存储库的名称并点击 search。一旦您的用户名和存储库出现,单击连接。然后选择所需的分支,并单击部署。

选择主服务器并部署分支
构建日志将开始填充页面上的控制台。注意,Heroku 首先查找 requirements.txt 文件,然后从 Pipenv 的 Pipfile.lock 安装依赖项。同样,将这些文件放在项目的根目录下。

一旦从 Pipfile.lock 构建了您的环境,并且构建成功,您将会看到下面的消息。

成功的应用部署
该应用程序已成功部署!点击查看按钮,查看 Heroku 上部署的应用程序。
最初构建表格
您可能会遇到这样的错误:在尝试获取或提交数据之前,您的表尚未创建。为了解决这个问题,我们在 app.py 中使用下面一行代码。
*@app.before_first_request
def setup():
db.create_all()*
自动部署
我们可以启用自动部署,让 Github master 的更改在推送时显示在 Heroku 上。如果您使用这种方法,您将希望确保始终有一个工作的主分支。

启用自动部署
结论
编码和构建有用的软件需要管理复杂性。我们讨论了作为版本控制工具的 Github,作为环境和包管理器的 Pipenv,以及让云公司管理数据库的一些好处。这些工具有助于降低构建软件的复杂性,因此开发人员可以专注于构建而不是管理。
对于希望在生产中部署、构建或使用代码的数据科学家和开发人员来说,实践适当的环境和包管理至关重要。使用像 Pipenv 这样的环境和包管理器可以使包括部署在内的许多过程变得更加舒适和高效!
此外,拥有一个管理良好的 GitHub 主分支和一个 Pipfile 允许 Heroku 的服务器用最少的故障排除来重建我们的应用程序。这让我们可以在几分钟内将一个应用从 GitHub 上的项目目录部署到 Heroku。
我们希望本指南对您有所帮助,欢迎评论和提问,谢谢!
从 Jupyter 笔记本部署机器学习模型
部署可以而且应该很容易
坦率地说,如果你不能从笔记本中获得你的机器学习模型,它可能不会被使用。本文将帮助您尽快创建模型的部署,以便您可以将业务流程注入到模型中。这是一项重要的技能,因为这意味着你不再依赖软件工程师/开发人员来帮助你。

为此,我们将使用 Watson 机器学习和 Jupyter 笔记本。我假设您已经有了 Anaconda 或其他可以运行笔记本的环境。以下是我们将遵循的大纲,您可以随意跳过您可能已经完成的步骤:
- 创建一个 IBM 云帐户。(~2 分钟)
- 创建 Watson 机器学习(WML)实例。(~2 分钟)
- 获取 API 密钥。(~1 分钟)
- 创建一个可以存储模型的部署空间。(~1 分钟)
- 创建一个机器学习模型。(大约 1 分钟,除非您正在创建自己的模型)
- 部署您的模型。(~4 分钟)
- 尝试发送您部署的模型数据。(~2 分钟)
创建 IBM 云帐户
访问 IBM Cloud 的注册页面,并遵循那里的指示。

创建沃森机器学习实例
登录后,这应该是您看到的屏幕。你可以点击顶部横幅中的目录按钮,滚动直到找到机器学习,或者使用搜索栏来找到它。

选择 Watson Machine Learning 后,点击右下角的 create 按钮创建一个免费的 Lite 实例。一定要记住你选择的地区,对我来说就是达拉斯。

如上所述,沃森机器学习每月提供 20 个自由容量单元,在此期间可以对模型进行训练、评估、部署和评分。如果您的预算有限,我建议您在本地环境中培训您的模型,并保存您的容量单位以用于评分。对于不会经常调用的较小型号,这可能就足够了。
获取 API 密钥
要获得密钥,请访问您的 IBM Cloud 帐户的 API 密钥管理页面。然后,您可以单击“Create an IBM Cloud API key”来创建一个新的密钥,并提供密钥名称和描述。我给出了“wml-api-key”作为我的键的名称。

创建 API 密钥后,将其复制并粘贴到笔记本中,以便我们使用。
创建部署空间
部署空间是您可以存储和管理所有已部署模型的地方。我建议为每个业务目的准备一个部署空间。访问您的部署空间页面以创建新的部署。

从现在开始,我们将在笔记本上写 python 代码。
创建机器学习模型
我将保持简单,为虹膜数据集创建一个 KNN 模型。虽然您应该制作一些与您的业务用例相关的东西,但是这个模型足以演示如何使用 WML。如果您没有制作自己的模型,可以复制并粘贴下面的单元格。
import sklearn
from sklearn.datasets import load_irisiris = load_iris()
X = iris.data
Y = iris.target
clf = sklearn.neighbors.KNeighborsClassifier()
clf.fit(X, Y)
部署您的模型
安装 Python SDK
您需要安装 IBM Watson 机器学习 python SDK。您可以通过在命令行中运行pip install ibm-watson-machine-learning来做到这一点。你也可以像这样在你的笔记本中运行它自己的单元格:!pip install ibm-watson-machine-learning。
设置您的客户端
您可以通过导入 Watson Machine 学习包并提供您的 API 键和区域来启动您的代码。如果您不知道应该为 location 提供什么值,您应该使用检查您的实例所在的城市。您通过查阅 locations 页面找到那个城市和地区。因为我的实例在达拉斯,所以我为下面的位置变量提供了“美国南部”。
from ibm_watson_machine_learning import APIClientapi_key = "<your-key>"
location = "<your-region>"
这些可以作为凭证提供。
wml_credentials = {
"apikey": api_key,
"url": '[https://'](/') + location + '.ml.cloud.ibm.com'
}client = APIClient(wml_credentials)
设置您的部署空间
我们需要获得您的部署空间的 ID。您可以通过运行下面的代码来做到这一点。
client.spaces.list()
从上面的输出中,您将获得您的部署空间的 ID。使用下面的代码设置您的 APIClient 来使用您的部署空间。
client.set.default_space("<ID>")
发布您的模型
在我们部署我们的模型之前,我们需要发布它。首先,我们必须决定我们想要使用哪个版本的 python,并设置一些元数据。如果你需要弄清楚你使用的是哪个版本的 python,运行import sys,然后运行sys.version。
如果您还部署了一个基于 sklearn 的模型,您将需要确定它的版本。你可以运行sklearn.__version__来解决这个问题。
metadata = {
client.repository.ModelMetaNames.NAME: 'Iris KNN Model',
client.repository.ModelMetaNames.TYPE: 'scikit-learn_0.22',
client.repository.ModelMetaNames.SOFTWARE_SPEC_UID: sofware_spec_uid
}published_model = client.repository.store_model(
model=clf,
meta_props=metadata,
training_data=iris.data,
training_target=iris.feature_names)
您将需要获得您发布的模型的 ID。您可以通过运行下面的代码来获得。
models_details = client.repository.list_models()
部署您的模型
要部署您的模型,请使用上面单元格中您发布的模型的 ID,并运行下面的代码。
metadata = {
client.deployments.ConfigurationMetaNames.NAME: "Deployment of Iris KNN Model",
client.deployments.ConfigurationMetaNames.ONLINE: {}
}
created_deployment = client.deployments.create("<your-published-model-id>", meta_props=metadata)
测试您的部署
您的模型现在已经部署,我们现在可以向它发送数据并获得响应。首先,我们需要通过运行下面的代码来获取已部署模型的 ID。
client.deployments.list()
然后,我们可以使用该 ID 并在列表列表中发送观察结果。
scoring_payload = {"input_data": [{"values": [[5.1, 3.5, 1.4, 0.2]]}]}
predictions = client.deployments.score("<your-deployment-id>", scoring_payload)
在预测变量中,我们现在已经存储了一个类的预测和每个类的概率。
结论
如果你的作品要产生巨大的影响,它必须出现在某个地方,而不是 PowerPoint。对于许多数据科学家来说,笔记本是机器学习模型的主要开发环境,如果您不想将模型及其依赖项打包成可以在您的计算机和生产服务器上运行的东西,那么这是一种方法。除了所有这些复杂性之外,就你必须获得的知识而言,这是最简单的工作流程,以使 ML 模型在生产中工作,这可能是在你的业务中采用 AI 的最快方式。
将. NET API 部署到 Azure
创建一个 SQL 数据库,并在云中提供您的 API!

介绍
本文是致力于为英雄视角之旅教程构建. NET API 的系列文章的第四篇。
到目前为止,我们已经:
您可以使用 Angular 应用程序的本地开发版本。NET API,以及一个来自于 my GitHub repo 的 Docker MSSQL 数据库,或者按照本系列的前一篇文章自己构建。
现在,让我们部署我们的。NET API 到 Azure!我必须感谢这个棒极了的微软教程,它详细介绍了这个过程。
文章大纲
- 设置环境
- 创建 Azure SQL server
- 展开。NET API 到 Azure
设置您的环境

你需要两个关键的软件:
- Azure 命令行界面
- 。NET Core —我用的是 3.0.2 版本
当这些都被安装后,把本地版本的。我的 GitHub repo 中的. NET API。从命令行导航到Heroes.API目录并运行。NET 核心程序通过运行dotnet run。一旦你确认它在你的系统上运行,停止程序。
初始化 git 储存库
因为你从 GitHub 下载了这个项目,它带有一个. git 隐藏文件夹,我们需要删除它。从Heroes.API向上一层,这样你就可以看到组成整个应用程序的所有 3 个文件夹。显示隐藏的文件夹.git文件夹,并从 linux 或 mac 系统中删除或运行sudo rm -r .git。
然后,导航回英雄。API 目录。运行ls以确保您看到所有预期的文件夹。
我们需要初始化一个新的 git 存储库,并将它推送到 Azure 远程存储库。从Heroes.API目录运行:
git init
git add .
git commit -m "first commit"
创建 Azure SQL 数据库
通过运行az login登录到 Azure CLI。
使用 az group 命令创建一个名为HeroesAPIgroup的资源组来存放您的资源。
az group create --name HeroesAPIgroup --location eastus
通过运行以下命令,在您的资源组名称heroesSQLdb中创建一个 SQL server
az sql server create \
--name heroapisqlserver \
--resource-group HeroesAPIgroup \
--location eastus \
--admin-user sqlAdmin \
--admin-password Mystrongpassw0rd
完成后,您将获得部署细节的 JSON 输出。
通过运行以下命令为您的服务器配置防火墙:
az sql server firewall-rule create \
--resource-group HeroesAPIgroup \
--server heroapisqlserver \
--name AllowAllIps \
--start-ip-address 0.0.0.0 \
--end-ip-address 0.0.0.0
在新创建的 SQL server 上创建一个heroes数据库。
az sql db create \
--resource-group HeroesAPIgroup \
--server heroapisqlserver \
--name heroes \
--service-objective S0
要向您的heroes数据库添加一个表,我们需要登录 Azure 门户,找到您的 HeroesAPIgroup 资源组,然后点击您的 heroes SQL 数据库。
转到查询编辑器,尝试使用创建 SQL server 时的用户名和密码输入您的 SQL 数据库。它应该会失败,因为根据您的防火墙规则,您的本地 IP 地址没有被授予访问服务器的权限。
返回到您的heroes数据库概述。点击设置服务器防火墙。

从防火墙设置中,单击添加客户端 IP。现在,您应该能够从您的家庭或办公室 IP 地址位置访问 SQL server。

现在,使用查询编辑器中的用户名和密码进入 SQL 数据库。

登录到 SQL Server 后,运行下面的查询来添加一个表,并将示例数据插入到数据库中。
CREATE TABLE HeroValue( id int, name VARCHAR(50) );
INSERT INTO HeroValue (id, name)
VALUES
(1, 'Wonder Woman'),
(2, 'Spiderman'),
(3, 'Black Widow'),
(4, 'Batman'),
(5, 'Captain Marvel');

我们有数据库!让我们复制出连接字符串以备后用。从 Overview 中,单击连接字符串,并复制。提供了网络连接字符串。我的看起来像这样:
Server=tcp:heroapisqlserver.database.windows.net,1433;Initial Catalog=heroes;Persist Security Info=False;User ID=sqlAdmin;Password={your_password};MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;
用您为管理员选择的密码替换{your_password}。
我们不会将这个连接字符串插入到我们的应用程序中。一旦我们部署了应用程序,我们将使用az webapp config为应用程序配置一个连接,这将优先于appsettings.json中的连接字符串。我们将在创建 web 应用程序后创建这个应用程序级的连接字符串,所以请记住这个连接字符串。
让我们部署该应用程序吧!
展开。NET API 到 Azure
我们将需要配置一个部署用户,授权他将 git 存储库推送到 Azure。立即创建用户:
az webapp deployment user set \
--user-name DeploymentUser420 \
--password DeploymentPassw0rd!
如果成功,您将获得 JSON 输出。如果你得到错误,Azure 文档说:如果你得到一个'Conflict'. Details: 409错误,改变用户名。如果你得到一个'Bad Request'. Details: 400错误,使用一个更强的密码。
创建应用服务计划
应用服务计划将决定为运行应用而创建的虚拟机的大小。我们将使用应用服务计划的免费 linux 层。
az appservice plan create \
--name HeroesAPIserviceplan \
--resource-group HeroesAPIgroup \
--is-linux \
--sku FREE
创建 web 应用程序
创建一个符合应用服务计划条款的 web 应用。
首先,我们需要检查哪些运行时可用。运行:
az webapp list-runtimes --linux
选择适合您代码的DOTNET|运行时。我们要用“DOTNETCORE|3.0”。使用 az webapp create 命令创建 web 应用。我强烈推荐在这个多功能的命令上阅读 Azure 文档。
az webapp create \
--resource-group HeroesAPIgroup \
--plan HeroesAPIserviceplan \
--name heroes-api \
--runtime "DOTNETCORE|3.0" \
--deployment-local-git
创建应用程序后,首先看到的是 git remote 的 URL。保存这个非常重要!我们将需要这个 URL 来将您的本地 git 存储库推送到 Azure。
我的 git 回购 URL。(不要担心在发布文章之前这个项目会被删除)。
Local git is configured with url of '[https://DeploymentUser420@heroes-api.scm.azurewebsites.net/heroes-api.git'](https://DeploymentUser420@heroes-api.scm.azurewebsites.net/heroes-api.git')
配置连接字符串
还记得设置 SQL server 后保存的连接字符串吗?我们现在将使用它在应用程序级别设置一个连接字符串。这将优先于指向本地 docker mssql 数据库的当前连接字符串。不要忘记将{your_strong_password}替换为您的管理员密码。
az webapp config connection-string set \
--resource-group HeroesAPIgroup \
--name heroes-api \
--settings MyDbConnection="Server=tcp:heroapisqlserver.database.windows.net,1433;Initial Catalog=heroes;Persist Security Info=False;User ID=sqlAdmin;Password={your_password};MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;" \
--connection-string-type SQLServer
为数据库使用设置环境变量
我们需要设置一个环境变量。NET API 知道在生产环境中连接到 Azure SQL 数据库,而不是用于开发的本地 docker 数据库。
az webapp config appsettings set \
--name heroes-api \
--resource-group HeroesAPIgroup \
--settings ASPNETCORE_ENVIRONMENT="Production"
现在,我们需要在。NET API 来读取环境变量,并相应地选择 Azure 数据库或 Docker 数据库。
修改Startup.cs中的 ConfigureServices 以首先查找环境变量ASPNETCORE_ENVIRONMENT,如果没有该变量,则选择本地 Docker 数据库。
// Use SQL Database if in Azure, otherwise, use SQLite
if(Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Production")
services.AddDbContext<HeroesContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("MyDbConnection")));
else
services.AddDbContext<HeroesContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DockerDB")));
保存您的更改,不要忘记提交 git repo。
git add .
git commit -m "connect to SQLDB in Azure"
从本地 git repo 推送到 Azure
您的应用程序已准备好进行生产部署。让我们将 git 存储库推送到远程 Azure 存储库,我们的 web 应用程序正在寻找该存储库来提供代码。添加创建 web 应用程序后保存的 git repo URL。
git remote add azure <deploymentLocalGitUrl-from-create-step>
将您的 git repo 推送到 Azure remote repo 来部署您的应用程序。当您运行以下命令时,它会要求您提供凭据。输入我们创建的部署用户的密码,而不是您的 Azure 登录名!
git push azure master
你做到了!您部署了您的应用程序!现在让我们来测试一下。浏览 heroes-api 应用服务概述,并复制 API URL 端点。它应该是这样的:
https://heroes-api.azurewebsites.net
测试来自 Postman 的 API
向[https://heroes-api.azurewebsites.net/api/Heroes](https://heroes-api.azurewebsites.net/api/Heroes)发送一个 GET 请求,观察所有预装英雄的 JSON 输出!成功!
来自英雄角游 App 的测试
打开英雄之旅 app 进入src/app/hero.service.ts。
在 HeroService 类下,注释掉本地的 URL。NET API,并用 Azure 的 API URL 端点替换 localhost:5000。您的连接字符串将如下所示:
*private* heroesUrl = ‘https://heroes-api.azurewebsites.net/api/Heroes';
通过运行以下命令启动 angular 应用程序:
ng serve --open
你做到了!你有一个前端,后端和一个数据库!

将您的 Angular 应用程序部署到 Azure
要将你的 Angular app 部署到 Azure,可以跳转到我的文章!
确保您记得在 HeroService 中交换连接字符串。
谢谢你读到这里!我希望这篇文章能让你轻松部署到 Azure,如果你需要更多的解释,这篇 Azure 教程真的很详细!
在 AWS 上部署 Python API
烧瓶+ Lambda + API 网关
创建我自己的应用程序并将其部署在云上以便每个人都可以使用它的第一个想法让我非常兴奋,这也是我写这篇文章的灵感。如果这个想法也引起了你的兴趣,请继续阅读这篇文章,从这篇文章中,你将一步一步地学习如何部署 python 应用程序。
首先,你需要一个应用程序
你需要将你的想法包装在一个应用程序中,或者说是一个 API,它可以处理来自互联网的呼叫。这里的就是一个例子。这是一个烧瓶应用程序,
关键在于app.py文件,这个应用程序接收你的简历并帮助你在内部推荐。请注意,我们甚至不需要 docker 文件,AWS Lambda 非常轻量级,您甚至不需要将代码包装在容器中!
其次,下载 Zappa
Zappa ,引自官方文件,它
让在 AWS Lambda + API Gateway 上构建和部署无服务器、事件驱动的 Python 应用程序(包括但不限于 WSGI web 应用程序)变得极其简单。可以把它想象成 Python 应用程序的“无服务器”网络托管。这意味着无限扩展、零停机、零维护,而成本只是您当前部署的一小部分!
如果你已经使用 AWS 服务有一段时间了,你会知道在云上部署一个使用多种不同服务和配置的服务不是一件容易的事情,但是 Zappa 来拯救你,用简单的命令(相信我,它真的只有几行!),所有的起重配置都会完成!
pip install zappa
顺便说一下,我假设您已经在项目虚拟环境中安装了所有的包,如果没有,请安装
virtualenv -p `which python3` env
(您需要预装 virtualenv)
现在做
zappa init
一个一个的检查设置,如果你不明白就用默认的,之后你仍然可以改变它。在这之后,你的根文件夹中会有一个zappa_setting.json,我的是这样的
{
"production": {
"app_function": "app.app",
"aws_region": "ap-southeast-1",
"profile_name": "default",
"project_name": "referral-api",
"runtime": "python3.7",
"s3_bucket": "zappa-referral-api-eu2hzy8sf"
}
}
第三,让 Zappa 访问你的 AWS
现在你需要去你的 AWS 控制台,但是等等,你说 Zappa 会为我们做所有的 AWS 工作?是的,但是请这样想,在 Zappa 可以代表您做出任何更改之前,它需要访问您的 AWS 资源,这一步是给 Zappa 一个做这些事情的凭证。
您可以遵循这里的步骤部署-无服务器-应用(相信我,这是一个真正的说明性指南,包含您需要的所有映像)。
对于附加到组的策略,请使用此策略!(上面链接中的那个不能让你更新应用)
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iam:AttachRolePolicy",
"iam:GetRole",
"iam:CreateRole",
"iam:PassRole",
"iam:PutRolePolicy"
],
"Resource": [
"arn:aws:iam::XXXXXXXXXXXXXXXX:role/*-ZappaLambdaExecutionRole"
]
},
{
"Effect": "Allow",
"Action": [
"lambda:CreateFunction",
"lambda:ListVersionsByFunction",
"logs:DescribeLogStreams",
"events:PutRule",
"lambda:GetFunctionConfiguration",
"cloudformation:DescribeStackResource",
"apigateway:DELETE",
"apigateway:UpdateRestApiPolicy",
"events:ListRuleNamesByTarget",
"apigateway:PATCH",
"events:ListRules",
"cloudformation:UpdateStack",
"lambda:DeleteFunction",
"events:RemoveTargets",
"logs:FilterLogEvents",
"apigateway:GET",
"lambda:GetAlias",
"events:ListTargetsByRule",
"cloudformation:ListStackResources",
"events:DescribeRule",
"logs:DeleteLogGroup",
"apigateway:PUT",
"lambda:InvokeFunction",
"lambda:GetFunction",
"lambda:UpdateFunctionConfiguration",
"cloudformation:DescribeStacks",
"lambda:UpdateFunctionCode",
"lambda:DeleteFunctionConcurrency",
"events:DeleteRule",
"events:PutTargets",
"lambda:AddPermission",
"cloudformation:CreateStack",
"cloudformation:DeleteStack",
"apigateway:POST",
"lambda:RemovePermission",
"lambda:GetPolicy"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"s3:ListBucketMultipartUploads",
"s3:CreateBucket",
"s3:ListBucket"
],
"Resource": "arn:aws:s3:::zappa-*"
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:AbortMultipartUpload",
"s3:DeleteObject",
"s3:ListMultipartUploadParts"
],
"Resource": "arn:aws:s3:::zappa-*/*"
}
]
}
现在您将为 Zappa 创建的凭证添加到您的本地文件(凭证和配置),我的如下所示
[default]
aws_access_key_id = ****
aws_secret_access_key = ****[zappa]
aws_access_key_id = ****
aws_secret_access_key = ****
像这样配置
[default]
region = ap-southeast-1
output = json[zappa]
region = ap-southeast-1
output = json
我专门为 Zappa 创建了一个,因为我相信我们大多数人都会有自己的默认凭证,这个设置可以让你在不同的配置文件之间切换。
现在它已经准备好部署了!
export AWS_DEFAULT_PROFILE=zappa
zappa deploy production
您会在命令行后面看到您的 API url。现在转到您的 AWS Lambda,您应该会看到我们部署的 API:

在 API Gateway 中,您可以看到:

既然我可以在 postman 上测试公共端点并获得响应:

恭喜你。现在你已经用 Lambda 和 API Gateway 把你的应用完全部署到 AWS 上了!
如果这已经满足了您的需要,您可以就此打住,但是如果您想要分发您的 API 并为其添加限制,您可以继续下一部分。
Extra1:向 API 添加密钥
您可能已经注意到,到目前为止,我们的 API 是公开可访问的,这意味着任何人都可以访问我们的 API,它很容易受到恶意攻击。为了避免这种不受欢迎的访问,我们需要对我们的 API 使用(使用计划)和凭证(x-api-key)添加额外的限制来限制访问。
要给你的 API 添加一个密钥,请遵循这里的步骤。
Extra2:通过 RapidAPI 发布您的 API
RapidAPI 是每个人都可以免费向全世界开放和出售他们的 API 的地方,只要有人愿意为此付费。
- 转到 RapidAPI 并点击
Add New API - 填写您的 API 的基本信息
- 对于 API 的 URL,粘贴我们之前通过 Zappa 部署后获得的 AWS url
- 在访问控制中添加您的 api 密钥,如下所示

5.添加一个定价计划,您就可以向公众推出它了!
最后,如果你有兴趣,你可以看看我的推荐 API 。如果你正在寻找一份新的职业,到目前为止,它可以帮助你找到 Bytedance 公司,并通过内部门户网站进行抓取。
这个帖子最初是受这个的启发,一个很棒的帖子帮助我开始了这个计划,请随意查看!
使用 Docker、GCP 云运行和 Flask 部署 Scikit-Learn NLP 模型
构建一个服务于自然语言处理模型的应用程序,将其容器化并部署的简要指南。

照片由 Adi Goldstein 在 Unsplash 上拍摄
如果您需要帮助构建 NLP 管道或评估模型,请查看我们上一篇文章。我们介绍了一些 NLP 基础知识以及如何用 Scikit-Learn 构建 NLP 管道。然后,我们评估了一些模型指标,并为我们的问题和数据决定了最佳模型。
请务必查看我们的 GitHub 资源库中的自述文件和代码,了解如何使用 Docker 在本地设置该应用程序!
[## 用 SciKit-Learn 构建 NLP 管道:火腿还是垃圾邮件?
使用 Scikit-Learn 的自然语言处理库制作简单的垃圾邮件检测器模型的初学者指南。
towardsdatascience.com](/build-a-nlp-pipeline-with-scikit-learn-ham-or-spam-b2cd0b3bc0c1)
在将我们的模型部署到云之前,我们需要构建一个应用程序来服务我们的模型。
构建应用程序
服务于这个模型的应用程序很简单。我们只需要将我们的模型导入到应用程序中,接收 POST 请求并返回模型对该 POST 的响应。
这是应用程序代码。
注意,data_dict是对应于通过 POST 请求发送的有效负载的 Python 字典。从这本词典中我们可以提取要分类的文本。这意味着我们的帖子需要相同的键。所以我们将发送带有{key: value}为{"text": "message")的 JSONs。
因为 Scikit-Learn 管道需要一个字符串列表,所以我们必须将文本包装成一个列表。此外,当从模型的.predict 方法接收结果时,我们接收一个包含单个元素的列表,并对其进行解包以访问预测。
一旦我们让应用程序在本地正常运行,我们就可以对我们的存储库做一些修改,为部署做准备了。
请记住,我们使用包和环境管理器 pipenv 来处理我们的应用程序的依赖性。如果您不熟悉虚拟环境和包管理,您可能需要安装它,并使用 Github 存储库中的 Pipfile 设置一个虚拟环境。查看这篇文章来获得帮助!
[## 数据科学的虚拟环境:使用 Pipenv 运行 Python 和 Jupyter
为 Python 设置虚拟环境。
towardsdatascience.com](/virtual-environments-for-data-science-running-python-and-jupyter-with-pipenv-c6cb6c44a405)
将应用容器化
我们需要对我们的项目文件做一些最后的修改,为部署做准备。在我们的项目中,我们使用 pipenv 和 pipenv-to-requirements 来处理依赖关系并生成一个requirements.txt。对于 Docker 容器,您需要的只是requirements.txt文件。
确保将您之前创建的 docker 文件添加到您的存储库中。
这是我们 Pipfile 的链接,它是关于这个项目的依赖关系的。
github.com](https://github.com/edkrueger/spam-detector/blob/master/Pipfile)
Docker 和 docker 文件
在我们让应用程序在云中运行之前,我们必须首先对它进行 Dockerize。查看我们在 GitHub 资源库中的自述文件,了解如何使用 Docker 在本地设置这个应用程序。

史蒂夫·哈拉马在 Unsplash 上的照片
Docker 是将应用程序投入生产的最佳方式。Docker 使用 docker 文件来构建容器。构建的容器存储在 Google Container Registry 中,在那里可以部署它。Docker 容器可以在本地构建,并将在任何运行 Docker 的系统上运行。
这是我们在这个项目中使用的 docker 文件:
每个 docker 文件的第一行都以FROM.开始,这是我们导入操作系统或编程语言的地方。下一行从 ENV 开始,将环境变量 ENV 设置为APP_HOME / app。这模仿了我们的项目目录的结构,让 Docker 知道我们的应用程序在哪里。
这些行是 Python 云平台结构的一部分,你可以在 Google 的 cloud 文档 中读到更多关于它们的内容。
WORKDIR行将我们的工作目录设置为$APP_HOME。然后,复制行使本地文件在 docker 容器中可用。
接下来的两行涉及设置环境并在服务器上执行它。RUN命令可以跟随着您想要执行的任何 bash 代码。我们使用RUN来 pip 安装我们的需求。然后CMD运行我们的 HTTP 服务器 gunicorn。最后一行中的参数将我们的容器绑定到$PORT,为端口分配一个 worker,指定该端口使用的线程数量,并将应用程序的路径声明为app.main:app。
您可以添加一个.dockerignore文件来从您的容器映像中排除文件。.dockerignore用于将文件隔离在容器之外。例如,您可能不希望在您的容器中包含您的测试套件。
要排除上传到云构建的文件,添加一个.gcloudignore 文件。由于 Cloud Build 将您的文件复制到云中,您可能希望忽略图像或数据以降低存储成本。
如果你想使用这些,一定要检查一下[.dockerignore](https://docs.docker.com/engine/reference/builder/#dockerignore-file)和[.gcloudignore](https://cloud.google.com/sdk/gcloud/reference/topic/gcloudignore)文件的文档,但是,要知道模式和.gitignore是一样的!
在本地构建并启动 Docker 容器
用这一行命名并构建容器。我们称我们的容器为spam-detector。
docker build . -t spam-detector
要启动我们的容器,我们必须使用这一行来指定容器将使用哪些端口。我们将内部端口设置为 8000,外部端口设置为 5000。我们还将环境变量PORT设置为 8000,并输入容器名。
PORT=8000 && docker run -p 5000:${PORT} -e PORT=${PORT} spam-detector
现在我们的应用程序应该在本地 Docker 容器中启动并运行了。
让我们在运行构建的终端中提供的本地主机地址向应用程序发送一些 JSONs。
用 Postman 测试应用程序
Postman 是一个软件开发工具,使人们能够测试对 API 的调用。邮递员用户输入数据。数据被发送到一个 web 服务器地址。信息以响应或错误的形式返回,由邮递员呈现给用户。
邮递员让测试我们的路线变得很容易。打开图形用户界面
- 选择发布并粘贴 URL,根据需要添加路线
- 单击正文,然后单击原始
- 从右边的下拉列表中选择 JSON
确保使用“文本”作为 JSON 中的关键字,否则应用程序将会抛出错误。将您希望模型处理的任何文本作为值放置。现在点击发送!

用 Postman 发送 JSON post 请求
然后在 Postman 中查看结果!看起来我们的邮件被归类为火腿。如果您收到一个错误,请确保您使用了正确的键,并在 POST URL 中添加了路由扩展名/predict。

电子邮件是安全的_(ツ)_/
让我们试试我的 Gmail 垃圾邮件文件夹中的电子邮件。

嗯,看起来我们运行的模式与谷歌不同。
现在让我们在没有 Postman 的情况下,只使用命令行来测试这个应用程序。
用 curl 测试应用程序
Curl 可以是一个简单的测试工具,允许我们保持在 CLI 中。我不得不做一些调整,让命令与应用程序一起工作,但添加下面的标志解决了错误。
打开终端,插入以下内容。更改文本值以查看模型将哪些内容分类为垃圾邮件和火腿。
curl -H "Content-Type: application/json" --request POST -d '{"text": "Spam is my name now give all your money to me"}' [http://127.0.0.1:5000/predict](http://127.0.0.1:5000/predict)
结果或错误将会出现在终端中!
{"result":"ham"}
现在让我们将应用程序部署到谷歌云平台,这样任何人都可以使用它。
Docker 图像和谷歌云注册表
GCP 云构建允许您使用 docker 文件中包含的指令远程构建容器。远程构建很容易集成到 CI/CD 管道中。由于 Docker 使用大量 RAM,它们还节省了本地计算时间和能量。
一旦我们准备好 docker 文件,我们就可以使用 Cloud Build 构建我们的容器映像。
从包含 Dockerfile 文件的目录中运行以下命令:
gcloud builds submit --tag gcr.io/**PROJECT-ID**/**container-name**
注意:用您的 GCP 项目 ID 替换项目 ID,用您的容器名称替换容器名称。您可以通过运行命令gcloud config get-value project来查看您的项目 ID。
该 Docker 图像现在可在 GCP 集装箱注册处或 GCR 访问,并可通过云运行的 URL 访问。
使用 CLI 部署容器映像
- 使用以下命令进行部署:
gcloud run deploy --image gcr.io/**PROJECT-ID**/**container-name** --platform managed
注意:用您的 GCP 项目 ID 替换项目 ID,用您的容器名称替换容器名称。您可以通过运行命令gcloud config get-value project来查看您的项目 ID。
2.将提示您输入服务名称和区域:选择您所选择的服务名称和区域。
3.您将被提示允许未认证的调用:如果您想要公共访问,请响应y,以及n 限制对同一个 google 项目中的资源的 IP 访问。
4.稍等片刻,直到部署完成。如果成功,命令行会显示服务 URL。
5.通过在 web 浏览器中打开服务 URL 来访问您部署的容器。
使用 GUI 部署容器映像
现在我们已经在 GCR 存储了一个容器映像,我们已经准备好部署我们的应用程序了。访问 GCP 云运行并点击创建服务,确保按要求设置计费。

选择您想服务的地区,并指定一个唯一的服务名称。然后通过分别选择未经身份验证或经过身份验证,在对应用程序的公共访问和私有访问之间进行选择。
现在我们使用上面的 GCR 容器图像 URL。粘贴 URL 或单击选择并使用下拉列表查找。检查高级设置以指定服务器硬件、容器端口和附加命令、最大请求数和扩展行为。
当您准备好构建和部署时,请单击创建!

从 GCR 选择一个容器图像
您将进入 GCP 云运行服务详细信息页面,在此您可以管理服务、查看指标和构建日志。

服务详情
单击 URL 查看您部署的应用程序!

呜哇!
恭喜你!您刚刚将一个打包在容器中的应用程序部署到云环境中。
您只需为请求处理过程中消耗的 CPU、内存和网络资源付费。也就是说,当你不想付费时,一定要关闭你的服务!
结论
我们已经介绍了如何设置一个应用程序来为一个模型提供服务,以及如何在本地构建 docker 容器。然后我们对接我们的应用程序,并在本地进行测试。接下来,我们将 docker 映像存储在云中,并使用它在 Google Cloud Run 上构建一个应用程序。
快速开发出任何像样的好模型都有巨大的商业和技术价值。拥有人们可以立即使用的东西和部署数据科学家可以稍后调整的软件的价值。
我们希望这些内容是信息丰富和有帮助的,让我们知道你想在软件、开发和机器学习领域了解更多的东西!
使用 IBM Watson 和 OpenScale 部署和解释神经网络

在进入如何使用 Watson Studio 部署机器学习模型并使用 OpenScale 解释结果的分步教程之前,我想讲一个的小故事,我想解释一下为什么我们实际上需要 AI,为什么 AI 是人类进化的下一步。如果您仅对技术部分感兴趣,那么可以随意跳到第二部分,名为 IBM Watson 。
为什么我们需要像人工智能这样的工具
大多数人,如果他们听到像人工智能或机器学习这样的术语,他们会想到机器人。这是因为大预算电影将人工智能呈现为一个类似人类的机器,具有毁灭人类的潜力的超能力。实际上 AI 并不真的需要胳膊和腿来毁灭人类,但这是另一个故事了。
人工智能基于这样一种想法,即人类的智能、行为、人类思维可以以这样一种方式建模,即机器(或算法)可以模仿人类,可以执行迄今为止需要人类干预的任务,即类似人类的推理。在我看来,我们不应该模仿类似人类的行为,人类非常容易出错,我们应该创造更好的机器/算法,它们可以为我们执行重复的任务,这样我们就可以专注于更重要的事情,也许是需要更多创造力、更多想象力、情感和其他类似人类品质的任务。
进步、创新、进化需要越来越好的工具,没有工具我们的身体和心理能力都非常有限,浅薄。如果你想想“现代”人类的历史,每个时代都是由工具定义的。如果我们从史前时代开始,所谓的史前史就已经被工具所定义,它被工具所划界。顾名思义,史前时期是从第一批石器的使用到书写系统的发明之间的时期。如你所见,在这个时代的定义中,我们已经有了工具,它被工具所界定。这两个事件之间有多个“时代”,像青铜时代或铁器时代,这些都是由工具定义的。
想想看,我们的现代历史也是由工具定义的,过去几十年最重要的事件是由新工具/机器/设备的发明定义的。是的,我说的是四次工业革命。如果我们思考这些革命,这些革命的原因是什么?答案是工具!
在第一次工业革命期间,最大的变化出现在机械化形式的工业中。机械化是农业开始被工业取代成为社会经济支柱的原因。
继第一次工业革命之后,近一个世纪后,我们看到世界经历了第二次。它始于 19 世纪末,工业领域的巨大技术进步帮助出现了一种新的能源、电力、天然气和石油。第二次工业革命的重点是钢铁需求的发展、化学合成以及电报和电话等通讯方式。
****第三次革命带来了电子、电信,当然还有计算机的崛起。通过新技术,第三次工业革命打开了太空探险、研究和生物技术的大门。
第四次工业革命或所谓的工业 4.0 正在发生,它被一件事所定义,那就是互联网。我们可以看到从植根于技术现象的第一次工业革命一直到发展虚拟现实世界的工业 4.0 的转变,这使我们能够弯曲物理定律。
正如你所看到的,我们历史上所有这些重大事件都是由工具定义的,人工智能是另一个强大的工具,它可以并将重塑我们的世界。在我看来, AI 是人类进化过程中绝对必要的一步(也许这将是人类历史上最后一次革命,但这是后话,另文)。如果我们想进行更高级的研究(例如以光速旅行或发明一种传送方式),我们需要更强大的工具,其中之一就是人工智能。另一个大事件将是量子计算机的发明,然后是量子计算和人工智能的结合。从这一点来看,发明没有限制,从这一点来看,我们可以想象未来的研究人员将是人工智能算法,而不是人类,但这是一个非常遥远和非常脆弱的未来。我们就紧扣当下,说说我们现在有什么样的 AI/ML 的工具。****
如今,我们有许多设备连接到互联网(第四次工业革命),每个设备都会产生数据。因为我们想要智能的和个性化的** 设备,可以猜测我们的需求,所以我们需要处理这些数据。处理如此巨大数量的数据是一项非常艰巨的任务,并且它不能手动完成。所以对数据的自动推理是绝对必要的。这就是人工智能来救援的地方。但是在自动推理之后,我们还想了解 AI 算法的动作的原因。这就是对可解释性的大肆宣传是如何产生的。要阅读更多关于可解释人工智能的当前趋势,你可以阅读我的文章解释可解释人工智能 。**
IBM 沃森
IBM开发的平台名为 Watson Studio,结合了机器学习服务和Watson open scale是一个全面的组合,旨在使开发、训练、管理模型和部署人工智能应用变得容易。这是一个在 IBM Cloud 上交付的 SaaS 解决方案。它为您的数据科学家、工程师、开发人员和领域专家提供了协作所需的工具,以推动其业务创新。
Watson Studio 加速机器和深度学习工作流,将人工智能注入您的业务,以推动创新。它为数据科学家、应用程序开发人员和主题专家提供了一套工具,允许他们协作连接数据、讨论数据并使用数据来构建、培训和部署大规模模型。成功的人工智能项目需要算法+数据+团队的组合,以及非常强大的计算基础设施。
这个平台的唯一问题是文档可能很难理解并且来自社区的支持不是那么先进,关于如何使用 Watson 的文章很少,关于使用 Watson** 创建应用的文章**很少(几乎没有)。所以我决定我们应该缩小这个差距,Watson 是一个伟大的工具,由一个非常强大的基础设施支持,除了创建和部署模型,它还为人工智能模型提供开箱即用的解释能力。为了解释模型的结果,他们使用了在解释可解释 AI 中提出的 LIME 算法。****
在下一节中,您将看到一个示例,说明如何构建一个神经网络来预测糖尿病,然后如何使用上面提到的工具部署模型、设置持续学习、漂移检测以及解释神经网络的结果。
沃森中的糖尿病预测
在此示例中,我们将使用神经网络通过 Pima 糖尿病数据集来预测糖尿病。我们将使用 Keras 包来快速构建和训练一个神经网络。我们将使用 Watson Studio 来构建、训练和部署网络和 OpenScale 来设置漂移检测、持续学习并向解释模型的结果。
本例中使用的数据集可以从 Diabetes.csv 下载。数据集包括几个医学预测变量和一个目标变量,结果。预测变量包括患者的怀孕次数、身体质量指数、胰岛素水平、年龄等。数据集的列可以描述为:
- 怀孕次数
- 口服葡萄糖耐量试验中 2 小时的血浆葡萄糖浓度
- 舒张压(毫米汞柱)
- 三头肌皮褶厚度(毫米)
- 2 小时血清胰岛素(微单位/毫升)
- 体重指数(体重公斤/(身高米) )
- 糖尿病谱系功能
- 年龄(岁)
- 类别变量(0 或 1)
为了解决这个问题,首先让我们设置我们的 IBM 帐户并准备糖尿病预测所需的服务。
IBM Cloud — Watson 逐步部署
首先要做的是在 IBM Cloud 上创建一个账户,并登录你的账户。
****重要提示:为了获得最佳性能和兼容性,每个资源应该在同一个区域。在本教程中,我将使用法兰克福作为每个资源的选定区域。您可以根据您的帐户类型和您当前的位置选择其他地区。
从这里开始,请遵循以下步骤:
- 在屏幕的右上角,单击您的帐户图片,然后单击 My IBM。

这将把您带到 IBM 仪表板
2.在您的 IBM 仪表板上,您将看到您的产品。从产品部分启动 IBM Cloud

这将带您进入 IBM Cloud Dashboard,在这里我们可以开始创建所需的服务。
或者,您可以使用https://cloud.ibm.com/直接访问 IBM Cloud
3.下一步是向您的云帐户添加新资源。在您的 IBM Cloud 帐户上,单击 Create Resource 按钮。

4.向下滚动并选择 Watson Studio 资源。

5.选择地区(我将选择法兰克福),确保您已经选择了 Lite 计划(如果您不想支付),然后单击创建。

6.在 Watson Studio 资源准备就绪之后,单击 Get Started。

7.在沃森工作室,我们将创建我们的第一个项目,称为糖尿病。为此,请单击“创建项目”按钮。

8.然后点击创建空项目按钮

10.为项目选择一个名称(此处为糖尿病)。下一步是将这个项目链接到一个对象存储(我们将在这里存储与项目相关的文件,如。用于训练数据、笔记本和由笔记本创建的资源等的 csv 文件)。要创建新的对象存储,请单击“添加”按钮。

11.选择 Lite 计划(如果您不想付费),然后单击创建

12.在弹出窗口中,为对象存储帐户命名,然后单击创建

13.刷新项目创建页面,您应该看到您创建的对象存储名称链接到项目。单击 Create 创建新的 Watson Studio 项目。

14.该项目将自动打开(如果没有,则在 Watson Studio 主页中单击该项目的名称)。现在,我们将在项目中添加一个 jupyter 笔记本文件,它将用于创建我们的神经网络,训练它,保存它并将其部署到 IBM Cloud。为此,请单击“添加到项目”按钮。

15.选择笔记本按钮。

16.给它起一个名字(比如糖尿病预测),对于运行时,选择默认的 Python 3.6 免费运行时。单击“创建笔记本”并等待笔记本初始化。

17.下一步是上传笔记本将使用的培训。为此,单击操作栏中的小矩阵图标,单击浏览并选择培训数据。csv 文件。

18.下一步是从上传的中读取数据。csv 文件。为此,单击 Insert to code 链接,这将自动向笔记本添加一段代码。如果您运行这个单元格(选择单元格并按 Shift+Enter ),它将连接到对象存储,读取 csv 文件并显示文件的前 5 行。

19.现在,我们将创建神经网络,训练它并将其保存到对象存储中
a.定义全局变量
b.导入必要的包
c.用于将数据拆分为特征变量和目标或标签变量,创建和训练模型,以及将模型加载到内存中的函数
d.因为我们将使用 zip deploy,所以我们必须压缩 NN 模型并创建一个. tgz 文件
20.现在我们有了压缩文件中的训练模型,下一步是将它部署到 IBM Cloud。对于这个部署,我们需要将 Watson 机器学习服务与糖尿病项目关联起来。为此,回到沃森工作室,点击汉堡包菜单,选择服务,然后沃森服务

21.点击添加服务

22.选择机器学习服务

23.在弹出菜单中选择地区(我将选择法兰克福),给它命名并点击确认

24.将创建一个新的机器学习服务。单击服务的名称。

25.为了使用这个服务来部署我们的模型,我们需要凭证来访问这个服务。在“服务凭据”选项卡上,单击“新建凭据”按钮。

26.在弹出窗口中给 ti 一个名称,为服务 ID 选择 Auto Generate,然后单击 Add

27.复制服务凭据,因为我们将在笔记本中使用它进行部署

28.现在回到笔记本,因为我们将使用新创建的机器学习服务编写代码来部署模型
a.导入并创建 Watson 机器学习服务客户端
https://gist.github.com/cdc56c5f4ee03c9201b9e6d6ff842f8c
b.设置模型的属性,并将其发布到存储库中
c.我们将阅读新模型的指南,以确保它是成功生成的
d.创建部署
e.列出所有部署,以确保一切顺利
f.用于访问我们模型的 API 是自动生成的。我们将阅读这个的 url,来测试我们的模型。
g.从代码中测试模型。
29.如果我们想用 Postman 测试我们的模型,我们需要一个访问令牌。这可以用我们的笔记本来阅读:
a.安装 ibm-watson python 包
b.设置令牌管理器—您必须在 IBM Cloud IAM 中创建一个新的 API 密钥(或者在 IBM Cloud 主页上,单击 hamburger 菜单,选择 Security,选择 Manage,Identity and Access,这将为 IAM 打开一个新的选项卡)—单击 API 密钥,然后单击 Create an IBM Cloud API Key 按钮,复制密钥并插入令牌管理器。
d.在 Postman 头部分添加令牌

e.将测试数据添加到请求的正文中,然后单击 Send

30.现在,在你的名为糖尿病的沃森项目中,你应该有下图所示的资产

现在我们有了工作模型和 API 端点来安全地访问它(基于令牌的认证),我们可以继续使用 OpenScale 建立持续学习、漂移检测和可解释性管道。****
在接下来的步骤中,我们将使用 Watson OpenScale 来解释结果,它使用 LIME 算法来解释模型(有关 LIME,请参见 解释可解释的 AI )。
IBM Cloud — OpenScale 逐步配置
- 在 IBM Cloud Resource 列表中,单击 Create resource 并选择 Watson OpenScale,为其命名,选择区域,选择 Lite 计划并单击 Create

2.启动 OpenScale 平台后,选择使用免费的 lite 计划数据库

3.下一步是添加机器学习提供者

4.你可以从多个提供商中选择,如沃森机器学习、Azure 或亚马逊服务,但我们有一个定制模型,因为我们的模型是手工构建的,由我们自己构建并手动部署。然后选择手动输入部署。

5.转到 Insights 仪表板,然后单击添加

6.在弹出窗口中,选择您部署的模型名称。

7.下一步是指定输入和输出数据模式。为此,我们必须创建一个新的 Jpyter 笔记本,并运行如下所示的代码:
8.下一步是配置模型细节:
a.选择存储桶名称和数据集名称

b.配置对象存储连接。为此,您应该进入 IBM Cloud 主页,单击“hamburger”按钮,单击“所有资源”、“存储”,选择您的存储,然后选择存储对象,在菜单中,您可以找到“配置”选项卡。在这里,您将找到建立连接的所有内容。
****
c.选择目标类的列名

d.选择功能列名称

e.选择包含分类数据文本的列(在本例中,我们没有任何分类数据)

f.选择输出变量名(这是自动创建的)

9.配置持续学习和漂移检测非常简单,您只需为评估指标(如准确性)设置一个阈值。
10.在所有的配置步骤(有效载荷记录、模型细节、质量、公平性、可解释性(这将被自动配置)、漂移)之后,你可以选择你的模型。

11.在“操作”下拉列表中,您可以上传测试数据并评估模型。如上图所示,生成了 10 份解释报告。如果您单击该数字,将出现一个弹出窗口,您可以在其中找到每个解释报告的 id。
12.您可以使用解释报告 id 来查看解释。

13.这将为您提供一个如下图所示的报告。例如,在这个报告中,您可以看到特征重要性、置信度等。

结论
在这篇文章中,我们了解到:
- 如何使用沃森工作室和沃森 OpenScale****
- 如何在沃森工作室使用 Jupyter 笔记本
- 如何在 Watson Studio 中创建、训练和测试神经网络****
- 如何将模型部署到 Watson 机器学习服务并设置具有安全连接的测试端点(基于令牌的安全性)
- 如何调用** 我们的模型使用 邮递员**
- 如何使用云对象存储以及如何将其连接到 Watson Studio 项目
- 如何建立一个 Watson OpenScale 部署模型并使用它来解释部署的神经网络的结果****
在下一篇文章中,我们将继续我们在可解释 AI** 世界的旅程,我们将继续 的第二部分解释可解释 AI**** 。未来,我们将讨论其他云提供商,我们将向您展示如何在 Google Cloud、Amazon 和 Azure 中部署模型和设置 API。如果你有兴趣,那么请跟着我上媒。**
感谢阅读这篇长文!
****成为媒介上的作家:https://czakozoltan08.medium.com/membership
我真的很喜欢咖啡,因为它给我精力去写更多的文章。如果你喜欢这篇文章,那么你可以给我买杯咖啡来表达你的欣赏和支持!
从 GitHub 向 Firebase 部署 Angular 应用程序
如何为自动化部署创建简单的 CI/CD 管道

由 Vadim Sadovski 在 Unsplash 上拍摄的照片
持续集成、持续交付或 CI/CD。这是开发人员的一个行话,而且有充分的理由。CI/CD 管道允许我们自动化大部分代码部署过程,使其在过程中更快更安全。
CI 部分包括构建、打包和测试我们的应用程序的自动化。在大多数情况下,这是由 Angular 自动完成的。而且,一旦我们编写了单元测试,它们也很容易集成到过程中。
接下来是 CD,我们应用程序的自动交付。在我们的例子中,这是对 Firebase 的部署。
在本文中,我们将使用 GitHub 操作来自动化 CI/CD 管道。这意味着每次我们点击git push origin master时,GitHub 会自动启动一个完整的构建、打包、(测试)和部署过程。我们将涵盖:
> Deployment Setup
- Writing Our Deployment (YAML)
- Secret Keys (With GitHub)
部署设置
首先,我们假设 Angular 应用程序已经通过常规的firebase deploy部署到 Firebase 主机上——如果你还没有这样做,请遵循这个指南。不会超过几分钟!
一旦我们准备好了,我们开始在项目的根目录下创建一个.github文件夹。在那里,我们添加了另一个名为workflows的文件夹,里面有一个名为main.yml的 YAML 文件。

Github Actions(相当于。github \我们项目目录中的工作流)。图片作者。
当目录.github\workflows被推送到 GitHub 时,它将被 GitHub 读取并用作 GitHub Actions 文件夹——我们为工作流存储 YAML 文件的地方!
但是什么是 YAML 文件呢?嗯,根据我们亲爱的维基百科 —
“YAML 是一种人类可读的数据序列化语言。它通常用于配置文件和存储或传输数据的应用程序中。
第一句话的意思是 YAML 是一种我们可以阅读的文件格式!它用于在不同语言或环境之间传输数据(JSON 是另一个例子)。
第二部分是我们需要了解的。这意味着 YAML 是一种提供指令的标准化方式,通常用于配置文件——就像我们的部署配置一样!
编写我们的部署
好的,让我们来看看我们将要使用的 YAML 文件。
虽然它看起来很混乱,但是一旦我们将脚本分解成几个部分,它就会变得非常简单。
- 简单来说就是给代码的不同部分命名(这是可选的!).
on: push: branches: - master,这是我们的触发器。它告诉 GitHub,一旦我们push到master branch,就触发下面的代码。- 接下来,我们在
jobs有我们的执行计划,包括一个build阶段。 - 我们在最新的 Ubuntu 机器
ubuntu-latest上执行一切。 - 现在我们执行计划中的每一个
steps。 - 我们通过
actions/checkout@master将我们的活动分支设置为master。 - 然后用
actions/setup-node@master初始化节点,这样我们就可以在下面的步骤中使用npm。 npm install添加了我们所有的应用依赖项,如下所示:

在 GitHub 动作中安装依赖项部署阶段。
- 之后,我们用
npm run build编译我们的应用程序——它被翻译成ng build:

GitHub 操作中部署的构建阶段。
- 最后,我们使用
w9jds/firebase-action@master部署我们新构建的应用程序,其中有两个额外的参数: - 我们传递了
deploy --only hosting参数,这意味着我们只部署到 Firebase 主机(而不是函数,例如)。 - 我们通过存储在 repo 中的
FIREBASE_TOKEN密钥传递我们的 Firebase 安全令牌(对我们进行身份验证)(我们将在接下来讨论这一点)。
这涵盖了我们的 YAML 中的所有内容,只不过是我们在部署应用程序时通常会执行的操作——除了指定操作系统!
秘密钥匙
唯一缺少的部分就是我们的FIREBASE_TOKEN。让我们解决这个问题。

如何使用 Firebase CLI 获取我们的 Firebase 令牌。图片作者。
首先,我们需要获得我们的访问令牌,为此我们只需:
1。打开我们的 CLI 并导航到我们的项目——通过键入firebase use [project-id](上面未显示)确保正确的 Firebase 项目处于活动状态。
2。使用firebase login:ci请求我们的 CI(持续集成)访问令牌,这将打开一个新窗口(否则,输入提供的 URL)。
3。在授权窗口中,我们需要登录 Google Cloud 并授权访问我们的帐户。
4。最后,我们收到了一个访问令牌,我们可以使用它将我们的应用程序部署到 Firebase!
现在我们有了令牌,我们需要导航到 GitHub 上的项目 repo 在这里我们可以添加访问令牌。

将 Firebase 令牌添加到项目 repo 的步骤。图片作者。
为此,在项目回购中,我们:
1 /3。从设置 > 机密中导航并点击新机密。打开新的秘密窗口。
4 /6。输入FIREBASE_TOKEN作为秘密名称,输入login firebase:ci提供的令牌,点击添加秘密!
现在,回到我们的 YAML 文件中,${{ secrets.FIREBASE_TOKEN }}允许我们访问刚刚为FIREBASE_TOKEN输入的值,而不需要将它存储在我们的回购文件中。
部署!
一旦我们设置好了一切,我们就像往常一样将项目推送到 GitHub repo 的主分支。回到我们的 CLI,我们输入如下内容:
git add .
git commit -m "Added CI support"
git push -u origin master

在 git 推送 origin master 之后,我们的 Angular 应用程序被部署到 Firebase。
我们的回购照常推送到 GitHub。要查看我们的部署,我们需要在 GitHub 中打开我们的 repo 并点击 Actions 选项卡。我们将看到“所有工作流程”窗口(如上)。

部署进度。
如果我们想更详细地查看我们的部署进度,我们单击我们的部署(在这里我们可以看到我们的提交消息),在侧栏中,单击构建和部署。在这里,我们将能够看到我们的部署正在采取的行动列表。

部署完成!
一旦我们的部署完成,我们将在右上角看到一个绿色的勾号!我们可以通过点击构建和部署窗口中每个部署阶段旁边的下拉箭头来查看部署的更多细节。
最后几个音符
部署生产版本
目前,我们没有部署角度优化的生产构建。就像我们对ng build所做的一样——我们将--prod添加到npm run build以切换到生产版本。
回到我们的 YAML 文件,我们修改Build:
- name: Build
uses: npm run build **--prod**
集成测试
我们也可以合并我们的角度单元测试!就在— name: Install Dependencies之后,我们添加npm test,就像这样:
- name: Install Dependencies
run: npm install
**- name: Testing
run: npm test**
- name: Build
run: npm run build
包扎
我们结束了,我们已经谈了很多了!包括:
- YAML 脚本,以及如何编写一个将 Angular 应用程序部署到 Firebase 的脚本。
- 从 Firebase CLI 获取我们的
FIREBASE_TOKEN,并将其作为密钥添加到我们的 GitHub repo 中。 - 在 GitHub 中部署我们的应用程序并查看部署状态!
- 以及一些关于产品构建和单元测试的额外注释。
因此,我们建立了一个完全自动化的 CI/CD 管道——只要我们在 GitHub 中推送 master 就会触发!
我希望你喜欢这篇文章。如果您有任何问题、想法或建议,请随时通过 Twitter 或在下面的评论中联系我们!
感谢阅读!
将任何 Python 项目部署到 Kubernetes
是时候深入 Kubernetes,使用这个成熟的项目模板将您的 Python 项目带到云中了!

随着项目的增长,它可能会变得难以用单个虚拟机或一些简单的 SaaS 解决方案来处理。你可以通过切换到更强大的解决方案来解决这个问题,如 Kubernetes 。然而,如果你不熟悉它的概念或者以前从未使用过它,这可能会有点太复杂。因此,为了帮助您——在本文中——我们将介绍您入门并在集群上部署您的 Python 项目所需的所有内容——包括集群设置、所有的 Kubernetes 清单和一些额外的自动化,以使您的生活更加轻松!
这是上一篇关于 自动化您的 Python 项目 的每一个方面的文章的后续,所以在阅读本文之前,您可能想要检查一下。
TL;博士:这是我的储存库,里面有完整的源代码和文档:【https://github.com/MartinHeinz/python-project-blueprint】T21
舒适的开发设置
为了在你的开发过程中富有成效,你需要有一个舒适的本地开发环境。在这种情况下,这意味着在本地使用简单的 Kubernetes ,密切镜像您的真实生产集群,为此,我们将使用种类:
KinD(Kubernetes-in-Docker)顾名思义,在 Docker 容器中运行 Kubernetes 集群。它是 Kubernetes 维护人员用于 Kubernetes v1.11+一致性测试的官方工具。它支持多节点集群以及高可用性集群。因为在 Docker 中运行 K8s , KinD 可以在 Windows、Mac、Linux 上运行。所以,你可以在任何地方运行它,你只需要安装 Docker。
所以,让我们安装类(在 Linux 上——如果你在 Windows 上,在这里看安装信息):
这样,我们就可以设置我们的集群了。为此,我们需要以下 YAML 文件:
这份清单描述了我们的星团。它将有 3 个节点—控制平面(role: control-plane)和 2 个工作者role: worker。我们还为它提供了一些更多的设置和参数,以便以后可以设置入口控制器,这样我们就可以在该集群上拥有 HTTPS。关于这些设置,您需要知道的只是extraPortMappings告诉集群将端口从主机转发到节点上运行的入口控制器。
注意:集群和 Python 应用程序的所有清单都可以在我的仓库 中找到,这里是 中的 *k8s* 目录。
现在,我们需要运行几个命令来启动它:
要创建集群,我们只需要运行第一个命令。之后,我们可以通过运行cluster-info和get nodes命令来检查是否可以运行。一段时间后,输入这些命令会变得很烦人,所以我们以后会更简单,但这样我们就可以启动并运行集群了。
接下来,我们要为我们的集群设置入口。为此,我们必须运行一些kubectl命令,使其与类一起工作:
首先,我们部署强制性的ingress-nginx组件。最重要的是,我们使用节点端口来公开 nginx 服务,这就是第二个命令所做的。最后一个命令为入口控制器应用一些类特定补丁。
定义清单
集群就绪后,就该设置和部署我们的应用程序了。为此,我们将使用非常简单的 Flask 应用程序— echo 服务器:
我选择了 Flask 应用程序,而不是一些 CLI 工具(或 Python 包),因为我们需要不会像一些 Python 包那样立即终止的应用程序。另外,请注意host参数被设置为0.0.0.0,如果没有这个参数,当我们通过 Kubernetes 服务和入口公开应用程序时,将无法访问它。
接下来我们需要的是这个应用程序的 YAML 清单,让我们把它分成单独的对象:
- 命名空间:
这里没什么好谈的。我们通常不希望在default名称空间中部署应用程序,所以我们将使用这个名称空间。
- 配置映射:
这是我们可以为应用程序定义变量的地方。这些来自data部分的变量将作为环境变量注入到应用程序容器中。作为一个例子,我包括了FLASK_ENV和FLASK_DEBUG,当应用程序启动时,它们将被烧瓶自动拾取。
- 秘密:
与我们指定纯文本变量的方式相同,我们可以使用 Secret 向我们的应用程序添加凭证和密钥之类的东西。但是,不应该将该对象推送到您的存储库中,因为它包含敏感数据。我们可以使用以下命令动态创建它:
注意:部署应用程序所需的此命令和其他命令列在存储库中的 README 以及底部清单文件 中,此处为 。
- 部署:
.
现在是最重要的部分——部署。这里的相关部分是指定图像、端口和环境变量的spec部分。对于image,我们指定来自 Docker Hub 的图像。如果我们想使用像 Artifactory 这样的私有注册表,我们就必须添加imagePullSecret来提供集群获取映像的凭证。可以使用以下命令创建该密码:
这显示了您如何允许从 GitHub 包注册表中提取您的映像,不幸的是,由于上述 YAML 中列出的问题,它现在不能与类一起工作,但是它可以与您在云中的生产集群一起工作(假设它没有使用类)。
如果您想避免每次重新部署应用程序时都将映像推送到远程注册表,那么您可以使用kind load docker-image martinheinz/python-project-blueprint:flask将映像加载到集群中。
在image之后,我们还指定了ports。这些是我们的应用程序正在监听的端口,在本例中是5000,因为我们的应用程序开始使用app.run(host='0.0.0.0', port=5000)。
最后一部分,envFrom部分用于从上面显示的配置图和秘密中注入明文变量和秘密,通过在各自的Ref字段中指定它们的名称。
- 服务:
现在,我们已经有了在port上监听的应用程序,我们需要服务来公开它。所有这些对象定义了在端口5000上监听的应用程序应该在端口443上的集群节点上公开。
- 入口:
最后一大难题是入口——一个管理集群中服务外部访问的对象。让我们首先看看rules部分——在这种情况下,我们定义我们的主机是localhost。我们还将path设置为/,这意味着发送到localhost/的任何请求都属于由之前显示的服务及其port的名称定义的关联backend。
这里的另一部分是tls。本节通过指定包含tls.crt和tls.key的秘密为列出的hosts提供 HTTPS。让我们创造这个秘密:
上面的代码片段首先设置了几个变量,然后使用openssl为 TLS 生成证书和密钥文件。最后一个命令创建包含这两个文件的秘密。
部署应用程序
准备好所有清单后,我们终于可以部署我们的应用程序了:
上面的大多数命令我们已经在前面的章节中看到过了。新功能是kubectl apply -f app.yaml,它在我们的集群中创建了所有必要的对象。创建后,我们可以使用kubectl get all检查这些对象的存在。最后,我们可以使用cURL来检查应用程序是否是可访问的,它是可访问的!这样,我们的应用程序就可以在集群上运行了!
简单一点
如果你还没有完全适应所有的kind和kubectl命令,或者你像我一样懒,不想把它们都打出来,那么我有几个Make目标给你——让你的生活更轻松:
-
调出集群:
-
重新部署/重新启动应用程序:
如果集群还没有准备好,那么make cluster命令将为您设置集群,如果准备好了,它将为您提供关于它的所有信息。如果您需要检查节点的状态并切换到您的开发名称空间,这很好。
这个非常简单,它所做的只是推出新的部署,因此如果有新的映像,它将部署它,否则它将重新启动您的应用程序。
- 调试:
如果您需要调试您的应用程序,您可能想要查看与应用程序窗格相关的最近事件以及最近(上一小时)的日志。这正是make cluster-debug为你做的。
- 获取远程外壳:
如果日志不足以解决您可能遇到的一些问题,并且您决定需要在容器内部探索一下,那么您可以运行make cluster-rsh来获得远程 shell。
- 更新清单:
我们以前见过这个命令。它只是重新应用了 YAML 清单,这在您调整 Kubernetes 对象的一些属性时非常方便。
结论
这篇文章并不是 Kubernetes 的教程,但是我认为它足够让你快速启动并运行你的应用程序。为了学习更多关于 Kubernetes 的知识,我建议在清单中玩一玩,调整一下,改变一下,看看会发生什么。在我看来,这是了解事物如何工作并熟悉kubectl命令的好方法。如果您有任何疑问、建议或问题,请随时联系我或在我的资源库中创建问题。在这个报告中,你还可以找到本文中显示的文档和所有清单。
资源
本文最初发布于martinheinz . dev
在多个 Docker 容器中部署 Apache Airflow
在 Apache Airflow 中编排数据科学模型,使用 Celery Executor 进行扩展,并使用 Docker Compose 部署在多个 Docker 容器中

约书亚·阿拉贡在 Unsplash 上拍摄的照片
当涉及到数据科学模型时,它们会定期运行。例如,如果我们预测下个月的客户流失,模型必须在每个月的最后一天运行。每月手动运行该模型是不可取的。我们可以使用一个调度程序来自动化这个过程。Apache Airflow 是一个理想的工具,因为它允许调度和监控您的工作流。在本文中,我们将讨论如何使用 Docker 部署 Apache Airflow,并保留进一步扩展的空间。熟悉 Apache Airflow 和 Docker 概念将是阅读本文的一个优势。
阿帕奇气流简介
气流由 3 个主要部分组成;Web 服务器、调度程序和元数据库。Web 服务器负责用户与应用程序交互的用户界面。调度器负责作业调度,而元数据库存储调度细节。即使气流有几个执行器,芹菜执行器更适合可伸缩性。芹菜执行器 3 额外的组件添加到气流。它们是工作者、消息代理和工作者监视器。Worker 负责执行由调度程序触发的作业。可以有多个工人。这些工作者可以分布在集群实例中。工人的数量可以根据系统的工作量和机器的能力来决定。消息经纪人帮芹菜操作。可以使用监控工具来监控芹菜工人。

阿帕奇气流与芹菜执行器(图片由作者)
使用 Docker,我们计划将上述每个组件运行在一个单独的 Docker 容器中。Web 服务器、调度程序和工作人员将使用一个公共的 Docker 映像。这个公共映像对于项目来说是唯一的,我们将讨论构建这个映像的 Dockerfile 文件。所有其他容器将直接使用公开可用的图像。
在本教程中,PostgreSQL 被用作元数据库,Redis 被用作消息代理,而芹菜花被用于监控工人。因为有多个容器,所以使用 Docker Compose 可以很容易地一次性部署所有的容器。
项目结构

项目结构:https://github.com/nishakanthiA/Airflow-Docker(作者图片)
该图像显示了我们的项目结构。所有与项目相关的文件都放在脚本文件夹中。所有与气流相关的文件都放在气流文件夹中。与部署相关的其他文件在最外面的目录中。env.list包括分类模型所需的环境变量。requrements.txt定义要在 python 环境中安装的包,以便运行模型。
Dockerfile用于创建供 Airflow web 服务器、调度程序和工作人员使用的图像。docker-compose.yml用于定义和启动所有的容器。
提出了一个简单的模型来分类著名的虹膜数据集。我已经在 dags 文件夹中添加了两个带有PythonOperator的 DAGs。一个用于训练模型,另一个用于通过已训练的模型获得预测。DAG 到列车模型的定义没有计划间隔。这意味着一旦需要模型训练,它就可以被触发。预测旨在每天检索。因此,生成预测的 DAG 被安排每天运行模型。文件airflow.cfg包含气流的配置属性。
创建 Docker 图像
要使用 docker 展开气流,参考的最佳图像是puck El/docker-air flow。(更新:气流现在有了它的官方 Docker 形象)但是这个形象不能照原样使用;由于一些原因。一个原因是它没有安装我们在项目中使用的所有包。如果我们需要更改 airflow.config 文件中的属性,我们必须将它们作为环境变量传递。由于存在大量变量,这并不容易。因此,我们将使用puckel/docker-airflow的基本映像编写一个定制的 docker 文件。除了 message broker、元数据库和 worker monitor 之外,这个映像将用于我们的所有容器中。以下是 Dockerfile 文件。
FROM puckel/docker-airflow:1.10.9COPY airflow/airflow.cfg ${AIRFLOW_HOME}/airflow.cfgCOPY requirements.txt /requirements.txt
RUN pip install -r /requirements.txt
创建 Docker 容器
元数据库
让我们首先为元数据库容器定义服务。Docker image postgres:9.6用于此。用户凭证和数据库名称应该作为环境变量给出。设置该容器时,数据库名称(POSTGRES_DB=airflow)应与 airflow 配置sql_alchemy_conn中的数据库连接字符串兼容。
version: '3.7'
services:
postgres:
image: postgres:9.6
environment:
- POSTGRES_USER=airflow
- POSTGRES_PASSWORD=airflow
- POSTGRES_DB=airflow
如果您已经有一个现有的 PostgreSQL 服务器,并且希望使用它,则不需要为元数据库部署额外的容器。为服务器中的气流元数据创建专用数据库。Airflow 将在启动时填充数据库,然后负责维护数据库。可以通过气流配置给出服务器的详细信息。设置服务器细节的一种方法是修改airflow.cfg文件中的sql_alchemy_conn。另一种方法是把它作为一个环境变量AIRFLOW__CORE__SQL_ALCHEMY_CONN。下面是为 PostgreSQL 连接提供的连接字符串的格式。登录服务器的凭证用户名、密码、主机 IP、数据库名应该作为环境变量传递。
sql_alchemy_conn =postgresql+psycopg2://$PG_USER:$PG_PASSWORD@$PG_HOST:5432/$PG_DB_NAME
这样,我们的第一个容器就变成可选的了。
芹菜执行器的消息代理
在这个项目中,我们通过使用多个气流工作者来关注应用程序的可伸缩性。为此,我们可以使用芹菜执行器。在气流配置文件中设置executor = CeleryExecutor 。环境变量是AIRFLOW__CORE__EXECUTORT11。
Celery 是一个任务队列实现,Airflow 使用它在后台定期异步运行并行批处理作业。它需要一个像 Redis 和 RabbitMQ 这样的消息代理来传输消息。气流没有这部分,需要外部实现。这里我们用 Redis。我们可以使用 image Docker image *redis:5.0.5*
用我们的第二个容器docker-compose.yml会是这个样子。
version: '3.7'
services:
postgres:
image: postgres:9.6
environment:
- POSTGRES_USER=airflow
- POSTGRES_PASSWORD=airflow
- POSTGRES_DB=airflow
redis:
image: redis:5.0.5
这里我们也可以使用一个外部 Redis 服务,而不需要创建这个容器。凭证应由气流配置文件中的broker_url、celery_result_backend给出。
Airflow Web 服务器

气流用户界面(图片作者)
我们的第三个容器是 Aiflow web 服务器,它负责用户界面。对于这个容器,我们将使用以前创建的 Docker 图像。以下是服务“webserver”的 docker 容器配置。
**webserver:
image:** webserver:latest
**build:
context:** .
**restart:** always
**depends_on:** - postgres
- redis
**environment:** - LOAD_EX=n
- FERNET_KEY=46BKJoQYlPPOexq0OhDZnIlNepKFf87WFwLbfzqDDho=
- EXECUTOR=Celery
- PYTHONPATH=/usr/local/airflow
**env_file:** - env.list
**volumes:** - ./airflow/dags:/usr/local/airflow/dags
- ./scripts:/usr/local/airflow/scripts
**ports:** - **"8080:8080"
command:** webserver
**healthcheck:
test:** [**"CMD-SHELL"**, **"[ -f /usr/local/airflow/airflow-webserver.pid ]"**]
**interval:** 30s
**timeout:** 30s
**retries:** 3
每个命令的用法解释如下。
- 构建上下文:指向创建的 Dockerfile。相应映像是在容器启动时构建的
- 重新启动:如果由于任何原因停止了,重新部署容器。
- 依赖于:web 服务器需要与元数据库和消息代理容器通信
- 环境:这些是基本映像 puckel/docker-airflow 请求的列表环境变量。让它们保持原样。您可以自由地添加更多的环境变量,如“PYTHONPATH ”,这些变量将被您自己的程序脚本使用。
- env_file:可以使用 file 给出环境变量的列表
- 卷:Dag 和程序脚本可以作为卷挂载。这比将文件复制到 Docker 映像中更有效。文件更新后,更改将自动部署到 web 服务器中。不需要构建映像和重新部署容器。
- 端口:要部署的端口。web 服务器正在端口 8080 上运行。
- command : airflow 命令启动 web 服务器。这是基础映像 puckel/docker-airflow 所要求的。不要修改它。
- healthcheck:检查容器健康状况的测试
气流调度程序
我们的第四个容器是 Aiflow scheduler。除了命令和依赖关系之外,服务配置与 Airflow web 服务器非常相似。命令是启动调度程序的气流命令。调度程序依赖于 web 服务器容器。
**scheduler:
image:** scheduler:latest
**build:
context:** .
**restart:** always
**depends_on:** - webserver
**volumes:** - ./airflow/dags:/usr/local/airflow/dags
- ./scripts:/usr/local/airflow/scripts
**environment:** - LOAD_EX=n
- FERNET_KEY=46BKJoQYlPPOexq0OhDZnIlNepKFf87WFwLbfzqDDho=
- EXECUTOR=Celery
- PYTHONPATH=/usr/local/airflow
**command:** scheduler
**env_file:** - env.list
气流工人
下一个集装箱是气流工人。命令是启动工作机的气流命令。工作进程依赖于调度器容器。可以有多个工人。这里我加了两个。
**worker1:
image:** worker1:latest
**build:
context:** .
**restart:** always
**depends_on:** - scheduler
**volumes:** - ./airflow/dags:/usr/local/airflow/dags
- ./scripts:/usr/local/airflow/scripts
**environment:** - FERNET_KEY=46BKJoQYlPPOexq0OhDZnIlNepKFf87WFwLbfzqDDho=
- EXECUTOR=Celery
- PYTHONPATH=/usr/local/airflow
**command:** worker
**env_file:** - env.list
**worker2:
image:** worker2:latest
**build:
context:** .
**restart:** always
**depends_on:** - scheduler
**volumes:** - ./airflow/dags:/usr/local/airflow/dags
- ./scripts:/usr/local/airflow/scripts
**environment:** - FERNET_KEY=46BKJoQYlPPOexq0OhDZnIlNepKFf87WFwLbfzqDDho=
- EXECUTOR=Celery
- PYTHONPATH=/usr/local/airflow
**command:** worker
**env_file:** - env.list
让多个工人在同一台机器上还可以减少作业的执行时间。为了获得更有效和最佳的结果,气流配置文件中的属性parallelism 、dag_concurrency、worker_concurrency和max_threads应根据工人数量进行调整。其中一些属性也可以在 DAG 级别进行调整。
工人可以分布在集群中的多台机器上。一台单独的机器将负责每个工人,而所有其他容器可以部署在一台公共机器上。我们可以保留一个单独的 docker-compose 文件来部署工人。主 docker-compose 文件将包含其余容器的服务。以下是 ECS 集群中 AWS EC2 实例中部署的 worker 容器的 docker-compose 文件示例。
version: '3.7'
services:
remote_worker_3:
image: remote_worker_3:latest
build:
context: .
args:
github_token: ${GITHUB_TOKEN}
restart: always
external_links:
- redis_1:redis
networks:
- sample_project_default
environment:
- FERNET_KEY=46BKJoQYlPPOexq0OhDZnIlNepKFf87WFwLbfzqDDho=
- EXECUTOR=Celery
volumes:
- ./sample_project/airflow/dags:/usr/local/airflow/dags
- ./sample_project/src:/usr/local/airflow/dags/src
env_file:
- env.list
command: worker
stdin_open: true
tty: truenetworks:
sample_project_default:
external: true
网络名称可以通过docker network ls命令找到。如果你有兴趣了解更多关于 Docker 网络搜索的信息。
工人监视器

芹菜花仪表板(https://flower.readthedocs.io/en/latest/screenshots.html)
工人的行为可以通过芹菜花来监控。这也是一个可选的容器。以下是花卉容器的配置。
**flower:
image:** flower:latest
**build:
context:** .
**restart:** always
**depends_on:** - redis
**environment:** - EXECUTOR=Celery
**ports:** - **"5555:5555"
command:** flower
部署
现在,我们准备用多个 Docker 容器部署我们的气流项目。我们可以使用 docker-compose.yml 文件一次性部署所有的容器。下面是一些有用的 Docker 命令。
- 开始容器:
docker-compose up -d -- build - 停止容器:
docker-compose down - 查看容器:
docker ps - 进入一个容器:
docker exec -it <container-id> bash - 查看一个容器的日志:
docker logs <container-id> - 监控集装箱:
docker stats
项目网址:https://github.com/nishakanthiA/Airflow-Docker
用 Python 和 Docker 部署 API
使用 Flask、Docker 和 Google Cloud 部署 API 的权威指南

这里有一些软件开发中的技巧,它们就像闸门一样阻挡着广阔的机会海洋。当学习其中一种技能时,似乎一个全新的世界突然被照亮了。
通过这篇文章,我们将涵盖我认为是这些技能之一。能够编写可部署到互联网并与 API 通信的代码。
构建一个可部署的 API 需要几个子技能,我们将在组装 API 时讨论这些子技能。然而,罗马不是一天建成的,精通(甚至能力)也不是——所以这不是一篇五分钟内从零到英雄的文章。
这篇文章是一个介绍,我们将涵盖要点——不多不少。在本文的最后,我们将拥有一个托管在云上的全功能 API。
简而言之,我们将涵盖—
> **Build an** **API** with Flask
> **Package** our app with Docker
> **Deploy** with Google Cloud Platform (GCP)
> **Test** with Postman
您可以在这里找到本文的 GitHub repo。
用 Flask 构建 API
我们创建一个新文件夹,其中包含一个名为app.py的 Python 脚本。该脚本将包含我们的 API 代码,其结构如下:
importsapp initializationAPI class
GET method
POST method
DELETE methodHTTP mapping
如果事情的顺序变得混乱——完整的app.py脚本在这一部分的末尾,你可以在 GitHub 上找到这个项目。
设置
导入和应用初始化
在这里,我们在导入中设置了最低限度,并像这样初始化我们的 API flask 应用程序:
from flask import Flask
from flask_restful import Resource, Api, reqparse
import pandas as pd
import osapp = Flask(__name__)
api = Api(app)
API 类别
在我们的 API 脚本中,我们需要定义一个包含 HTTP 方法 GET、POST 和 DELETE 的类。
Flask 需要知道这个类是我们 API 的入口点,所以我们用类定义传入Resource。我们将创建一个名为Places的类:
class Places(Resources):
<methods go here>
我们还需要告诉 Flask 这个 API 类的入口点在哪里。例如,如果我们的 API 位于www.api.com,我们可能想要指定在[www.api.com**/places**](http://www.api.com/places.) 提供Places类的入口。
我们可以使用add_resource方法来做到这一点:
api.add_resource(Places, '/places')
这个方法被放在类定义之外,并遵循类定义。
当然,这意味着我们可以在 API 中添加多个类和入口点。这对于更复杂的服务尤其有用——尽管在本文中我们将只讨论其中一个。
为了简单起见,我们将把代码中嵌入的数据作为 Python 字典来操作。看起来是这样的:
DATA = {
'places':
['rome',
'london',
'new york city',
'los angeles',
'brisbane',
'new delhi',
'beijing',
'paris',
'berlin',
'barcelona']
}
获取
我们使用这种方法来获取数据,在我们的例子中,数据就是我们的DATA字典。
def get(*self*):
*# return our data and 200 OK HTTP code* return {'data': DATA}, 200
帖子
POST 方法用于将数据添加到我们的DATA['places']列表中。
def post(*self*):
*# parse request arguments* parser = reqparse.RequestParser()
parser.add_argument('location', *required*=True)
args = parser.parse_args()*# check if we already have the location in places list* if args['location'] in DATA['places']:
*# if we do, return 401 bad request* return {
'message': f"'{args['location']}' already exists."
}, 401
else:
*# otherwise, add the new location to places* DATA['places'].append(args['location'])
return {'data': DATA}, 200
这里发生了什么事?
reqparse库允许我们解析传递给 POST 请求的参数。例如,如果我们的 places API 位于 web 地址api.com/places处,我们可以指定我们要添加的新位置的location,如下所示:
api.com/places?**location=sydney**
- 在取出位置参数后,我们需要检查它是否已经存在于
DATA['places']中——这是我们用if语句完成的。如果数据已经存在,我们简单地返回409 Conflict和一条简短的消息,解释所提供的位置已经存在。 - 否则,我们可以将新位置添加到我们的
DATA['places']列表中,然后返回新的DATA和一个200 OKHTTP 代码。
删除
我们用 DELETE 作为 POST 的一个等价的相反的动作。用户指定要从DATA['places']列表中移除的位置。
def delete(*self*):
*# parse request arguments* parser = reqparse.RequestParser()
parser.add_argument('location', *required*=True)
args = parser.parse_args()*# check if we have given location in places list* if args['location'] in DATA['places']:
*# if we do, remove and return data with 200 OK* DATA['places'].remove(args['location'])
return {'data': DATA}, 200
else:
*# if location does not exist in places list return 404* return {
'message': f"'{args['location']}' does not exist."
}, 404
这里发生了什么事?
作为一个相等且相反的操作,我们稍微修改了 POST 逻辑:
- 我们还是用同样的方法使用
reqparse。 - 对于 location 参数,我们再次使用相同的
if语句来检查它是否已经存在于DATA['places']中。如果是的话,我们从 T3 中 T2 它,并返回新的 T4 和一个 T5 HTTP 代码。 - 否则,我们返回消息
404 Not Found,解释所提供的位置在DATA['places']中不存在。
总共
如果我们将所有这些部分放在一起,我们将得到以下脚本:
带 Docker 的包装
下一步,我们将创建一个 Docker 映像。这里有两个相似的术语——图像和容器。
一个映像本质上是一个蓝图——而一个容器是一个根据蓝图构建的结构/部署。
首先,我们将创建我们的映像,然后将它部署到 Google cloud(在那里它将成为一个容器)。
创建我们的 Docker 形象有三个关键步骤:
- 获取码头工人
- 设置我们的 docker 文件
- 建立我们的形象
1。Docker 文档能够比我更好地指导你完成安装过程!你可以在这里找到它们。
关于 Windows 或 Mac 上 Docker 的概述,请查看此视频:
Windows 上的 Docker 为 1:46:21,Mac 上的 Docker 为 1:53:22。
2。因为我们将 API 部署为 docker 容器,所以我们需要在目录中包含一个名为 Dockerfile 的容器设置文件。
在我们的 docker 文件中,我们将为三个 Python 库使用RUN命令——所有这些都将指定使用一个 requirements.txt 文件。
对于我们的简单 API,它看起来像这样:
flask
flask-restful
gunicorn
在我们的 Dockerfile,中,我们概述了我们的形象(容器蓝图)。Docker 将读取提供“构建”指令的Dockerfile。
FROM python:3.6-slim-busterWORKDIR /app
COPY . .RUN pip install -r requirements.txtCMD exec gunicorn --bind :$PORT --workers 1 --threads 8 --timeout 0 app:app
这里发生了什么?
- 我们使用另一个官方图像和
FROM python:3.6-slim-buster初始化我们的图像。这个脚本初始化官方的 Docker Python 3.6‘slim-buster’图像——官方 Python 图像的完整列表在这里可以找到。 - 接下来,我们将图像中的活动目录设置为带有
WORKDIR /app的/app——这是我们的 Google Cloud 实例所期望的结构。 - 现在我们
COPY从源文件目录到镜像文件系统的所有东西。在这种情况下,从目录Dockerfile所在—到活动图像目录/app。 - 我们的依赖关系列表
requirements.txt现在在镜像文件系统中,我们RUN pip install递归地-r遍历requirements.txt的每一行。实质上就是:
pip install flask
pip install flask-restful
pip install gunicorn
- 最后,我们使用
[gunicorn](https://gunicorn.org/)包初始化我们的 HTTP 服务器。我们使用CMD指令来执行gunicorn并传递几个服务器设置参数。
3。我们的最后一步是构建 Docker 图像,稍后我们将把它上传到 Google 容器注册中心。
要构建映像,请打开 CLI,导航到包含我们的文件的目录,然后键入:
docker build -t tut-api .
- 这里,
docker build是 Docker 镜像构建命令。 - 我们使用
-t标志来指定我们的图像名称。 tut-api仅仅是我们形象的名称,随便你怎么称呼它。.告诉 docker 将当前目录中的所有内容包含在映像中(别忘了这一点,我几乎每次都这么做)。
最后,我们可以继续将我们的 API 部署到云中。
部署到云
这里,我们将使用谷歌云平台(GCP)的容器注册表来存储我们的 Docker 映像,并使用 Cloud Run 来部署它。
项目和容器注册

首先,我们需要建立一个项目。我们首先在云控制台中导航到项目选择器页面,然后点击创建项目。

记下项目 ID —我们稍后会用到。
这里我们简单地给我们的项目起个名字——我的是 medium 。
接下来,我们需要在谷歌控制台中导航到容器注册表 (GCR)。如果我们已经正确设置了我们的项目,我们将会看到如下所示的屏幕:

我们的空谷歌容器注册(GCR)屏幕。
云构建
我们将使用云构建将我们的映像构建到一个容器中。在我们这样做之前,我们需要为我们的项目启用云构建 API。只需点击此处并选择您正在进行的项目:

为云构建 API 注册项目。
现在我们有了项目设置,我们需要使用 Google Cloud SDK 将我们的 API Docker 映像推送到 GCR——我们从这里下载。
证明
安装完成后,我们需要登录 gcloud。为此,只需在 CMD 提示符(或等效的 CLI)中键入:
gcloud auth login
该命令将打开我们的 web 浏览器,允许我们像往常一样登录。然后,我们将 Docker 配置为使用我们的凭证:
gcloud auth configure-docker
上传到容器注册表
我们将使用 GCR 来存储我们的形象。为了构建我们的容器并将其保存到注册表中,我们导航到我们的 API 目录并submit它:
gcloud builds submit --tag gcr.io/[PROJECT-ID]/tut-api
gcloud builds submit是我们用来将图像提交给云构建的命令。
我们的注册表位置作为目标映像提供,其中:
*gcr.io*是 GCR 主机名 。*[PROJECT-ID]*是我们的项目 ID,这是我们在创建项目时看到的——对我来说是*medium-286319*。*tut-api*是我们的形象名称。
现在,如果我们导航回我们的注册表,我们应该会看到我们新上传的 Docker 映像(这可能需要一些时间来构建,请查看您的云构建仪表板):

使用云运行部署
有了 Docker 容器,我们就可以通过 Cloud Run 将它部署到 web 上。

我们通过点击左上角的导航按钮(在 GCP 控制台中)并选择云运行来打开云运行控制台。
接下来,我们将看到云运行界面,我们通过单击创建服务来部署我们的容器:

接下来,我们(2)输入我们的首选部署设置,(3–4)选择我们的容器映像,以及(5)创建我们的部署!
在我们的 API 被部署之后,我们可以在云运行控制台的顶部找到 API 的 URL。

云运行中 API 的 URL。
测试我们的部署
对于测试 API, Postman 是你的朋友——在这里找到下载链接。

安装完成后,打开 Postman 并输入 API 的网址,例如:
[https://tut-api-2czbipghsq-ew.a.run.app/](https://tut-api-2abcdefgh-ew.a.run.app/.)
在我们的代码中,我们将我们的Places类的位置指定为/places:
api.add_resource(Places, '/places')
因此,我们知道要访问包含在Places中的方法,我们必须将/places添加到我们的 API 地址:
[https://tut-api-2czbipghsq-ew.a.run.app**/places**](https://tut-api-2abcdefgh-ew.a.run.app/places)
得到
对于 GET 请求,这就是我们所需要的—将其输入地址栏,在下拉列表中单击 GET ,然后单击 Send 。

顶栏显示我们正在向https://tut-api-2czbipghsq-ew.a.run.app/places发送一个 GET 请求。底部区域显示我们的数据响应,右上角显示状态:200 OK 。
让我们也测试一下其他方法——记住为 POST 和 DELETE 请求添加我们的location参数,并更新请求类型(在下拉列表中)。
邮政

在下拉列表中选择岗位,添加?location=sydney 到地址栏,点击发送。我们将返回我们的数据附加 sydney。

仍然使用 POST ,我们将地址栏中的悉尼改为罗马,并点击发送。我们将返回一个 401 未授权的 HTTP 代码和一条简单的消息,告诉我们罗马已经存在。
删除

在下拉列表中选择删除,我们保留位置为罗马,点击发送。我们将返回删除了罗马的数据。

现在,如果我们试图删除东京(不存在)——我们将返回一个 404 Not Found HTTP 代码,并带有一条消息告诉我们东京不存在。
打开闸门
这就是这个简单的 API 示例,它内置在 Flask 中,并使用 Docker 部署在 GCP 上。
简而言之,构建一个 API 并将其部署到 web 上是一个极其简单而高效的过程。这并不难,并为我们打开了一片广阔的机会之门。
我希望你喜欢这篇文章——如果你有任何问题或建议,请随时通过 Twitter 或在下面的评论中联系我们。如果你想要更多这样的内容,我也会在 YouTube 上发布。
感谢阅读!
如果您喜欢这篇文章,并且有兴趣进一步拓展您在网络技术方面的技能组合,请在此尝试我的数据科学角度介绍:
[## 如何使用 Angular 部署 TensorFlow Web 应用程序
在角度构建的 web 应用程序中使用 Python 构建的模型
towardsdatascience.com](/how-to-use-angular-to-deploy-tensorflow-web-apps-5675b5a042cc)
使用 CDK 将自动扩展机器学习模型推理堆栈部署到 AWS
使用 AWS/CDK 的强大功能,在一个堆栈中部署 ML 模型,该堆栈可以自动扩展,以便在 CPU 或 GPU 上进行推理

来源: unsplash
几年来,数据科学和机器学习非常性感,许多公司都将“人工智能”作为一种新的强大工具,以黑匣子的形式自动化复杂的任务。在这个领域,深度学习似乎是建立模型来检测和分类图像或文本以及其他酷东西的圣杯。一旦训练好模型,通常将它们部署在小型 web 服务器上,并公开一个简单的 REST API 来对给定的样本执行推理。它通常非常方便,而训练模型需要大量的计算能力和大量的 GPU,推理只需要一个相对低功率的 CPU 来对单个样本进行预测。您可以找到许多关于这种方法的文章和博客帖子;事件开源项目和公司可以使整个事情变得轻松。
然而,在有些情况下,您需要不仅对一个样本,而且对一批样本进行推断。在这种情况下,推理在 CPU 上执行时会花费大量时间,您需要使用 GPU 来并行化作业。使用一个小的网络服务器现在不再适用,因为你不想为一台连接了 GPU 的一直运行的机器付费。例如,假设您必须对上传到您的 S3 存储桶的大文件执行一些预测。你的文件首先被分割成小块,模型根据这些小块进行预测。你想要的是你的栈在一个文件准备好处理的时候自动启动,使用一个有 GPU 的机器,当没有东西要处理的时候关闭整个东西。因为没有可用的无服务器堆栈(将来会有吗?),我们需要构建一个堆栈来根据我们的需求自动扩展。
体系结构
建议的体系结构如下:我们得到一个带有要执行的任务的 SQS 消息。例如,它可能是 S3 上要处理的文件的名称。根据在 AWS 的参数存储中找到的配置参数,该消息被转发到另一个 SQS 队列,一个用于基于 CPU 的堆栈,另一个用于基于 GPU 的堆栈。然后,ECR 集群使用 Cloudwatch 警报来触发两个自动伸缩组的伸缩,一个使用纯 CPU 实例,另一个使用支持 GPU 的实例。然后将结果返回到 S3 桶中。

提议的架构
自动化
为了使整个过程更加自动化,我们可以使用 CDK 应用程序。就像 Terraform 或 Kubernetes 提供通过代码构建堆栈一样,CDK 倾向于成为在 AWS 上部署堆栈的参考。你当然可以使用 Cloudformation,但是一想到要使用非常大的 YAML 文件来管理一个堆栈,我就害怕。然而,使用像 Typescript、C#或 Python 这样的现代编程语言要有趣得多。在存储库源代码中,您可以找到两个类来构建堆栈:DeployModelEcsMediumStackCore和DeployModelEcsMediumStack。第一个,顾名思义,构建堆栈的核心,即主 SQS 队列,附加一个 lambda 函数、一个 ECS 集群和一些 IAM 策略的定义。然后DeployModelEcsMediumStack类为 CPU 或 GPU 架构构建一个堆栈。SQS 队列和相关指标、具有正确 AMI 的自动扩展组、实例类型和扩展策略,以及具有要检索的正确 ECR 映像的 ECS 任务。
串
首先,应该用ecs.Cluster构造创建一个集群。在那里,我们创建一个自动扩展组,使用cluster.addCapacity静态方法向集群添加一个容量提供者。然后我们需要用构造ecs.Ec2TaskDefinition创建一个任务,提供用静态方法ecs.ContainerImage.fromEcrRepository检索的正确的 ECR 图像。该映像必须是基于 ECS 优化 AMI 的映像才能正常工作。没有官方的 AWS AMI 支持 ECS 的 GPU,但是你可以找到自定义的。我们还需要注意gpuCount属性,当我们要使用 GPU 时,将其设置为1。最后,使用构造ecs.Ec2Service创建服务,并将其附加到集群。
使用堆栈
一旦一切都部署完毕,您所需要做的就是在主 SQS 队列中发送一条消息,其中包含要执行的命令,在我的示例中就是要在 S3 上检索的文件的名称。要决定是使用基于 GPU 的实例还是仅使用 CPU 的实例,我们只需要在系统管理器的参数存储中更改配置。这种消息的一个例子可以是
aws sqs send-message --queue-url [https://sqs.ca-central-1.amazonaws.com/1234567890/MediumArticleQueue](https://sqs.ca-central-1.amazonaws.com/1234567890/MediumArticleQueue) --message-body '{"filename": "file_to_process.bin"}'
行列
在提议的架构中有三个 SQS 队列,但是用户只需要在主队列[MediumArticleQueue](https://sqs.ca-central-1.amazonaws.com/1234567890/MediumArticleQueue)中发送一个消息。一旦接收到消息,λ函数被触发,并且关于配置(SSM/参数存储中的参数),消息被转发到适当的队列,GPUQueue用于管理基于 GPU 的实例的自动缩放组,CPUQueue用于仅基于 CPU 的实例。
密码
这个 CDK 堆栈的 typescript/python 代码在这里发布有点大,但是你可以在这个 repo 中找到源代码。请随意复制或分叉代码,只需竖起大拇指或一点点意见将不胜感激。
最后一个音符
在源代码中,我定义了警报来缩放自动缩放组,但没有缩放任务计数。原因是在添加 ECS 服务时,我们还用ecsService.autoScaleTaskCount方法设置了它的自动伸缩行为。然而,AWS/CDK 没有正确地将任务扩展和实例扩展联系起来,而任务扩展和实例扩展是容量提供者的职责。当您直接在控制台中工作时,可以实现这种行为,但不是通过编程实现的。有一个 PR 来纠正它,但是在这篇文章发表的时候它还不可用。为了以后支持这个特性,我添加了一个注释代码部分来说明当这个特性发布时,代码会是什么样子。
使用 PyCaret 构建:在 Microsoft Azure 平台上部署
实用教程
将机器学习模型部署到 Microsoft Azure 平台
在这个故事中,我开发了一个工作教程,在微软的 Azure 云平台上部署一个用pycaret库训练的模型。在我之前的文章用 PyCaret 构建:在 Google 云平台上部署中,我们已经学习了如何在 Google 云上部署模型。我们将在本教程中使用相同的示例,并在 Microsoft Azure 平台上部署该模型。

我们学习把用pycaret训练的模型部署到微软 Azure 平台上。pycaret支持在 AWS 上部署训练有素的模型,但目前不支持 GCP 或 Azure。我遵循了类似于 library 中使用的代码实践,用 AWS 部署和加载模型,在微软的 Azure 平台上部署模型。
PyCaret 是 Python 中的一个开源、低代码机器学习库,允许您在几秒钟内从准备数据到在您选择的笔记本环境中部署模型。来源
PyCaret 是公民数据科学家的 autoML 框架,在其官方文档和主页中使用。这是一个相对较新的库,几个月前发布供公众使用,目前仍在积极开发中。在浏览了一些源代码后,我意识到当前的公开版本缺乏对 Google 和 Azure 云平台的训练/最终模型部署的支持。不过,它支持在 Amazon web services 上部署。
微软 Azure 是另一个非常受欢迎的云服务框架,目标市场不同于谷歌和 AWS。Azure 已经拥有庞大的客户群,并获得了合理的市场份额。在我看来,对于公民数据科学家来说,大概微软 Azure 是最好的起点。让我们学习如何在 Microsoft Azure 上部署模型。
对于本教程,我们将使用回归教程(REG101) —初级初学者进行模型训练。
正在安装 pycaret
!pip install pycaret
安装 Gdrive
我们需要安装 google drive 来读取 colab 环境中的数据。下面是最简单的安装方法。您将被要求输入访问过程生成的令牌。这里是关于安装 gdrive 的文章的链接
在本教程中,我们将在 Google drive 上本地保存模型。
from google.colab import drive
drive.mount('/content/drive')Drive already mounted at /content/drive; to attempt to forcibly remount, call drive.mount("/content/drive", force_remount=True).
让我们创建一个目录来本地保存模型。
# Create directory on google drive to save models locally. You can use temp paths.
import os
model_dir = '/content/drive/My Drive/azure_deploy_model/'
os.makedirs(model_dir, exist_ok=True)
获取数据
您可以从这里找到的原始源下载数据,并使用 pandas (了解如何使用) 加载数据,或者您可以使用 PyCaret 的数据存储库,使用get_data()函数加载数据(这将需要互联网连接)。
from pycaret.datasets import get_data
dataset = get_data('diamond')

#check the shape of data
dataset.shape(6000, 8)data = dataset.sample(frac=0.9, random_state=786).reset_index(drop=True)
data_unseen = dataset.drop(data.index).reset_index(drop=True)
print('Data for Modeling: ' + str(data.shape))
print('Unseen Data For Predictions: ' + str(data_unseen.shape))Data for Modeling: (5400, 8)
Unseen Data For Predictions: (600, 8)
在 PyCaret 中设置环境
让我们使用 pycaret 的设置模块设置建模管道。
from pycaret.regression import *exp_reg101 = setup(data = data, target = 'Price', session_id=123)Setup Successfully Completed!

创建一个轻型 GBM 模型
对于本教程,我们使用 pycaret 中实现的许多选项中的轻量级 GBM 对数据进行建模。您可以选择任何您喜欢的模型,但这不是本教程的重点。
lightgbm = create_model('lightgbm')

调谐光梯度增强机
让我们来训练这个模型,用 pycaret 的术语来说,这个模型也被称为调整模型。
tuned_lightgbm = tune_model('lightgbm')

残差图
下图显示了模型的残差
plot_model(tuned_lightgbm)

预测误差图用于绘制目标的预测误差与真实值。
plot_model(tuned_lightgbm, plot = 'error')

特征重要性图
特征重要性是非常有用的图,可以看到模型中每个特征的贡献。
plot_model(tuned_lightgbm, plot='feature')

分析模型性能的另一种方法是使用evaluate_model()功能,该功能显示给定模型所有可用图的用户界面。它在内部使用plot_model()功能。
evaluate_model(tuned_lightgbm)interactive(children=(ToggleButtons(description='Plot Type:', icons=('',), options=(('Hyperparameters', 'param…
根据测试/保留样本进行预测
predict_model(tuned_lightgbm);

最终确定用于部署的模型
final_lightgbm = finalize_model(tuned_lightgbm)#Final Light Gradient Boosting Machine parameters for deployment
print(final_lightgbm)LGBMRegressor(boosting_type='gbdt', class_weight=None, colsample_bytree=1.0,
importance_type='split', learning_rate=0.4, max_depth=10,
min_child_samples=20, min_child_weight=0.001, min_split_gain=0.9,
n_estimators=90, n_jobs=-1, num_leaves=10, objective=None,
random_state=123, reg_alpha=0.9, reg_lambda=0.2, silent=True,
subsample=1.0, subsample_for_bin=200000, subsample_freq=0)predict_model(final_lightgbm)
****
根据看不见的数据预测
unseen_predictions = predict_model(final_lightgbm, data=data_unseen)
unseen_predictions.head()

Label列被添加到data_unseen集合中。标签是使用final_lightgbm模型的预测值。如果您想对预测进行四舍五入,您可以在predict_model()中使用round参数。
保存模型
让我们首先在本地保存模型
model_dir
model_name = 'Final_lightgbm_model''/content/drive/My Drive/azure_deploy_model/'# Saving model to google drive
save_model(final_lightgbm, model_dir + model_name)Transformation Pipeline and Model Successfully Saved
加载保存的模型
为了在将来的某一天在相同或不同的环境中加载已保存的模型,我们将使用 PyCaret 的load_model()函数,然后轻松地将已保存的模型应用于新的未知数据进行预测。
saved_final_lightgbm = load_model(model_dir + model_name)Transformation Pipeline and Model Successfully Loaded
一旦模型加载到环境中,您就可以使用相同的predict_model()函数简单地使用它来预测任何新数据。下面我们应用了加载模型来预测我们在上面第 13 节中使用的相同的data_unseen。
new_prediction = predict_model(saved_final_lightgbm, data=data_unseen)new_prediction.head()

注意unseen_predictions和new_prediction的结果是相同的。
在 Microsoft Azure 上部署训练模型
微软 Azure 是最大的云提供商之一,在云即服务上提供机器学习。在我之前的文章中,我已经介绍了将模型部署到 Google 云平台。图书馆已经支持亚马逊网络服务部署。
一旦我们有了训练好的模型,下一个任务就是部署它来为客户服务。有各种可用的部署选项,但是在本节中,我将重点关注在 Microsoft Azure 平台上部署它。我尝试使用类似于pycaret库中的方法在 AWS 上部署。
先决条件
在 Azure cloud 上部署 ml 模型的先决条件是
- 熟悉微软 Azure 平台
- Microsoft Azure 帐户
- 基本了解存储容器及其命令行工具
- 使用 pycaret 的最终训练模型
import os, uuid
from azure.storage.blob import BlobServiceClient, BlobClient, ContainerClient
AZURE _ STORAGE _ CONNECTION _ STRING是连接到 AZURE 存储 blob 的身份验证字符串。您可以在您的环境中设置该字符串,并且可以随时使用。另一种选择是,只要需要连接,就输入字符串。
微软 Azure 存储容器相当于谷歌云存储桶
# add the connection string in environment
# Linux
! export AZURE_STORAGE_CONNECTION_STRING="<yourconnectionstring>"
# After you add the environment variable, restart any running programs that will need to read the environment variable. For example, restart your development environment or editor before continuing.
# Retrieve the connection string for use with the application. The storage
# connection string is stored in an environment variable on the machine
# running the application called AZURE_STORAGE_CONNECTION_STRING. If the environment variable is
# created after the application is launched in a console or with Visual Studio,
# the shell or application needs to be closed and reloaded to take the
# environment variable into account.
connect_str_env = os.getenv('AZURE_STORAGE_CONNECTION_STRING')
您可以使用下面的表单在 google colab 中输入您的连接字符串
## Enter connection string when running in google colab
connect_str = 'Enter Connection String Here' #@param {type:"string"}
print(connect_str)
若要创建到 blob 容器的连接,请使用下面的命令创建服务客户端对象。
# Create the BlobServiceClient object which will be used to create a container client
blob_service_client = BlobServiceClient.from_connection_string(connect_str)
我写了/收集了下面的实用程序来从 blobs 上传/下载数据。
def create_container(container_name):
# Create the container
container_client = blob_service_client.create_container(container_name)
return container_client
def upload_blob(container_name, source_file_name, destination_blob_name):
# Create a blob client using the local file name as the name for the blob
blob_client = blob_service_client.get_blob_client(container=container_name, blob=destination_blob_name)
print("\nUploading to Azure Storage as blob:\n\t" + source_file_name)
# Upload the created file
with open(source_file_name, "rb") as data:
blob_client.upload_blob(data)
def download_blob(container_name, source_blob_name, destination_file_name):
# Download the blob to a local file
print("\nDownloading blob to \n\t" + destination_file_name)
# Create a blob client using the local file name as the name for the blob
blob_client = blob_service_client.get_blob_client(container=container_name, blob=source_blob_name)
if destination_file_name is not None:
with open(destination_file_name, "wb") as download_file:
download_file.write(blob_client.download_blob().readall())
print(
"Blob {} downloaded to {}.".format(
source_blob_name, destination_file_name
)
)
将模型保存到 Azure 容器
使用上面的工具,使用下面的代码将模型上传到 Azure-container。在上传之前,我们创建容器,如果以前没有这样做。
也可以使用 GUI 创建容器。
# Create a unique name for the container
container_name = "pycaret" + str(uuid.uuid4())
container_client = create_container(container_name)
# Save Model Local/google drive and upload to Azure
model_name_azure = 'lightgbm-reg101-azure'
save_model(final_lightgbm, model_name= model_dir + model_name_azure, verbose=False)
model_src = model_dir + model_name_azure +'.pkl'
model_dst = str(model_name)+'.pkl'upload_blob(CLOUD_PROJECT, bucket_name, model_src, model_dst)File /content/drive/My Drive/azure_deploy_model/lightgbm-reg101-azure.pkl uploaded to Final_lightgbm_model.pkl.
从 Azure 下载预测模型
一旦你的模型上传到 Azure,你可以随时下载来执行预测。我遵循一个简单的流程,首先在本地或 google drive 中下载模型,然后使用load_model函数加载模型。
print("\nListing blobs...")
# List the blobs in the container
blob_list = container_client.list_blobs()
for blob in blob_list:
print("\t" + blob.name)
outfile_name = model_dir + 'lightgbm-reg101-azure-downloaded'
model_azure_src = str(model_name)+'.pkl'
download_blob(container_name, model_azure_src, outfile_name + '.pkl')
使用最近从 Azure 下载的模型来执行预测。
# Loading the model for predictions
azure_final_lightgbm = load_model(outfile_name)Transformation Pipeline and Model Successfully Loaded# Predictions from deployed model
new_prediction_azure = predict_model(azure_final_lightgbm, data=data_unseen)new_prediction_azure.head()

谷歌 Colab 笔记本
按照下面的谷歌合作笔记本来复制和实践这个指南。
结论
在本教程中,我们学习了如何在使用pycaret库进行培训时将模型部署到 Microsoft Azure。
主要目标是使用[pycaret](https://github.com/pycaret/pycaret)的内置实用程序从 Azure 部署和加载模型。以下是一些亮点
- 安装 google drive 以保存模型
- 用
pycaret训练回归模型 - 保存和加载经过培训/最终确定的模型 Microsoft Azure
- 将经过培训/最终确定的模型部署到微软的 Azure 容器
- 使用 Azure 部署的模型来执行预测
使用 Amazon SageMaker 部署 Fastai —基于变压器的 NLP 模型,并使用 AWS API 网关和 Lambda 函数创建 API

Fastai-Transformers 模型部署在 AWS SageMaker 上,并作为 AWS API 提供服务。
目录
- 介绍
- 第 1 部分—导出模型并重新加载它
- 第 2 部分——使用 Amazon SageMaker 进行部署
- 第 3 部分——使用 Amazon Lambda 和 Amazon API Gateway 创建模型 API
- 结论
- 参考
1.介绍
T 何变形金刚库由抱脸创建。这个库以前被称为 pytorch-transformers 或 pytorch-pretrained-bert,它汇集了 40 多个最先进的预训练 NLP 模型(bert、GPT-2、罗伯塔、CTRL……)。这是一个自以为是的库,专为寻求使用/研究/扩展大规模变压器模型的 NLP 研究人员而建。
该实现提供了有趣的附加工具,如 tokenizer、optimizer 或 scheduler。它可以是自给自足的,但是将它并入 fastai 库提供了与强大的 fastai 工具兼容的更简单的实现,例如区分学习率、逐步解冻或倾斜三角形学习率。这里的重点是轻松获得最先进的结果,并“让 NLP 再次变得不酷”。
我假设您已经实现了您的模型,我不打算讨论这一部分,本文将只讨论使用 AWS 服务的部署部分,但是如果您需要查看实现,请查看 Kaggle 上的这个内核。
2.第 1 部分—导出模型并重新加载它
2.1。 导出模型
首先,我们需要使用 fastai 库的学习模块将我们的模型导出为 PKL 文件:
2.2.加载模型:
当使用自定义的 transformers 模型(如 Bert)时,您需要重新定义自定义模型的体系结构,以便在加载它时,load_learner()函数会查找特定的函数以用于新的预测。
在加载模型之前,我们需要重新定义我们在培训中使用的定制 transformer 模型。
然后我们可以加载我们的模型并进行预测:
3.第 2 部分——使用 Amazon SageMaker 进行部署
用亚马逊自己的话说:
亚马逊 SageMaker 为每一个开发者和数据科学家提供了快速构建、训练和部署机器学习模型的能力。Amazon SageMaker 是一个完全托管的服务,涵盖了整个机器学习工作流,以标记和准备您的数据,选择算法,训练模型,调整和优化它以进行部署,进行预测,并采取行动。您的模型以更少的工作量和更低的成本更快地投入生产。
SageMaker 提供了一个框架来训练和部署您的模型。一切都在 Docker 容器中运行。

AWS SageMaker 的用户界面
因为我们将使用 Amazon SageMaker Python SDK,所以我们需要一个笔记本实例来运行我们的代码。
3.1。 使用 SageMaker Python SDK 部署模型
来自 SageMaker Python SDK 文档:
Amazon SageMaker Python SDK 是一个开源库,用于在 Amazon SageMaker 上训练和部署机器学习模型。
通过 SDK,你可以使用流行的深度学习框架、亚马逊提供的算法或你自己的内置于 SageMaker 兼容的 Docker 图像中的算法来训练和部署模型。
3.1.1。 准备环境:
部署的总体架构如下:

部署架构
将您的模型(PKL 文件)上传到笔记本实例后,我们需要将它压缩,这样我们就可以将它上传到 S3。
然后,我们可以将它上传到 S3 存储,如下所示:
现在我们已经准备好将我们的模型部署到 SageMaker 模型托管服务中。我们将使用 SageMaker Python SDK 和 Amazon SageMaker 开源 PyTorch 容器,因为该容器支持 fast.ai 库。使用一个预定义的 Amazon SageMaker 容器可以很容易地编写一个脚本,然后在 Amazon SageMaker 中运行它。
为了在 SageMaker 中服务模型,我们需要一个实现 4 个方法的脚本: model_fn,input_fn,predict_fn & output_fn 。
- model_fn 方法需要从磁盘上保存的权重中加载 PyTorch 模型。
- input_fn 方法需要将 invoke 请求体反序列化为我们可以对其执行预测的对象。
- predict_fn 方法接受反序列化的请求对象,并对加载的模型执行推理。
- output_fn 方法获取预测结果,并根据响应内容类型将其序列化。
方法 input_fn 和 output_fn 是可选的,如果省略,SageMaker 将假定输入和输出对象是 NPY 格式类型,内容类型为 application/x-npy。
这是 serve.py 脚本:
另一件事是将这个脚本放在一个文件夹中,并将其命名为 my_src,我们将添加一个需求文本文件;来强制 SageMaker 安装所需的库,比如 Fastai。
我的 requirements.txt 文件仅包含以下内容:
fastai==1.0.52
变压器
你可以在 SageMaker Python SDK 文档这里读到更多关于这个的内容。
3.1.2。 部署型号:
首先,我们需要创建一个 RealTimePredictor 类来接受 JSON/application item 作为输入和输出 JSON。默认行为是接受 NumPy 数组。
我们需要得到 IAM 角色 ARN 给 SageMaker 权限,以读取我们的模型从 S3 人工制品。
我们将把我们的模型部署到实例类型 ml.p2.xlarge。我们将传入我们的服务脚本的名称,例如 serve.py。我们还将传入我们之前上传的模型的 S3 路径。
SageMaker 需要一段时间来为推断准备好端点。
3.2.3。 使用 Boto3 调用端点:
Boto 是 Python 的 Amazon Web Services (AWS) SDK。它使 Python 开发人员能够创建、配置和管理 AWS 服务,如 EC2 和 S3。Boto 提供了一个易于使用的、面向对象的 API,以及对 AWS 服务的底层访问。
4.第 3 部分——使用 Amazon Lambda 和 Amazon API Gateway 创建模型 API
我们将使用 API Gateway 和 AWS Lambda 调用 Amazon SageMaker 部署的模型端点。
下图显示了如何使用无服务器架构调用部署的模型。从客户端开始,客户端脚本调用 Amazon API Gateway API 动作并传递参数值。API 网关是向客户端提供 API 的层。此外,它还密封了后端,这样 AWS Lambda 就可以在一个受保护的私有网络中运行。API Gateway 将参数值传递给 Lambda 函数。Lambda 函数解析该值并将其发送到 SageMaker 模型端点。该模型执行预测,并将预测值返回给 AWS Lambda。Lambda 函数解析返回值并将其发送回 API Gateway。API 网关用该值响应客户端。

部署架构
4.1。创建亚马逊 Lambda 函数
AWS Lambda 是一个事件驱动的无服务器计算平台,由亚马逊提供,作为亚马逊网络服务的一部分。它是一种计算服务,运行代码以响应事件,并自动管理该代码所需的计算资源。
为了创建一个函数,我们指定它的名称和运行时环境(在我们的例子中是 Python 3):

然后,我们使用自定义函数调用使用 Boto3 库的端点,如下所示:
4.2。 创建亚马逊 Web API 网关实例:
Amazon API Gateway 是一个完全托管的服务,使开发人员可以轻松地创建、发布、维护、监控和保护任何规模的 API。
我们创建一个 API 并将其关联到 Lambda 函数作为一个集成,如下所示:

然后我们需要确定 API 的路由,我们将只使用一个路由“/classify”和“POST”作为我们的请求方法。

4.3。 测试你的亚马逊 API
现在我们有了 Lambda 函数、API 网关和测试数据,让我们使用 Postman 来测试它,Postman 是一个用于测试 web 服务的 HTTP 客户端。
当我们部署您的 API 网关时,它提供了如下所示的调用 URL:
https://{restapi_id}。执行-api。{ region } . Amazon AWS . com/{ stage _ name }/{ resource _ name }
在 Postman 中,我们放置调用 URL,并选择 POST 作为请求方法。在 Body 选项卡中,我们放置要分类的文本,如下图所示。
然后我们发送我们的请求,它将返回 JSON item 作为包含模型预测的响应。

使用 postman 测试 API
我们还可以使用 python 中的请求库,如下所示:
结论
就是这样。您已经创建了一个由 Amazon SageMaker 部署和托管的模型端点。然后创建了调用端点的无服务器组件(一个 API 网关和一个 Lambda 函数)。现在你知道如何使用无服务器技术调用亚马逊 SageMaker 托管的机器学习模型端点了。
参考
这是使用亚马逊 SageMaker 的程序员实用深度学习 fast.ai 课程 v4 的快速入门指南…
course.fast.ai](https://course.fast.ai/start_sagemaker.html) [## 使用 Amazon API Gateway 和 AWS Lambda | Amazon Web 调用 Amazon SageMaker 模型端点…
在 AWS 机器学习研讨会上,客户经常会问,“在我部署了一个端点之后,我该从那里去哪里?”你可以…
aws.amazon.com](https://aws.amazon.com/blogs/machine-learning/call-an-amazon-sagemaker-model-endpoint-using-amazon-api-gateway-and-aws-lambda/) [## 步骤 6.1:将模型部署到 SageMaker 托管服务
要在 SageMaker 托管服务中部署模型,您可以使用 Amazon SageMaker Python SDK 或 AWS SDK
docs.aws.amazon.com](https://docs.aws.amazon.com/sagemaker/latest/dg/ex1-deploy-model.html)
在 Google Kubernetes 引擎上部署使用 Streamlit 和 PyCaret 构建的机器学习应用程序
在 Google Kubernetes 引擎上封装和部署 Streamlit 应用程序的循序渐进的初学者指南

在 Google Kubernetes 引擎上封装和部署 streamlit 应用程序的循序渐进的初学者指南
概述
在我们关于在云中部署机器学习管道的上一篇文章中,我们展示了如何在 PyCaret 中开发机器学习管道,并在 Heroku PaaS 上部署一个训练有素的模型,作为使用 Streamlit 开源框架构建的 web 应用程序。如果你以前没有听说过 PyCaret,你可以阅读这个公告来了解更多。
在本教程中,我们将使用相同的机器学习管道和 Streamlit 应用程序,并演示如何将它们封装和部署到 Google Kubernetes 引擎上。
在本教程结束时,您将能够在 Google Kubernetes 引擎上构建和托管一个全功能的容器化 web 应用程序。该 web 应用程序可用于使用经过训练的机器学习模型生成在线预测(逐个)和批量预测(通过上传 csv 文件)。最终的应用程序如下所示:

最终应用程序(第 1 页,共 2 页)
👉您将在本教程中学到什么
- 什么是容器,什么是 Docker,什么是 Kubernetes,什么是 Google Kubernetes 引擎?
- 建立一个 Docker 图像,并上传到谷歌容器注册(GCR)。
- 在 GCP 上创建一个集群,并以 web 服务的形式部署一个机器学习应用。
- 看看一个使用训练有素的机器学习管道来实时预测新数据点的 web 应用程序。
过去,我们讨论过使用 docker 的容器化以及在 Azure、GCP 和 AWS 等云平台上的部署。如果您有兴趣了解更多相关信息,可以阅读以下教程:
- 使用 PyCaret 和 Streamlit 构建和部署机器学习 web 应用
- 在 AWS Fargate 上部署机器学习管道
- 在 Google Kubernetes 引擎上部署机器学习管道
- 在 AWS Web 服务上部署机器学习管道
- 在 Heroku PaaS 上构建和部署您的第一个机器学习 web 应用
💻本教程的工具箱
PyCaret
PyCaret 是 Python 中的一个开源、低代码机器学习库,用于训练和部署机器学习管道和模型到生产中。PyCaret 可以使用 pip 轻松安装。
pip install **pycaret**
细流
Streamlit 是一个开源的 Python 库,可以轻松地为机器学习和数据科学构建漂亮的定制 web 应用。使用 pip 可以轻松安装 Streamlit。
pip install **streamlit**
谷歌云平台
由谷歌提供的谷歌云平台(GCP)是一套云计算服务,运行在谷歌内部用于其最终用户产品(如谷歌搜索、Gmail 和 YouTube)的相同基础设施上。如果你没有 GCP 的账户,你可以在这里注册。如果你是第一次注册,你将获得 1 年的免费学分。
让我们开始吧。
在我们进入 Kubernetes 之前,让我们了解一下什么是容器,为什么我们需要一个容器?

https://www.freepik.com/free-photos-vectors/cargo-ship
您是否遇到过这样的问题:您的代码在您的计算机上运行得很好,但是当一个朋友试图运行完全相同的代码时,却无法运行?如果你的朋友重复完全相同的步骤,他或她应该得到相同的结果,对不对?一个词的答案是 环境。你朋友的环境和你不一样。
环境包括什么?Python 等编程语言以及所有库和依赖项,以及构建和测试应用程序时使用的确切版本。
如果我们可以创建一个可以转移到其他机器上的环境(例如:你朋友的电脑或者谷歌云平台这样的云服务提供商),我们就可以在任何地方重现结果。因此,容器 是一种将应用程序及其所有依赖项打包的软件,因此应用程序可以从一个计算环境可靠地运行到另一个计算环境。
那 Docker 是什么?

Docker 是一家提供允许用户构建、运行和管理容器的软件(也叫 Docker)的公司。虽然 Docker 的集装箱是最常见的,但还有其他不太出名的替代品,如 LXD 和 LXC 也提供集装箱解决方案。**
现在您已经具体了解了容器和 docker,让我们了解 Kubernetes 是什么。
什么是 Kubernetes?
Kubernetes 是 Google 在 2014 年开发的一个强大的开源系统,用于管理容器化的应用程序。简而言之,Kubernetes 是一个跨机器集群运行和协调容器化应用的系统。这是一个旨在完全管理容器化应用程序生命周期的平台。

特征
✔️ 负载平衡:自动在集装箱之间分配负载。
✔️ 缩放:当需求发生变化时,如高峰时间、周末和节假日,通过添加或移除容器来自动放大或缩小。
✔️ 存储:保持存储与应用程序的多个实例一致。
✔️ 自我修复自动重启失败的容器,并杀死不响应用户定义的健康检查的容器。
✔️ 自动化部署你可以自动化 Kubernetes 为你的部署创建新的容器,移除现有的容器,并把它们的所有资源都移植到新的容器中。
有 Docker 为什么还要 Kubernetes?
想象一下这样一个场景,您必须在多台机器上运行多个 docker 容器来支持一个企业级 ML 应用程序,无论白天还是晚上都有不同的工作负载。虽然听起来很简单,但手动完成的工作量很大。
您需要在正确的时间启动正确的容器,弄清楚它们如何相互通信,处理存储问题,以及处理失败的容器或硬件。这就是 Kubernetes 正在解决的问题,它允许大量的容器和谐地一起工作,减少了操作负担。
什么是 Google Kubernetes 引擎?
Google Kubernetes 引擎是 Google 开源的 Kubernetes 在 Google 云平台上的一个实现。简单!
其他受欢迎的 GKE 替代品是亚马逊 ECS 和 T2 微软 Azure Kubernetes 服务。
最后一次,你明白吗?
- ****容器是一种打包应用程序及其所有依赖项的软件,因此应用程序可以从一个计算环境可靠地运行到另一个计算环境。
- Docker 是一个用于构建和管理容器的软件。
- Kubernetes 是一个开源系统,用于在集群环境中管理容器化的应用程序。
- ****Google Kubernetes 引擎是开源的 Kubernetes 框架在 Google 云平台上的实现。
在本教程中,我们将使用谷歌 Kubernetes 引擎。为了跟进,你必须有一个谷歌云平台账户。点击此处免费报名。
设置业务环境
一家保险公司希望通过使用住院时的人口统计和基本患者健康风险指标来更好地预测患者费用,从而改善其现金流预测。

( 数据来源 )
目标
使用训练有素的机器学习模型和管道,构建支持在线(逐个)以及批量预测的 web 应用程序。
任务
- 使用 PyCaret 训练、验证和开发机器学习管道。
- 构建一个前端 web 应用程序,具有两个功能:(一)在线预测和(二)批量预测。
- 创建 Dockerfile 文件
- 在 Google Kubernetes 引擎上部署 web 应用程序。一旦部署,它将成为公开可用的,并可以通过网址访问。
👉任务 1 —模型训练和验证
培训和模型验证是在集成开发环境(IDE)或笔记本电脑中进行的,可以在本地机器上进行,也可以在云上进行。如果您以前没有使用过 PyCaret,单击此处了解更多关于 PyCaret 的信息,或者在我们的网站上查看入门教程。
在本教程中,我们进行了两个实验。第一个实验是使用 PyCaret 中的默认预处理设置进行的。第二个实验具有一些额外的预处理任务,例如缩放和归一化、自动特征工程和将宁滨连续数据分成区间。参见第二个实验的设置代码:
****# Experiment No. 2**from **pycaret.regression** import *****r2 = **setup**(data, target = 'charges', session_id = 123,
normalize = True,
polynomial_features = True, trigonometry_features = True,
feature_interaction=True,
bin_numeric_features= ['age', 'bmi'])**

两个实验的信息网格比较
神奇的事情只发生在几行代码中。请注意,在实验 2** 中,转换后的数据集有 62 个用于训练的特征,这些特征仅来自原始数据集中的 6 个特征。所有的新特性都是 PyCaret 中的转换和自动特性工程的结果。**

转换后数据集中的列
PyCaret 中模型定型的示例代码:
**# Model Training and Validation
lr = **create_model**('lr')**

线性回归模型的 10 倍交叉验证
注意转换和自动特征工程的影响。R2 不费吹灰之力就增加了 10%。我们可以比较两个实验的线性回归模型的残差图,并观察转换和特征工程对模型的异方差的影响。
**# plot residuals of trained model **plot_model**(lr, plot = 'residuals')**

线性回归模型的残差图
机器学习是一个迭代的过程。迭代的次数和其中使用的技术取决于任务的关键程度,以及预测错误时的影响。在医院的 ICU 中实时预测患者结果的机器学习模型的严重性和影响远远超过为预测客户流失而建立的模型。
在本教程中,我们只执行了两次迭代,第二次实验中的线性回归模型将用于部署。然而,在这个阶段,模型仍然只是笔记本/ IDE 中的一个对象。要将其保存为可以传输到其他应用程序并由其他应用程序使用的文件,请执行以下代码:
**# save transformation pipeline and model
**save_model**(lr, model_name = 'deployment_28042020')**
当您在 PyCaret 中保存一个模型时,基于在 setup() 函数中定义的配置的整个转换管道被创建。所有的相互依赖都是自动编排的。查看存储在“deployment_28042020”变量中的管道和模型:

使用 PyCaret 创建的管道
我们已经完成了培训和模型选择。最终的机器学习管道和线性回归模型现在保存为 pickle 文件(deployment_28042020.pkl ),该文件将在 web 应用程序中用于生成对新数据点的预测。
👉任务 2 —构建前端 web 应用程序
现在,我们的机器学习管道和模型已经准备好开始构建一个前端 web 应用程序,它可以在新的数据点上生成预测。该应用程序将通过 csv 文件上传支持“在线”以及“批量”预测。让我们将应用程序代码分成三个主要部分:
页眉/布局
该部分导入库,加载训练模型,并创建一个基本布局,顶部有一个徽标,一个 jpg 图像,边栏上有一个下拉菜单,用于在“在线”和“批量”预测之间切换。

app.py —代码片段第 1 部分
在线预测
本节处理初始 app 功能,在线逐一预测。我们使用 streamlit 小部件,如数字输入、文本输入、下拉菜单和复选框来收集用于训练模型的数据点,如年龄、性别、身体质量指数、儿童、吸烟者、地区。

app.py —代码片段第 2 部分
批量预测
批量预测是该应用的第二层功能。streamlit 中的 file_uploader 小部件用于上传 csv 文件,然后从 PyCaret 调用原生的 predict_model() 函数来生成预测,使用 streamlit 的 write()函数显示这些预测。

app.py —代码片段第 3 部分
如果您还记得上面的任务 1,我们最终确定了一个线性回归模型,该模型根据从 6 个原始特征中提取的 62 个特征进行了训练。web 应用程序的前端有一个输入表单,只收集六个特征,即年龄、性别、bmi、儿童、吸烟者、地区。
我们如何将新数据点的这 6 个特征转换成用于训练模型的 62 个特征?我们不需要担心这一部分,因为 PyCaret 通过编排转换管道自动处理这一部分。当您在使用 PyCaret 定型的模型上调用 predict 函数时,在从定型模型生成预测之前,会自动(按顺序)应用所有转换。
在 Heroku 上发布应用程序之前的最后一步是在本地测试 web 应用程序。打开 Anaconda 提示符,导航到您的项目文件夹并执行以下代码:
****streamlit** run app.py**

简化应用测试—在线预测

简化应用测试—批量预测
现在我们有了一个全功能的 web 应用程序,我们可以开始在 Google Kubernetes 引擎上封装和部署应用程序了。
👉任务 3 —创建 Dockerfile 文件
为了将我们的应用程序进行容器化部署,我们需要一个 docker 映像,它在运行时成为一个容器。使用 docker 文件创建 docker 映像。Dockerfile 只是一个包含一组指令的文件。该项目的 docker 文件如下所示:
Dockerfile 文件
这个 Dockerfile 文件的最后一部分(从第 23 行开始)是特定于 Streamlit 的,通常不需要。Dockerfile 区分大小写,必须与其他项目文件位于项目文件夹中。
👉任务 4 —在 GKE 部署洗钱渠道:
如果你想继续,你必须从 GitHub 中派生出这个库。

https://github.com/pycaret/pycaret-streamlit-google
按照以下简单的 10 个步骤在 GKE 集群上部署应用程序。
步骤 1 —在 GCP 控制台中创建新项目
登录您的 GCP 控制台,然后转到“管理资源”

谷歌云平台控制台→管理资源
点击创建新项目****

Google 云平台控制台→管理资源→创建新项目
步骤 2 —导入项目代码
点击控制台窗口右上角的激活云壳按钮,打开云壳。

谷歌云平台(项目信息页面)
在 Cloud Shell 中执行以下代码来克隆本教程中使用的 GitHub 存储库。
**git clone [https://github.com/pycaret/pycaret-streamlit-google.git](https://github.com/pycaret/pycaret-streamlit-google.git)**
步骤 3-设置项目 ID 环境变量
执行以下代码来设置 PROJECT_ID 环境变量。
**export PROJECT_ID=**pycaret-streamlit-gcp****
pycaret-streamlit-gcp 是我们在上面的步骤 1 中选择的项目的名称。
步骤 4 —构建 docker 映像
通过执行以下代码,构建应用程序的 docker 映像并标记它以便上传:
**docker build -t gcr.io/${PROJECT_ID}/insurance-streamlit:v1 .**

docker 构建成功时返回的消息
您可以通过运行以下代码来检查可用的图像:
****docker** images**
步骤 5 —上传容器图像
- 认证到容器注册表(您只需要运行一次):
**gcloud auth configure-docker**
2.执行以下代码将 docker 图像上传到 Google 容器注册表:
**docker push gcr.io/${PROJECT_ID}/insurance-streamlit:v1**
步骤 6 —创建集群
现在容器已经上传,您需要一个集群来运行容器。一个集群由一个运行 Kubernetes 的计算引擎 VM 实例池组成。
- 为 gcloud 工具设置项目 ID 和计算引擎区域选项:
**gcloud config set project $PROJECT_ID
gcloud config set compute/zone **us-central1****
2.通过执行以下代码创建一个集群:
**gcloud container clusters create **streamlit-cluster** --num-nodes=2**

谷歌云平台→ Kubernetes 引擎→集群
步骤 7 —部署应用程序
要在 GKE 集群上部署和管理应用程序,您必须与 Kubernetes 集群管理系统通信。执行以下命令来部署应用程序:
**kubectl create deployment insurance-streamlit --image=gcr.io/${PROJECT_ID}/insurance-streamlit:v1**
步骤 8 —将您的应用程序公开到互联网上
默认情况下,您在 GKE 上运行的容器不能从互联网上访问,因为它们没有外部 IP 地址。执行以下代码,将应用程序公开给 internet:
**kubectl expose deployment insurance-streamlit --type=LoadBalancer --port 80 --target-port **8501****
步骤 9 —检查服务
执行下面的代码来获取服务的状态。 EXTERNAL-IP 是您可以在浏览器中查看已发布应用的网址。
**kubectl get service**
第 10 步—在网址上查看应用程序的运行情况

发布于https://34.70.49.248的应用程序—第 1 页

发布于https://34.70.49.248的应用程序—第 2 页
****注意:在这篇文章发表时,该应用程序将从公共地址中删除,以限制资源消耗。
PyCaret 2.0.0 来了!
我们收到了来自社区的大力支持和反馈。我们正在积极改进 PyCaret,并准备我们的下一个版本。 PyCaret 2.0.0 会更大更好。如果您想分享您的反馈并帮助我们进一步改进,您可以在网站上填写此表格或者在我们的 GitHub 或 LinkedIn 页面上发表评论。
关注我们的 LinkedIn 并订阅我们的 YouTube 频道,了解更多关于 PyCaret 的信息。
想了解某个特定模块?
从第一个版本 1.0.0 开始,PyCaret 有以下模块可供使用。点击下面的链接,查看 Python 中的文档和工作示例。
另请参见:
笔记本中的 PyCaret 入门教程:
你愿意投稿吗?
PyCaret 是一个开源项目。欢迎每个人都来投稿。如果您愿意投稿,请随意处理未决问题。dev-1.0.1 分支上的单元测试接受拉请求。
如果你喜欢 PyCaret,请给我们 GitHub 回购的⭐️。
**中:【https://medium.com/@moez_62905/ **
领英:https://www.linkedin.com/in/profile-moez/
推特:https://twitter.com/moezpycaretorg1
使用 Streamlit 和 Polyaxon 将机器学习应用程序部署到 Kubernetes
使用 Polyaxon 在 Azure Kubernetes(AKS) 上训练、分析和部署容器化 Streamlit 机器学习应用的分步指南。
本指南的学习目标
- 集装箱、 Kubernetes 、 Streamlit 和 Polyaxon 简介。
- 创建一个 Kubernetes 集群并使用舵部署 Polyaxon 。
- 如何在 Kubernetes 集群上运行的 Jupyter 笔记本上探索数据集。
- 如何在 Kubernetes 上使用 Polyaxon 训练一个机器学习模型的多个版本。
- 如何保存一个机器学习模型?
- 如何使用 Polyaxon UI 分析模型?
- 如何使用 Streamlit 通过用户界面展示模型并进行新的预测。
本指南所需的工具
什么是容器?
容器是一个标准的软件单元,它将代码及其所有依赖项打包,以便应用程序能够快速可靠地从一个计算环境运行到另一个计算环境。 Docker 是一个工具,旨在通过使用容器来更容易地创建、部署和运行应用程序。
在我们的指南中,我们将使用容器来打包我们的代码和依赖项,并轻松地将它们部署在 Kubernetes 上。
什么是 Kubernetes?
Kubernetes 是一个强大的开源分布式系统,用于管理容器化的应用程序。简而言之,Kubernetes 是一个在机器集群上运行和编排容器化应用的系统。这是一个旨在完全管理容器化应用程序生命周期的平台。

我为什么要用 Kubernetes?
- 负载平衡 : 自动在集装箱之间分配负载。
- 缩放:当需求变化时,如高峰时间、周末和节假日,通过添加或移除容器来自动放大或缩小。
- 存储:保持存储与应用程序的多个实例一致。
- 自我修复自动重启失败的容器,并杀死不响应用户定义的健康检查的容器。
- 自动化部署您可以自动化 Kubernetes 为您的部署创建新的容器,删除现有的容器,并将它们的所有资源应用到新的容器中。
什么是 Streamlit?
Streamlit 是一个开源框架,用来创建一个交互式的、漂亮的可视化应用。全部用 python!
Streamlit 提供了许多有用的特性,对数据驱动项目的可视化非常有帮助。
使用 Streamlit 的 Face-GAN 浏览器示例

这个 Streamlit 应用程序使用邵伯关的 TL-GAN 演示了 NVIDIA 名人脸 GAN 模型。
为什么我应该使用 Streamlit?
- 创建交互式用户界面的简单易行的方法
- 不需要开发经验
- 在数据驱动的项目中使用不同的功能很有趣:)
- 全面的文档
什么是 Polyaxon?
Polyaxon 是一个开源的云本机机器学习平台,它提供了简单的接口来训练、监控和管理模型。
Polyaxon 运行在 Kubernetes 之上,允许扩展和缩减集群的资源,并提供工具来自动化实验过程,同时跟踪关于模型、配置、参数和代码的信息。
我为什么要用 Polyaxon?
- 自动跟踪关键模型度量、超参数、可视化、工件和资源,以及版本控制代码和数据。
- 通过 CLI、dashboard、SDK 或 REST API 调度作业和实验,最大限度地提高集群的利用率。
- 使用优化算法有效地运行并行实验,并找到最佳模型。
- 可视化、搜索和比较实验结果、超参数、训练数据和源代码版本,以便您可以快速分析哪些有效,哪些无效。
- 持续开发、验证、交付和监控模型,以创造竞争优势。
- 根据需要扩展您的资源,并在任何平台(AWS、Microsoft Azure、Google 云平台和本地硬件)上运行作业和实验。
什么是头盔?
Helm 是 Kubernetes 的包管理器,它允许我们部署和管理像 Polyaxon 这样的云原生项目的生命周期。
蓝色库伯内特服务
在本教程中,我们将使用 Azure Kubernetes 服务(AKS) ,这是 Azure 上的一个完全托管的 Kubernetes 服务。如果您没有 Azure 帐户,您可以在此注册一个免费帐户。
在以后的帖子中,我们将提供在谷歌云平台 (GKE) 、 AWS (EKS)和一个带有 Minikube 的本地集群上运行本指南的类似说明。
设置工作空间
本教程的目的是获得在 Kubernetes 上运行机器学习实验和部署的实践经验。让我们从创建工作空间开始。
步骤 1 —使用 AKS 部署 Kubernetes 集群
让我们在 AKS 上创建一个简单的 Kubernetes 集群,它只有一个节点:
az aks create --resource-group myResourceGroup --name streamlit-polyaxon --node-count 1 --enable-addons monitoring --generate-ssh-keys
要确保您在正确的集群上,您可以执行以下命令
az aks get-credentials --resource-group myResourceGroup --name streamlit-polyaxon
步骤 2 —安装头盔
在您的本地机器上安装 Helm 以便能够管理 Polyaxon 以及您可能想要在 Kubernetes 上运行的其他云原生项目。
curl -fsSL -o get_helm.sh [https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3](https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3)chmod 700 get_helm.sh./get_helm.sh
第 3 步-添加多轴图表到头盔
helm repo add polyaxon https://charts.polyaxon.com
步骤 4—安装 Polyaxon CLI
pip install -U polyaxon
步骤 5—将 Polyaxon 部署到 Kubernetes
polyaxon admin deploy
步骤 6—等待部署进入就绪状态
kubectl get deployment -n polyaxon -w
这大约需要 3 分钟:
NAME READY UP-TO-DATE AVAILABLE AGE
polyaxon-polyaxon-api 1/1 1 1 3m17s
polyaxon-polyaxon-gateway 1/1 1 1 3m17s
polyaxon-polyaxon-operator 1/1 1 1 3m17s
polyaxon-polyaxon-streams 1/1 1 1 3m17s
步骤 7-公开 Polyaxon API 和 UI
Polyaxon 提供了一个简单的命令,以安全的方式在本地主机上公开仪表板和 API:
polyaxon port-forward
步骤 8-在 Polyaxon 上创建一个项目
在不同于用于显示仪表板的终端会话中,运行:
polyaxon project create --name=streamlit-app
您应该看到:
Project `streamlit-app` was created successfully.
You can view this project on Polyaxon UI: [http://localhost:8000/ui/root/streamlit-app/](http://localhost:8000/ui/root/streamlit-app/)

Polyaxon 的 Streamlit 项目
现在我们可以进入下一部分:训练和分析模型。
训练机器学习模型
在本教程中,我们将训练一个模型来根据其特征对鸢尾花进行分类。
虹膜特征:萼片,花瓣,长度和宽度
探索数据集
我们将首先在 Kubernetes 集群上运行的笔记本会话中探索 iris 数据集。
让我们启动一个新的笔记本会话,并等待它进入运行状态:
polyaxon run --hub jupyterlab -w
Polyaxon 提供了一系列高效的组件,称为 hub,并允许使用一个命令启动一个笔记本会话。在后台,Polyaxon 将创建一个 Kubernetes 部署和一个 headless 服务,并将使用 Polyaxon 的 API 公开该服务。更多细节请查看 Polyaxon 的开源中心。
几秒钟后,笔记本电脑将开始运行。
注意:如果您停止了上一个命令,您总是可以通过执行以下命令来获取上一个(缓存的)正在运行的操作:
polyaxon 运营服务

运行在 Polyaxon 上的 Jupyter 实验室
让我们创建一个新笔记本,并从检查数据集的功能开始:

探索数据集
执行的命令:
from sklearn.datasets import load_irisiris= load_iris()print(iris.feature_names)
print(iris.target_names)
print(iris.data.shape)
print(iris.target.shape)
print(iris.target)
数据集是关于鸢尾花的种类:

鸢尾花数据集

鸢尾花属性
探索模型
scikit-learn 提供了不同类别的算法,在本教程的范围内,我们将使用 最近邻 s 算法。
在我们创建一个健壮的脚本之前,我们将在笔记本会议中尝试一个简单的模型:

探索模型
执行的命令:
from sklearn.neighbors import KNeighborsClassifierX = iris.data
y = iris.targetclassifier = KNeighborsClassifier(n_neighbors=3)# Fit the model
classifier.fit(X, y)# Predict new data
new_data = [[3, 2, 5.3, 2.9]]
print(classifier.predict(new_data))
# Show the results
print(iris.target_names[classifier.predict(new_data)])
在这种情况下,我们使用n_neighbors=3和完整的数据集来训练模型。
为了探索我们的模型的不同变体,我们需要为我们的模型制作一个脚本,并对输入和输出进行参数化,以方便地更改参数,如n_neighbors。我们还需要建立一些估计模型的性能的严格方法。
一种实用的方法是创建一个评估程序,在该程序中,我们将数据集分成训练和测试。我们在训练集上训练模型,并在测试集上评估它。
scikit-learn 提供了分割数据集的方法:
from sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=1012)
生产模型训练
现在我们已经建立了一些实践,让我们创建一个接受参数、训练模型并保存结果分数的函数:

生产就绪模型
执行的命令:
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn import metrics
from sklearn.datasets import load_iristry:
from sklearn.externals import joblib
except:
passdef train_and_eval(
n_neighbors=3,
leaf_size=30,
metric='minkowski',
p=2,
weights='uniform',
test_size=0.3,
random_state=1012,
model_path=None,
):
iris = load_iris()
X = iris.data
y = iris.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=test_size, random_state=random_state)
classifier = KNeighborsClassifier(n_neighbors=n_neighbors, leaf_size=leaf_size, metric=metric, p=p, weights=weights)
classifier.fit(X_train, y_train)
y_pred = classifier.predict(X_test)
accuracy = metrics.accuracy_score(y_test, y_pred)
recall = metrics.recall_score(y_test, y_pred, average='weighted')
f1 = metrics.f1_score(y_pred, y_pred, average='weighted')
results = {
'accuracy': accuracy,
'recall': recall,
'f1': f1,
}
if model_path:
joblib.dump(classifier, model_path)
return results
现在我们有了一个脚本,它接受参数来评估基于不同输入的模型,保存模型并返回结果,但这仍然是非常手动的,对于更大和更复杂的模型来说,这是非常不切实际的。
用 Polyaxon 进行实验
我们将创建一个脚本并使用 Polyaxon 运行模型,而不是通过手动更改笔记本中的值来运行模型。我们还将使用 Polyaxon 的跟踪模块记录结果指标和模型。
我们将要训练的模型的代码可以在这个 github repo 中找到。
使用默认参数运行示例:
polyaxon run --url=[https://raw.githubusercontent.com/polyaxon/polyaxon-examples/master/in_cluster/sklearn/iris/polyaxonfile.yml](https://raw.githubusercontent.com/polyaxon/polyaxon-examples/master/in_cluster/sklearn/iris/polyaxonfile.yml) -l
使用不同的参数运行:
polyaxon run --url=[https://raw.githubusercontent.com/polyaxon/polyaxon-examples/master/in_cluster/sklearn/iris/polyaxonfile.yml](https://raw.githubusercontent.com/polyaxon/polyaxon-examples/master/in_cluster/sklearn/iris/polyaxonfile.yml) -l -P n_neighbors=50
安排多个平行实验
我们不会手动更改参数,而是通过探索一系列配置来自动完成这一过程:
polyaxon run --url=[https://raw.githubusercontent.com/polyaxon/polyaxon-examples/master/in_cluster/sklearn/iris/hyper-polyaxonfile.yml](https://raw.githubusercontent.com/polyaxon/polyaxon-examples/master/in_cluster/sklearn/iris/hyper-polyaxonfile.yml) --eager
您将看到 CLI 创建了几个并行运行的实验:
Starting eager mode...
Creating 15 operations
A new run `b6cdaaee8ce74e25bc057e23196b24e6` was created
...
分析实验

在 Polyaxon 上并行运行多个实验
根据实验的准确度对实验进行分类

分类实验
比较accuracy和n_neighbors

可视化精度和 n 个邻居
通过准确性选择最佳模型
在我们的脚本中,我们使用 Polyaxon 在每次运行实验时记录一个模型:
# Logging the model
tracking.log_model(model_path, name="iris-model", framework="scikit-learn")

模型谱系
将模型部署为虹膜分类应用程序
我们将部署一个简单的 streamlit 应用程序,它将加载我们的模型并显示一个应用程序,该应用程序根据特征进行预测,并显示与 flower 类对应的图像。
import streamlit as st
import pandas as pd
import joblib
import argparse
from PIL import Image
def load_model(model_path: str):
model = open(model_path, "rb")
return joblib.load(model)
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument(
'--model-path',
type=str,
)
args = parser.parse_args()
setosa = Image.open("images/iris-setosa.png")
versicolor = Image.open("images/iris-versicolor.png")
virginica = Image.open("images/iris-virginica.png")
classifier = load_model(args.model_path)
print(classifier)
st.title("Iris flower species Classification")
st.sidebar.title("Features")
parameter_list = [
"Sepal length (cm)",
"Sepal Width (cm)",
"Petal length (cm)",
"Petal Width (cm)"
]
sliders = []
for parameter, parameter_df in zip(parameter_list, ['5.2', '3.2', '4.2', '1.2']):
values = st.sidebar.slider(
label=parameter,
key=parameter,
value=float(parameter_df),
min_value=0.0,
max_value=8.0,
step=0.1
)
sliders.append(values)
input_variables = pd.DataFrame([sliders], columns=parameter_list)
prediction = classifier.predict(input_variables)
if prediction == 0:
elif prediction == 1:
st.image(versicolor)
else:
st.image(virginica)
让我们用 Polyaxon 来安排应用程序
polyaxon run --url=[https://raw.githubusercontent.com/polyaxon/polyaxon-examples/master/in_cluster/sklearn/iris/streamlit-polyaxonfile.yml](https://raw.githubusercontent.com/polyaxon/polyaxon-examples/master/in_cluster/sklearn/iris/streamlit-polyaxonfile.yml) -P uuid=86ffaea976c647fba813fca9153781ff
注意,在您的用例中,uuid 86ffaea976c647fba813fca9153781ff会有所不同。

在 Polyaxon 上运行的 Streamlit 分类应用程序
结论
在本教程中,我们经历了使用 Kubernetes、Streamlit 和 Polyaxon 训练和部署简单分类应用程序的端到端过程。
你可以在这个 repo 里找到这个教程的源代码。
使用 Chef 部署机器学习应用程序
机器学习
使用配置管理工具 Chef 部署模型概述
作为一名数据科学家,您可能遇到过依赖性问题、对环境不熟悉,或者如何使用 TensorFlow 等工具配置基础架构和版本问题。当我试图在其他主机上运行一个经过训练的模型时,我遇到了同样的问题。然后,这个世界很友好地向我介绍了 Chef——一个为我们完成繁琐任务的配置管理工具。让我向你解释我们从基础开始使用的步骤和工具。那么为什么要等呢?我们开始吧!

COVID19 反馈申请主页(作者照片)
使用情绪分析开发了一个简单的应用程序,以了解人们对国家和中央政府在新冠肺炎事件后采取的措施有多满意。点击此处访问应用程序。
背景
我使用了 Flask、VADER 情绪分析、谷歌计算引擎、Chef——一个配置管理工具&负载平衡器来完成这项任务。你兴奋吗?趁还不算太晚,让我们深潜吧!

这是开始的好时机。(使用 Canva 设计)
用于情感分析的机器学习模型
在这个项目中,我使用了 VADER 情绪分析器来检测对州和中央政府所采取的措施的满意度。VADER (Valence Aware 字典和情感推理器)是一个基于规则的情感分析工具,专门针对社交媒体中表达的情感,适用于不同领域的文本。

情感分析。(使用 Canva 设计)
网络服务器
web 服务器可以是软件应用程序,也可以是硬件,它在任务启动时负责后端活动。根据应用程序的不同,您可以使用不同类型的 web 服务器。对于这个应用程序,我使用了 Flask,这是一个用 Python 编写的微型 web 框架。下面的代码片段显示了我们如何从用户那里获取输入,并将它们呈现给我们的 flask 服务器。

Flask 服务器—客户端。(使用 Canva 设计)
我们将运行 Flask 服务器作为服务。服务通过在系统打开和关闭时自动允许程序启动和停止来帮助用户在后台运行某个程序。
现在,运行在 flask 服务器上的模型已经准备好了,让我们深入了解软件团队在生产环境中开发和部署大型应用程序时可能面临的错综复杂的问题。
演示没有配置管理的生活
如果没有配置管理,组织可能会面临各种挑战。让我们考虑一个软件开发者试图实现一个新的特性,并且在这个过程中安装了几个包或者软件并且成功地部署了一个代码。这位开发人员没有系统地安排依赖关系,并向他的团队成员承诺,他将在以后使用适当的文档来完成这项工作。

管理(使用 Canva 制作)
但赶时间的压力让他忘记了安排一切,让未来的队友更好地破译一切。他达到了他的目标,他的老板和队友暂时感到满意,他继续前进。另一个开发人员被指定完成项目的后续任务。新的开发者现在只能靠自己去理解一切,试图揭开那里到底发生了什么的神秘面纱。可能会发生这样的情况,他宁愿根本不碰服务器的配置,担心他可能会失去什么!

开发者的问题。(使用 Canva 设计)
上述情况正是配置管理帮助您避免的。作为开发人员,我们理解文档的重要性,不想让其他开发人员对发生的事情一无所知。相反,我们会赞成一个项目,为我们提供以下细节。
我们在运行什么服务?这些服务处于什么状态?
他们是如何走到现在的状态的?
变化的目的是什么?
配置管理帮助我们得到这些答案。

使用 Canva 制作
所以 SCM(软件配置管理)很神奇,懂!但是,我们如何做到这一点,并利用我们的优势所有功能呢?你看,这并不困难,我们有很多工具来实现 SCM,其中很少是 Ansible、Puppet、Juju、SaltStack 和 Chef。在我们的应用程序中,正在使用 Chef,所以让我们开始学习 Chef 的故事吧!
厨师
- chef 是一家公司,是用 Ruby 和 Erlang 写的一个配置管理工具的名字。老实说,厨师这个名字和它的作用非常相关。厨师通常会写下食谱,拿走所有的配料,然后开始准备菜肴。类似地,在我们的软件配置管理工具——Chef 的情况下,也在做同样的事情,但是有不同的术语和结果。它由三个重要部分组成,即工作站、Chef 服务器和节点。

厨师 Infra。(来源— Chefdoc )
- 还有一种称为 chef-client 的东西,它充当在 chef 管理下的每个节点(您很快就会理解这个术语)上本地运行的代理。当 chef-client 运行时,它将执行使节点进入预期状态所需的所有步骤。既然 chef-clients 已经在节点上设置好了,让我们开始理解这三个重要的片段是做什么的。
厨师—工作站
- 这是仓库,基站,后台,准备室,或者任何你想叫它的地方。我们应用程序的完整代码在这里开发和测试,然后使用 chef 命令工具(Chef 开发工具包)进行配置。chef-server 收到的所有请求都由工作站处理(批准/拒绝/修改)。
- 我们在工作站开发的东西被称为配方。因此,菜谱是一种管理“系统组件”(也称为资源)的方式,它通过安装包、运行程序以及在需要时创建、编辑或删除文件来实现。
- 在所有的下载和开发完成后,所有的代码和文件都按照期望的顺序排列,并存储在食谱中。
- 一旦烹饪书里的食谱准备好了,就使用工具厨房进行测试,看看是否一切就绪。一旦满意,我们使用 Knife 将包含资源和食谱的食谱以及支持的组件上传到 Chef 服务器。
主厨—服务员
Chef 服务器充当信息中心。Chef 为我们提供了自己的托管服务器,随时可供使用。Chef 服务器精确地连接了工作站和所有节点。我们从工作站接收食谱、食谱、策略和其他有用的组件,chef-server 会将我们的食谱分发到任何与其连接的受管节点。

主厨服务器。(使用 Canva 设计)
Chef 节点
- 节点是由 Chef 管理的任何机器,它可以是物理、虚拟或云网络设备。如上所述,节点使用 chef-client 服务从 chef-server 获取并应用食谱,这个过程称为聚合。当一个节点聚合时,它与服务器同步,并且每当它被触发时,它将更新任何策略。为此,我们首先需要启动节点(创建虚拟机)。我使用谷歌云平台(GCP)的谷歌计算引擎在云中创建节点/虚拟机。节点也可以是任何公共计算机,而不仅仅是云。
- 为了在 chef 服务器和节点之间建立成功的通信,必须完成引导。要添加这些凭证和所有需求,我们只需使用以下单一命令引导该节点安装所有组件。
knife bootstrap FQDN -x user -P password — sudo -N nodename -r “recipe[cookbookname]”
负载平衡器
如果在同一个实例中传递了太多的请求,ML 模型可能需要相当长的时间才能给出输出。我们经常看到一条消息,上面写着“服务器忙”。为了避免这种情况,我们使用了负载平衡器。根据需要创建几个服务器,负载平衡器帮助将流量重定向到密度较低的服务器或节点。下面的图片将帮助你更好地描绘它。

负载平衡。(使用 Canva 设计)
作为一名数据科学家,您不必担心编写厨师代码。我已经创建了一个 Chef cookbook,它需要一个到您的应用程序的 GitHub 库的链接作为输入。使用在任何云服务上创建的节点的 FQDN 运行上面的命令。就是这样,您的应用程序将处于生产环境中!
完整的代码和食谱可以在这里找到。
结论
为了避免各种 ML 工具/包的版本问题,并花一些时间开发模型,维护一本 Chef cookbook 是一个好的实践。第一次可能会花一些时间,但是以后您可以将同一本书用于任何其他应用程序。希望我能给你一个清晰的关于 Chef 的概念,以及它在 ML 模型的成功部署中的作用。我会很快再见到你,为你带来更多关于不同技术的有趣解释!
如果您想联系,在 LinkedIn 上联系我。
在 Google Kubernetes 引擎上部署机器学习管道

在 Google Kubernetes 引擎上封装和部署 ML 管道的循序渐进的初学者指南
概述
在我们关于在云中部署机器学习管道的上一篇文章中,我们展示了如何用 PyCaret 开发机器学习管道,用 Docker 将其容器化,并作为使用 Microsoft Azure web App 服务的 Web 应用。如果你以前没有听说过 PyCaret,请阅读这个公告以了解更多信息。
在本教程中,我们将使用我们之前构建和部署的相同的机器学习管道和 Flask 应用程序。这次我们将演示如何在 Google Kubernetes 引擎上封装和部署机器学习管道。
👉本教程的学习目标
- 了解什么是容器,什么是 Docker,什么是 Kubernetes,什么是 Google Kubernetes 引擎?
- 建立一个 Docker 图像,并上传到谷歌容器注册(GCR)。
- 使用 Flask app 作为 web 服务创建集群和部署机器学习管道。
- 看看一个使用训练有素的机器学习管道来实时预测新数据点的 web 应用程序。
之前我们展示了如何在 Heroku PaaS 上部署 ML 管道和如何在 Azure Web 服务上使用 Docker 容器部署 ML 管道。
本教程将涵盖整个工作流程,从构建 docker 图像开始,将其上传到 Google Container Registry,然后将预训练的机器学习管道和 Flask 应用程序部署到 Google Kubernetes 引擎(GKE)上。
💻本教程的工具箱
PyCaret
PyCaret 是 Python 中的开源、低代码机器学习库,用于训练和部署机器学习管道和模型到生产中。PyCaret 可以使用 pip 轻松安装。
pip install pycaret
瓶
Flask 是一个允许你构建 web 应用的框架。web 应用程序可以是商业网站、博客、电子商务系统,也可以是使用训练好的模型从实时提供的数据中生成预测的应用程序。如果你没有安装 Flask,你可以使用 pip 来安装。
谷歌云平台
由谷歌提供的谷歌云平台(GCP)是一套云计算服务,运行在谷歌内部用于其最终用户产品(如谷歌搜索、Gmail 和 YouTube)的相同基础设施上。如果你没有 GCP 的账户,你可以在这里注册。如果你是第一次注册,你将获得 1 年的免费学分。
让我们开始吧。
在我们进入 Kubernetes 之前,让我们了解一下什么是容器,为什么我们需要一个容器?

【https://www.freepik.com/free-photos-vectors/cargo-ship 号
您是否遇到过这样的问题:您的代码在您的计算机上运行得很好,但是当一个朋友试图运行完全相同的代码时,却无法运行?如果你的朋友重复完全相同的步骤,他或她应该得到相同的结果,对不对?一个词的答案是 环境。你朋友的环境和你不一样。
环境包括什么?→编程语言,如 Python 和所有的库和依赖项,以及构建和测试应用程序所使用的确切版本。
如果我们可以创建一个可以转移到其他机器上的环境(例如:你朋友的电脑或者谷歌云平台这样的云服务提供商),我们就可以在任何地方重现结果。因此,容器 是一种将应用程序及其所有依赖项打包的软件,因此应用程序可以从一个计算环境可靠地运行到另一个计算环境。
那 Docker 是什么?

Docker 是一家提供允许用户构建、运行和管理容器的软件(也称为 Docker)的公司。虽然 Docker 的集装箱是最常见的,但也有其他不太出名的选择,如提供集装箱解决方案的 LXD 和 LXC。
现在您已经具体了解了容器和 docker,让我们了解 Kubernetes 是什么。
什么是 Kubernetes?
Kubernetes 是 Google 在 2014 年开发的一个强大的开源系统,用于管理容器化的应用程序。简而言之,Kubernetes 是一个跨机器集群运行和协调容器化应用的系统。这是一个旨在完全管理容器化应用程序生命周期的平台。

由 Unsplash 上的 chuttersnap 拍摄
特征
✔️ 负载平衡:自动在集装箱之间分配负载。
✔️ 扩展:当需求变化时,如高峰时间、周末和节假日,通过添加或删除容器来自动扩展或缩小。
✔️ 存储:保持存储与应用程序的多个实例一致。
✔️ 自我修复自动重启失败的容器,并杀死不响应用户定义的健康检查的容器。
✔️ 自动化部署您可以自动化 Kubernetes 来为您的部署创建新的容器,删除现有的容器,并将它们的所有资源应用到新的容器中。
有 Docker 为什么还要 Kubernetes?
想象一下这样一个场景,您必须在多台机器上运行多个 docker 容器来支持一个企业级 ML 应用程序,无论白天还是晚上都有不同的工作负载。虽然听起来很简单,但手动完成的工作量很大。
您需要在正确的时间启动正确的容器,弄清楚它们如何相互通信,处理存储问题,以及处理失败的容器或硬件。这就是 Kubernetes 正在解决的问题,它允许大量的容器和谐地一起工作,减少了操作负担。
将 Docker 与 Kubernetes 相提并论是错误的。这是两种不同的技术。Docker 是一个允许你容器化应用程序的软件,而 Kubernetes 是一个容器管理系统,允许创建、扩展和监控成百上千个容器。
在任何应用程序的生命周期中,Docker 用于在部署时打包应用程序,而 kubernetes 用于在生命周期的其余时间管理应用程序。

通过 Kubernetes / Docker 部署的应用程序的生命周期
什么是 Google Kubernetes 引擎?
Google Kubernetes 引擎是 Google 开源 Kubernetes 在 Google 云平台上的实现。简单!
其他受欢迎的 GKE 替代品有亚马逊 ECS 和微软 Azure Kubernetes 服务 T21。
最后一次,你明白吗?
- ****容器是一种打包应用程序及其所有依赖项的软件,因此应用程序可以从一个计算环境可靠地运行到另一个计算环境。
- Docker 是一款用于构建和管理容器的软件。
- Kubernetes 是一个在集群环境中管理容器化应用的开源系统。
- ****Google Kubernetes 引擎是开源的 Kubernetes 框架在 Google 云平台上的实现。
在本教程中,我们将使用谷歌 Kubernetes 引擎。为了跟进,你必须有一个谷歌云平台账户。点击这里免费报名。
设置业务环境
一家保险公司希望通过使用住院时的人口统计和基本患者健康风险指标来更好地预测患者费用,从而改善其现金流预测。

( 数据源 )
目标
构建和部署一个 web 应用程序,将患者的人口统计和健康信息输入到基于 web 的表单中,然后输出预测的收费金额。
任务
- 为部署培训和开发机器学习管道。
- 使用 Flask 框架构建 web 应用程序。它将使用经过训练的 ML 管道实时生成对新数据点的预测。
- 建立一个 docker 图像,并上传到谷歌容器注册(GCR)的容器。
- 创建集群并在 Google Kubernetes 引擎上部署应用程序。
由于我们已经在最初的教程中介绍了前两个任务,我们将快速回顾它们,然后集中讨论上面列表中的其余项目。如果您有兴趣了解更多关于使用 PyCaret 在 Python 中开发机器学习管道以及使用 Flask 框架构建 web 应用程序的信息,请阅读本教程。
👉开发机器学习管道
我们正在使用 Python 中的 PyCaret 进行训练,并开发一个机器学习管道,它将作为我们 web 应用程序的一部分。机器学习管道可以在集成开发环境(IDE)或笔记本中开发。我们使用笔记本运行了以下代码:
当您在 PyCaret 中保存一个模型时,基于在 setup() 函数中定义的配置的整个转换管道被创建。所有的相互依赖都是自动编排的。查看存储在“deployment_28042020”变量中的管道和模型:

使用 PyCaret 创建的机器学习管道
👉构建 Web 应用程序
本教程的重点不是构建 Flask 应用程序。这里讨论它只是为了完整性。现在我们的机器学习管道已经准备好了,我们需要一个 web 应用程序,它可以连接到我们训练过的管道,以实时生成对新数据点的预测。我们已经使用 Python 中的 Flask 框架创建了 web 应用程序。该应用程序有两个部分:
- 前端(使用 HTML 设计)
- 后端(使用 Flask 开发)
这是我们的 web 应用程序的外观:

本地计算机上的 Web 应用程序
如果到目前为止你还没有跟上,没问题。您可以简单地从 GitHub 派生这个存储库。此时,您的项目文件夹应该是这样的:

https://www.github.com/pycaret/pycaret-deployment-google
现在我们有了一个全功能的 web 应用程序,我们可以开始在 Google Kubernetes 引擎上封装和部署应用程序了。
在 Google Kubernetes 引擎上部署 ML 管道的 10 个步骤:
👉步骤 1 —在 GCP 控制台中创建新项目
登录您的 GCP 控制台,然后转到“管理资源”

谷歌云平台控制台→管理资源
点击创建新项目****

Google 云平台控制台→管理资源→创建新项目
👉步骤 2 —导入项目代码
点击控制台窗口顶部的激活云壳按钮打开云壳。

谷歌云平台(项目信息页面)
在 Cloud Shell 中执行以下代码来克隆本教程中使用的 GitHub 存储库。
**git clone https://github.com/pycaret/pycaret-deployment-google.git**

git 克隆https://github.com/pycaret/pycaret-deployment-google.git
👉步骤 3-设置项目 ID 环境变量
执行以下代码来设置 PROJECT_ID 环境变量。
**export PROJECT_ID=**pycaret-kubernetes-demo****
py caret-kubernetes-demo是我们在上面的步骤 1 中选择的项目的名称。
👉步骤 4—构建 docker 映像
通过执行以下代码,构建应用程序的 docker 映像并标记它以便上传:
**docker build -t gcr.io/${PROJECT_ID}/insurance-app:v1 .**

docker 构建成功时返回的消息
您可以通过运行以下代码来检查可用的图像:
**docker images**

云壳上“docker images”命令的输出
👉步骤 5—上传容器图像
- 认证到容器注册表(您只需要运行一次):
**gcloud auth configure-docker**
2.执行以下代码将 docker 图像上传到 Google 容器注册表:
**docker push gcr.io/${PROJECT_ID}/insurance-app:v1**
👉步骤 6—创建集群
现在容器已经上传,您需要一个集群来运行容器。一个集群由一个运行 Kubernetes 的计算引擎 VM 实例池组成。
- 为 gcloud 工具设置项目 ID 和计算引擎区域选项:
**gcloud config set project $PROJECT_ID
gcloud config set compute/zone **us-central1****
2.通过执行以下代码创建一个集群:
**gcloud container clusters create **insurance-cluster** --num-nodes=2**

谷歌云平台→ Kubernetes 引擎→集群
👉步骤 7—部署应用程序
要在 GKE 集群上部署和管理应用程序,您必须与 Kubernetes 集群管理系统通信。执行以下命令来部署应用程序:
**kubectl create deployment insurance-app --image=gcr.io/${PROJECT_ID}/insurance-app:v1**

通过 kubectl 创建部署时返回的输出
👉步骤 8—将您的应用程序公开到互联网上
默认情况下,您在 GKE 上运行的容器不能从互联网上访问,因为它们没有外部 IP 地址。执行以下代码,将应用程序公开给 internet:
**kubectl expose deployment insurance-app --type=LoadBalancer --port 80 --target-port 8080**
👉步骤 9—检查服务
执行下面的代码来获取服务的状态。 EXTERNAL-IP 是您可以在浏览器中查看已发布应用的网址。
**kubectl get service**

云壳→ kubectl 获取服务
👉第 10 步——在 http://34.71.77.61:8080 的上查看应用程序的运行情况

最终应用上传至 http://34.71.77.61:8080
****注意:在这篇文章发表时,该应用程序将从公共地址中删除,以限制资源消耗。
PyCaret 1.0.1 来了!
我们收到了来自社区的大力支持和反馈。我们正在积极改进 PyCaret,并准备我们的下一个版本。 PyCaret 1.0.1 会更大更好。如果您想分享您的反馈并帮助我们进一步改进,您可以在网站上填写此表格或者在我们的 GitHub 或 LinkedIn 页面上发表评论。
关注我们的 LinkedIn 并订阅我们的 YouTube 频道,了解更多关于 PyCaret 的信息。
想了解某个特定模块?
从第一个版本 1.0.0 开始,PyCaret 有以下模块可供使用。点击下面的链接,查看 Python 中的文档和工作示例。
另请参见:
笔记本中的 PyCaret 入门教程:
你愿意投稿吗?
PyCaret 是一个开源项目。欢迎每个人都来投稿。如果您愿意投稿,请随意处理未决问题。dev-1.0.1 分支上的单元测试接受拉请求。
如果你喜欢 PyCaret,请给我们 GitHub 回购的⭐️。
中:https://medium.com/@moez_62905/
领英:https://www.linkedin.com/in/profile-moez/
推特:【https://twitter.com/moezpycaretorg1 T43
无需管理员权限即可安全部署机器学习模型
通过诗歌和 Dash 分享您的本地见解

照片由普里西拉·杜·普里兹在 Unsplash 拍摄
将洞察力转化为行动
恭喜你!你在工作中牵头的机器学习项目已经完成。你花了几个月的时间与利益相关者讨论业务问题,将业务问题转化为数据问题,获取和探索数据,当你看到数据一团糟时清理数据,选择合适的指标,并构建和调整机器学习模型,为你带来出色的结果。你完了!
除了…你不是为一个科技巨头工作,你的同事不是程序员,你是唯一一个知道如何从你建立的模型中获得预测的人。你可能不想在可预见的未来导出和发送 CSV 文件,但是你绝对不能在面向公众的云服务上建立你的模型和相关的个人身份信息。同样不言而喻的是,您不被信任管理凭证,您不被允许在您的组织的单点登录门户后保护您自己的 web 服务器,并且您没有预算来购买企业解决方案。
您开始这个项目的目标是帮助您的团队成员更高效、更有效、更经济地完成他们的工作,但是他们需要实际使用您构建的东西来实现这些目标。这篇文章将介绍如何将一款 Dash 应用发给你的同事,而不需要管理员证书,以及如何消除摩擦,以便他们可以轻松使用它。
虚拟环境
我使用诗歌为我的项目创建虚拟环境和管理依赖关系。它在 Windows 上运行良好,文档也很棒。在其他计算机上安装您的依赖项就像共享您的pyproject.toml文件一样简单。
本指南的其余部分假设你也使用诗歌。
为什么是 Dash?
Dash 与 Plotly 相结合,可以轻松创建具有交互式可视化功能的 web 应用程序,以探索和导出机器学习模型的结果。

例如,我构建了一个 web 应用程序,允许最终用户控制模型的大量输入并导出结果。用户可以更改:要建模的会计年度、二元分类模型的决策阈值以及最小和最大捐赠/销售阈值。该应用程序还显示人们在散点图上的位置,并允许最终用户根据地理位置选择要导出的人。每当控制盒中的任何东西发生变化,应用程序中的每个数字都会立即更新。
最终产品使非技术人员可以轻松地从机器学习模型中获得结果,并在自己的工作流程中使用这些结果。
如何构建 Dash 应用程序的细节超出了本文的范围,但我会在以后的文章中解释我是如何做的。
前期投资
不幸的是,指导您的同事安装 Python 并确保正确设置路径变量的初始时间投资是无法回避的。但是你只需要做这一步一次,我保证这是值得的。
编写一个批处理脚本来启动应用程序
向非技术用户部署 web 应用的一个重要方面是减少产品发布过程中的摩擦。终端用户不想记住启动应用程序所需的命令,坦率地说,他们也不应该记住。令人欣慰的是,通过编写一个带有三行代码的批处理脚本(一个带有后缀.bat的文件),可以自动启动 Dash 应用程序。将这些命令复制到新的记事本文件中:
@echo off
start [http://127.0.0.1:8050/](http://127.0.0.1:8050/)
poetry run python path\to\app_script.py
将path\to\app_script.py替换为从项目根目录到启动 Dash 应用程序的脚本的路径。将该文件保存在项目的根目录下,并将其命名为类似于dashboard.bat的名称。
该脚本首先在默认 web 浏览器的新选项卡中打开默认 Dash 应用程序 URL,然后运行包含 Dash 应用程序的 Python 脚本。这意味着 web 浏览器会说网站不可用,直到支持 Dash 的 Flask 服务器启动并运行。一旦服务器启动(这可能需要 5-10 秒),用户应该刷新浏览器来加载应用程序。
双击刚刚创建的批处理脚本,确保它能够工作。该文件将是您的团队进入应用程序的入口点。
与同事共享文件
这一步有一些灵活性,取决于有多少人在开发应用程序,有多少人在使用应用程序,以及你计划多久更新一次。如果您不是唯一的开发人员,正在与一个大型团队共享,或者需要频繁更新,您可能更喜欢自动化程度更高的方法。
然而,我是唯一的开发人员,我与五个人共享我的 web 应用程序,每年可能不会有超过几次更新。我决定将项目(包括 Python 文件、保存的 XGBoost 模型和用于模型的数据文件)复制到 Google Drive 文件夹,尽管任何文件共享服务都可以类似地工作。
该文件夹的内容可能如下所示:
.
├── dashboard.bat
├── glamtk
│ ├── dashboard
│ │ ├── assets
│ │ │ ├── logo.png
│ │ │ └── styles.css
│ │ ├── __init__.py
│ │ ├── app.py
│ │ ├── glossary.py
│ │ ├── index.py
│ │ ├── layout.py
│ │ ├── load_models.py
│ │ └── navbar.py
│ ├── data
│ │ ├── models
│ │ │ ├── churn_xgboost_2014
│ │ │ ├── churn_xgboost_2015
│ │ │ ├── churn_xgboost_2016
│ │ │ ├── churn_xgboost_2017
│ │ │ ├── churn_xgboost_2018
│ │ │ └── churn_xgboost_2019
│ │ ├── processed
│ │ │ ├── features.csv
│ │ │ └── geolocation.csv
│ │ └── raw
│ │ ├── ...
├── pyproject.toml
与所有相关人员共享该文件夹,并要求他们下载其中的内容。最好添加一个说明,告诉他们您将很快完成安装😁
安装 Python
在 Windows 电脑上安装 Python 和创建虚拟环境曾经是一项耐心(和故障排除)的练习,但自从微软将 Python 添加到微软商店以来,这个过程变得容易多了。
- 通过打开开始菜单(按键盘上的 Windows 键)并键入“store”来打开 Microsoft store。
- 在右上角的搜索框中键入“python ”,然后单击 Python 3.8。
- 单击安装。安装时商店会提示你登录,但你不需要。关闭提示继续。
Python 现在安装好了!
装诗
一旦您的同事安装了诗歌,他们就可以使用您的pyproject.toml文件下载您的项目所需的所有依赖项。
- 打开开始菜单,输入“powershell ”,然后按回车键,打开 Powershell。
- 根据诗歌的网站,复制这个命令,粘贴到 Powershell 中,然后按 enter:
(Invoke-WebRequest -Uri https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py -UseBasicParsing).Content | python - 安装完成后,关闭 Powershell。打开一个新的命令提示符(开始菜单->键入“cmd”并按 enter)并输入命令
poetry --version。如果得到类似Poetry version 1.0.0的结果,那么继续第 7 步。但是,如果命令返回错误,请继续下一步。 - 打开开始菜单,输入“环境”。这里有两个非常相似的选项:“编辑系统环境变量”和“编辑您的帐户的环境变量”。由于我们没有管理员凭据,请务必为您的帐户选择编辑环境变量。(见下图。)
- 双击用户变量部分中的“路径”,单击新建,并将其粘贴到文本框:
%USERPROFILE%\.poetry\bin - 这很重要:在“编辑环境变量”窗口和“环境变量”窗口中点击确定。如果您没有在两个窗口中都单击 OK,新的 path 变量将不会被保存。
- 通过在命令提示符窗口中输入以下命令来更改 poems 的默认缓存目录:
poetry config cache-dir "%USERPROFILE%\pypoetry\Cache"。 - 关闭命令提示符窗口。
诗词现装!

确保选择正确的环境变量选项!
安装应用程序
由于您的同事已经下载了您共享的文件,现在是时候安装您的应用程序的依赖项了。
- 打开一个新的命令提示窗口,通过键入
mkdir <project>并按 enter 键为应用程序创建一个文件夹,用您的项目名称替换<项目>。因为我的项目叫做 GLAMtk,所以我让我的团队类型为mkdir glamtk。这个新文件夹将位于每个人的用户文件夹中,用户文件夹位于C:\Users\<username>。 - 解压缩从 Google drive(或其他服务)下载的存档文件夹,并将内容复制到刚刚创建的文件夹中。使用上面的示例文件树,用户可以复制
dashboard.bat、glamtk文件夹和pyproject.toml。 - 在命令提示符窗口中,通过键入
cd <project>并按 enter 键打开您在步骤 1 中创建的文件夹。 - 通过键入
poetry install并按 enter 键安装所需的依赖项。这将需要一段时间,取决于您的项目有多少依赖项。
您的应用程序现在可以使用了!让每个人通过双击dashboard.bat来检查它是否工作。
未来更新
这种方法允许您轻松地向团队发送更新。只要不引入新的依赖项或更改启动 Dash 应用程序的 Python 脚本,更新应用程序就像用新版本替换项目文件夹一样简单。批处理脚本仍将工作,并且依赖项已经安装。
如果您确实更改了 Dash 应用程序的入口点或向您的应用程序添加了依赖项,请遵循上面针对诗歌和/或批处理脚本的相应步骤。
包扎
这篇文章介绍了如何以 Dash 应用程序的形式向 Windows 计算机上的最终用户提供机器学习模型,而无需管理员凭据。
这需要相当大的前期投资,尤其是如果你带领许多人通过 Zoom 的这些步骤,但要考虑到这是对你未来计划和团队效率的投资。最终用户将能够使用你花了很长时间创建的机器学习模型,而你不需要亲自处理每个请求。
欢迎在下面留下评论——我很乐意听到你使用过的替代部署方法,或者对这篇文章中的任何其他内容的想法。感谢阅读!
在 AWS Fargate 上部署机器学习管道

在 AWS Fargate 上封装和部署 ML pipeline serverless 的循序渐进的初学者指南
概述
在我们关于在云中部署机器学习管道的上一篇文章中,我们展示了如何用 PyCaret 开发机器学习管道,用 Docker 将其容器化,并使用 Google Kubernetes 引擎将其作为 web 应用程序。如果你以前没有听说过 PyCaret,请阅读这个公告以了解更多信息。
在本教程中,我们将使用我们之前构建和部署的相同的机器学习管道和 Flask 应用程序。这次我们将演示如何使用 AWS Fargate 无服务器地封装和部署机器学习管道。
👉本教程的学习目标
- 什么是容器?Docker 是什么?什么是 Kubernetes?
- 什么是亚马逊弹性容器服务(ECS)?
- 什么是 AWS Fargate 和无服务器部署?
- 构建一个 Docker 映像并将其推送到 Amazon 弹性容器注册中心。
- 使用 AWS 管理的基础设施(如 AWS Fargate)创建和执行任务定义。
- 看看一个使用训练有素的机器学习管道来实时预测新数据点的 web 应用程序。
本教程将涵盖整个工作流程,从在本地构建 docker 映像开始,将其上传到 Amazon Elastic Container Registry,创建一个集群,然后使用 AWS 管理的基础设施(即 AWS Fargate)定义和执行任务。
过去,我们已经讨论过在其他云平台上的部署,比如 Azure 和 Google。如果你有兴趣了解更多,你可以阅读下面的故事:
💻本教程的工具箱
PyCaret
PyCaret 是 Python 中的开源、低代码机器学习库,用于训练和部署机器学习管道和模型到生产中。PyCaret 可以使用 pip 轻松安装。
pip install pycaret
瓶
Flask 是一个允许你构建网络应用的框架。web 应用程序可以是商业网站、博客、电子商务系统,也可以是使用训练好的模型从实时提供的数据中生成预测的应用程序。如果你没有安装 Flask,你可以使用 pip 来安装。
Windows 10 家庭版 Docker 工具箱
Docker 容器用于打包应用程序及其所有必需的组件,如库和其他依赖项,并作为一个包发送出去。如果你之前没用过 docker,本教程还涵盖了在 Windows 10 Home 上安装 Docker 工具箱(legacy)。在之前的教程中,我们介绍了如何在 Windows 10 Pro edition 上安装 Docker Desktop。
亚马逊网络服务(AWS)
亚马逊网络服务(AWS)是由亚马逊提供的一个全面且广泛采用的云平台。它拥有来自全球数据中心的超过 175 项全功能服务。如果你以前没用过 AWS,你可以注册免费账号。
✔️Let's 开始吧…..
什么是容器?
在我们开始使用 AWS Fargate 实现之前,让我们了解一下什么是容器,为什么我们需要容器?

https://www.freepik.com/free-photos-vectors/cargo-ship
您是否遇到过这样的问题:您的代码在您的计算机上运行得很好,但是当一个朋友试图运行完全相同的代码时,却无法运行?如果你的朋友重复完全相同的步骤,他或她应该得到相同的结果,对不对?一个词的答案是 环境。你朋友的环境和你不一样。
环境包括什么?Python 等编程语言以及所有库和依赖项,以及构建和测试应用程序时使用的确切版本。
如果我们可以创建一个可以转移到其他机器上的环境(例如:你朋友的电脑或者谷歌云平台这样的云服务提供商),我们就可以在任何地方重现结果。因此,容器 是一种将应用程序及其所有依赖项打包的软件,因此应用程序可以从一个计算环境可靠地运行到另一个计算环境。
Docker 是什么?
Docker 是一家提供软件(也叫 Docker )的公司,允许用户构建、运行和管理容器。虽然 Docker 的集装箱是最常见的,但还有其他不太出名的替代品,如 LXD 的和 LXC 的。

现在,您已经从理论上了解了什么是容器,以及 Docker 如何用于容器化应用程序,让我们想象一个场景,其中您必须在一组机器上运行多个容器,以支持一个企业级机器学习应用程序,该应用程序在白天和晚上都有不同的工作负载。这在现实生活中很常见,尽管听起来很简单,但手动完成的工作量很大。
您需要在正确的时间启动正确的容器,弄清楚它们如何相互通信,处理存储考虑事项,处理失败的容器或硬件以及数以百万计的其他事情!
管理成百上千个容器以保持应用程序正常运行的整个过程被称为容器编排。先不要纠结于技术细节。
在这一点上,您必须认识到管理现实生活中的应用程序需要不止一个容器,并且管理所有的基础设施以保持容器正常运行是繁琐的、手动的和管理负担。
这就把我们带到了 T21。
什么是 Kubernetes?
Kubernetes 是谷歌在 2014 年开发的一个开源系统,用于管理容器化的应用程序。简而言之,Kubernetes 是一个跨机器集群运行和协调容器化应用的系统。

虽然 Kubernetes 是谷歌开发的开源系统,但几乎所有主要的云服务提供商都将 Kubernetes 作为托管服务提供。比如:亚马逊提供的亚马逊弹性 Kubernetes 服务(EKS) ,谷歌提供的谷歌 Kubernetes 引擎,微软提供的 Azure Kubernetes 服务(AKS) 。
到目前为止,我们已经讨论并理解了:
✔️一 集装箱
✔️码头工人
✔️·库伯内特
在介绍 AWS Fargate 之前,只剩下一件事要讨论,那就是亚马逊自己的容器编排服务亚马逊弹性容器服务(ECS)。****
AWS 弹性集装箱服务
亚马逊弹性容器服务(Amazon ECS)是亚马逊自己开发的容器编排平台。ECS 背后的思想类似于 Kubernetes (两者都是编排服务)。
ECS 是 AWS 本地服务,这意味着它只能在 AWS 基础设施上使用。另一方面, EKS 基于 Kubernetes,这是一个开源项目,用户可以在多云(AWS、GCP、Azure)甚至本地运行。
亚马逊还提供基于 Kubernetes 的容器编排服务,称为亚马逊弹性 Kubernetes 服务(亚马逊 EKS)。尽管 ECS 和 EKS 的目的非常相似,即编排容器化的应用程序,但在定价、兼容性和安全性方面还是有相当大的差异。没有最佳答案,解决方案的选择取决于使用案例。
无论您使用哪种容器编排服务(ECS 或 EKS ),都有两种方法可以实现底层基础架构:
- 手动管理集群和底层基础设施,如虚拟机/服务器/(在 AWS 中也称为 EC2 实例)。
- 无服务器—完全不需要管理任何东西。只需上传容器就可以了。← 这是 AWS Fargate。

亚马逊 ECS 底层基础设施
AWS Fargate —集装箱的无服务器计算
AWS Fargate 是一个用于容器的无服务器计算引擎,它与亚马逊弹性容器服务(ECS)和亚马逊弹性库本内特服务(EKS)一起工作。Fargate 使您可以轻松地专注于构建应用程序。Fargate 消除了供应和管理服务器的需要,允许您为每个应用程序指定和支付资源,并通过设计应用程序隔离来提高安全性。
Fargate 分配适当的计算量,消除了选择实例和扩展集群容量的需要。您只需为运行容器所需的资源付费,因此不存在过度配置和为额外的服务器付费的问题。

AWS Fargate 如何工作—https://aws.amazon.com/fargate/
对于哪种方法更好,没有最佳答案。选择无服务器还是手动管理 EC2 集群取决于使用案例。有助于这一选择的一些要点包括:
ECS EC2(人工进近)
- 你全押在 AWS 上。
- 您有专门的运营团队来管理 AWS 资源。
- 您在 AWS 上已经有了足迹,即您已经在管理 EC2 实例
AWS 法盖特
- 您没有庞大的运营团队来管理 AWS 资源。
- 你不想要操作责任或想要减少它。
- 您的应用程序是无状态的(无状态应用程序不保存在一个会话中生成的客户端数据,以便在下一个与该客户端的会话中使用)。
设置业务环境
一家保险公司希望通过使用住院时的人口统计和基本患者健康风险指标来更好地预测患者费用,从而改善其现金流预测。

( 数据源 )
目标
构建和部署一个 web 应用程序,将患者的人口统计和健康信息输入到基于 web 的表单中,然后输出预测的收费金额。
任务
- 为部署培训和开发机器学习管道。
- 使用 Flask 框架构建 web 应用程序。它将使用经过训练的 ML 管道实时生成对新数据点的预测。
- 构建一个 Docker 映像并将其推送到 Amazon 弹性容器注册中心。
- 创建并执行任务,使用 AWS Fargate 无服务器基础架构部署应用程序。
由于我们已经在最初的教程中介绍了前两个任务,我们将快速回顾它们,然后集中讨论上面列表中的其余项目。如果您有兴趣了解更多关于使用 PyCaret 在 Python 中开发机器学习管道以及使用 Flask 框架构建 web 应用程序的信息,请阅读本教程。
👉开发机器学习管道
我们正在使用 Python 中的 PyCaret 进行训练,并开发一个机器学习管道,它将作为我们 web 应用程序的一部分。机器学习管道可以在集成开发环境(IDE)或笔记本中开发。我们使用笔记本运行了以下代码:
当您在 PyCaret 中保存一个模型时,基于在 setup() 函数中定义的配置的整个转换管道被创建。所有的相互依赖都是自动编排的。查看存储在“deployment_28042020”变量中的管道和模型:

使用 PyCaret 创建的机器学习管道
👉构建 Web 应用程序
本教程的重点不是构建 Flask 应用程序。这里讨论它只是为了完整性。现在我们的机器学习管道已经准备好了,我们需要一个 web 应用程序,它可以连接到我们训练过的管道,以实时生成对新数据点的预测。我们已经使用 Python 中的 Flask 框架创建了 web 应用程序。该应用程序有两个部分:
- 前端(使用 HTML 设计)
- 后端(使用 Flask 开发)
这是我们的 web 应用程序的外观:

本地计算机上的 Web 应用程序
如果到目前为止你还没有跟上,没问题。您可以简单地从 GitHub 派生这个存储库。此时,您的项目文件夹应该是这样的:
使用 AWS Fargate 部署 ML 管道的 10 个步骤:
👉步骤 1 —安装 Docker 工具箱(适用于 Windows 10 家庭版)
为了在本地构建 docker 映像,您需要在您的计算机上安装 Docker。如果你使用的是 64 位 Windows 10:Pro、Enterprise 或 Education (Build 15063 或更高版本),你可以从 DockerHub 下载 Docker Desktop。
然而,如果你使用的是 Windows 10 Home,你需要从 Dockers GitHub 页面安装旧版 Docker 工具箱的最新版本(v19.03.1)。

https://github.com/docker/toolbox/releases
下载并运行DockerToolbox-19.03.1.exe文件。
检查安装是否成功的最简单方法是打开命令提示符并键入“docker”。它应该打印帮助菜单。

Anaconda 提示检查 docker
👉步骤 2—创建 Dockerfile 文件
创建 Docker 映像的第一步是在项目目录中创建 Docker 文件。Dockerfile 只是一个包含一组指令的文件。该项目的 docker 文件如下所示:
Dockerfile 区分大小写,必须与其他项目文件位于项目文件夹中。Dockerfile 没有扩展名,可以使用任何文本编辑器创建。您可以从这个 GitHub 资源库下载这个项目中使用的 Dockerfile。
👉步骤 3—在弹性容器注册中心(ECR)中创建一个存储库
(a)登录您的 AWS 控制台并搜索弹性容器注册表:

AWS 控制台
(b)创建一个新的存储库:

在 Amazon 弹性容器注册表上创建新的存储库
对于这个演示,我们已经创建了“py caret-deployment-AWS-repository”。
(c)点击【查看推送命令】:

py caret-部署-AWS-存储库
(d)复制推送命令:

py caret-deployment-AWS-repository 的推送命令
👉步骤 4—执行推送命令
使用 Anaconda 提示符导航到您的项目文件夹,并执行您在上一步中复制的命令。下面的代码仅用于演示,可能无法正常工作。要获得正确的代码来执行,您必须从存储库中的“查看推送命令”中获得代码的副本。
在执行这些命令之前,您必须位于 docker 文件和其余代码所在的文件夹中。
****Command 1**
aws ecr get-login-password --region ca-central-1 | docker login --username AWS --password-stdin 212714531992.dkr.ecr.ca-central-1.amazonaws.com**Command 2**
docker build -t pycaret-deployment-aws-repository .**Command 3**
docker tag pycaret-deployment-aws-repository:latest 212714531992.dkr.ecr.ca-central-1.amazonaws.com/pycaret-deployment-aws-repository:latest**Command 4**
docker push 212714531992.dkr.ecr.ca-central-1.amazonaws.com/pycaret-deployment-aws-repository:latest**
👉第 5 步—检查您上传的图像
单击您创建的存储库,您将看到上一步中上传的图像的图像 URI。复制图像 URI(这将需要在下面的第 7 步)。

👉步骤 6 —创建和配置集群
(a)点击左侧菜单上的“集群”:

创建集群—步骤 1
(b)选择“仅联网”并点击下一步:

选择仅网络模板
(c)配置集群(输入集群名称)并点击创建:

配置集群
(d)集群创建:

集群已创建
👉步骤 7-创建新的任务定义
在 Amazon ECS 中运行 Docker 容器需要一个任务定义。您可以在任务定义中指定的一些参数包括:Docker 图像,用于您的任务中的每个容器。每个任务或者一个任务中的每个容器使用多少 CPU 和内存。
(a)点击“创建新的任务定义”:

创建新的任务定义
(b)选择“FARGATE”作为发射类型:

选择启动类型兼容性
(c)详细填写:

配置任务和容器定义(第 1 部分)

配置任务和容器定义(第 2 部分)
(d)点击“添加容器”并填写详细信息:

在任务定义中添加容器
(e)点击右下角的“创建任务”。

👉步骤 8-执行任务定义
在步骤 7 中,我们创建了一个启动容器的任务。现在我们将通过点击动作下的“运行任务”来执行任务。

执行任务定义
(a)点击“切换到发射类型”将类型更改为 Fargate:

运行任务—第 1 部分
(b)从下拉列表中选择 VPC 和子网:

运行任务—第 2 部分
(c)点击右下角的“运行任务”:

任务创建成功
👉步骤 9-从网络设置中允许入站端口 5000
在我们看到我们的应用程序在公共 IP 地址上运行之前,最后一步是通过创建一个新规则来允许端口 5000。为此,请遵循以下步骤:
(a)点击任务

(b)点击 ENI Id:

(c)点击安全组

(d)点击【编辑入站规则】

(e)添加端口 5000 的自定义 TCP 规则

👉步骤 10——查看应用程序的运行情况
使用端口 5000 的公共 IP 地址访问应用程序。

任务定义日志

最终应用上传到 http://35.182.227.98:5000
****注意:在这篇文章发表时,该应用程序将从公共地址中删除,以限制资源消耗。
PyCaret 2.0.0 来了!
我们收到了来自社区的大力支持和反馈。我们正在积极改进 PyCaret,并准备我们的下一个版本。 PyCaret 2.0.0 会更大更好。如果您想分享您的反馈并帮助我们进一步改进,您可以在网站上填写此表格或者在我们的 GitHub 或 LinkedIn 页面上发表评论。
关注我们的 LinkedIn 并订阅我们的 YouTube 频道,了解更多关于 PyCaret 的信息。
想了解某个特定模块?
从第一个版本 1.0.0 开始,PyCaret 有以下模块可供使用。点击下面的链接,查看 Python 中的文档和工作示例。
另请参见:
笔记本中的 PyCaret 入门教程:
你愿意投稿吗?
PyCaret 是一个开源项目。欢迎每个人都来投稿。如果您愿意投稿,请随意处理未决问题。dev-1.0.1 分支上的单元测试接受拉请求。
如果你喜欢 PyCaret,请给我们 GitHub 回购的⭐️。
**中:【https://medium.com/@moez_62905/ **
领英:https://www.linkedin.com/in/profile-moez/
推特:https://twitter.com/moezpycaretorg1
使用 Docker 容器在云上部署机器学习管道

重述
在我们的上一篇文章中,我们展示了如何使用 Python 中的 PyCaret 和 Flask 框架开发机器学习管道并将其部署为 web 应用。如果你以前没有听说过 PyCaret,请阅读这个公告以了解更多信息。
在本教程中,我们将使用我们之前构建和部署的相同的机器学习管道和 Flask 应用程序。这次我们将演示如何使用微软 Azure web App 服务将机器学习管道部署为 Web 应用。
为了在微软 Azure 上部署机器学习管道,我们必须将我们的管道封装在一个名为“Docker”的软件中。如果你不知道容器化是什么意思,没问题——本教程就是关于这个的。
👉本教程的学习目标
- 什么是容器?Docker 是什么?我们为什么需要它?
- 在本地计算机上构建一个 Docker 文件,并将其发布到Azure Container Registry(ACR)。
- 使用我们上传到 ACR 的容器在 Azure 上部署一个 web 服务。
- 看看一个使用训练有素的机器学习管道实时预测新数据点的 web 应用程序。
在我们的上一篇文章中,我们讨论了模型部署的基础以及为什么需要它。如果您想了解更多关于模型部署的信息,请点击这里阅读我们的上一篇文章。
本教程将涵盖从本地构建容器到将其推送到 Azure Container Registry,然后将我们预先训练好的机器学习管道和 Flask 应用部署到 Azure Web 服务的整个工作流程。

工作流程:创建映像→在本地构建容器→推送至 ACR →在云上部署应用
💻本教程的工具箱
PyCaret
PyCaret 是 Python 中的开源、低代码机器学习库,用于训练和部署机器学习管道和模型到生产中。PyCaret 可以使用 pip 轻松安装。
pip install **pycaret**
瓶
Flask 是一个允许你构建网络应用的框架。web 应用程序可以是商业网站、博客、电子商务系统,也可以是使用训练好的模型从实时提供的数据中生成预测的应用程序。如果你没有安装 Flask,你可以使用 pip 来安装。
码头工人
Docker 是一款工具,旨在通过使用容器来简化应用程序的创建、部署和运行。容器用于打包应用程序及其所有必需的组件,如库和其他依赖项,并作为一个包发送出去。如果你之前没有用过 docker,本教程也涵盖了在 Windows 10 上安装 docker 的内容。
微软 Azure
微软 Azure 是一套云服务,用于在一个庞大的全球网络上构建、管理和部署应用。其他经常用于部署 ML 管道的云服务有亚马逊 Web 服务(AWS) 、谷歌云、 IBM 云和阿里云。我们将在未来的教程中介绍其中的大部分。
如果你以前没有使用过微软 Azure,你可以在这里注册一个免费账户。当你第一次注册时,你可以获得前 30 天的免费积分。通过遵循本教程,您可以在构建自己的 web 应用程序时利用这些信用。
什么是容器,我们为什么需要它?
您是否遇到过这样的问题:您的 python 代码(或任何其他代码)在您的计算机上运行良好,但当您的朋友试图运行完全相同的代码时,却无法运行?如果你的朋友重复完全相同的步骤,他们应该得到相同的结果,对不对?一个词的答案是 环境。你朋友的 Python 环境和你的不一样。
环境包括什么?→ Python ( 或您使用过的任何其他语言)以及构建和测试应用程序时使用的所有库和依赖项的确切版本。
如果我们能够以某种方式创建一个可以转移到其他机器上的环境(例如:你朋友的电脑或者像微软 Azure 这样的云服务提供商),我们就可以在任何地方重现结果。因此,****容器是一种打包应用程序及其所有依赖项的软件,这样应用程序就可以从一个计算环境可靠地运行到另一个计算环境。
"想想容器,当你想到容器的时候"

https://www.freepik.com/free-photos-vectors/cargo-ship
这是数据科学中理解容器最直观的方式。它们就像船上的集装箱一样,目标是将一个集装箱的内容与其他集装箱隔离开来,这样它们就不会混淆。这正是容器在数据科学中的用途。
现在我们已经理解了容器背后的隐喻,让我们看看为我们的应用程序创建一个隔离环境的替代选项。一个简单的替代方法是为每个应用程序准备一台单独的机器。
(1 台机器= 1 个应用=无冲突=一切都好)
使用一台单独的机器很简单,但是它并没有超过使用容器的好处,因为为每个应用程序维护多台机器是很昂贵的,这是一个难以维护和难以扩展的噩梦。简而言之,在现实生活的很多场景中并不实用。
创建隔离环境的另一种方法是虚拟机。容器在这里也更受欢迎,因为它们需要更少的资源,非常便携,而且运行速度更快。****

虚拟机与容器
你能看出虚拟机和容器之间的区别吗?使用容器时,不需要客户操作系统。想象一下在一台虚拟机上运行 10 个应用程序。这将需要 10 个客户操作系统,而使用容器时则不需要。
我理解容器,但是 Docker 是什么?
Docker 是一家提供允许用户构建、运行和管理容器的软件(也称为 Docker)的公司。虽然 Docker 的集装箱是最常见的,但也有其他不太出名的选择,如提供集装箱解决方案的 LXD 和 T21。
在本教程中,我们将使用 Docker Desktop for Windows 来创建一个我们将在 Azure Container Registry 上发布的容器。然后我们将使用该容器部署一个 web 应用程序。

Docker 图像与 Docker 容器
docker 图片和 docker 容器有什么区别?这是到目前为止最常被问到的问题,所以让我们马上澄清这个问题。有许多可用的技术定义,但是,直观地认为 docker 图像是一个基于哪个容器被创建的模具。图像本质上是容器的快照。
如果你喜欢稍微技术性一点的定义,那么考虑一下这个:当 Docker 图像在 Docker 引擎上运行时,它们在运行时成为容器。
打破炒作:
说到底,docker 只是一个包含几行指令的文件,保存在您的项目文件夹下,文件名为【docker file】。
另一种思考 docker 文件的方式是,它们就像你在自己的厨房里发明的食谱。当你和其他人分享这些食谱,他们按照完全相同的指示,他们就能做出同样的菜。类似地,您可以与他人共享您的 docker 文件,然后他人可以基于该 docker 文件创建图像并运行容器。
既然您已经理解了容器、docker 以及我们为什么应该使用它们,那么让我们快速设置一下业务上下文。
设置业务环境
一家保险公司希望通过使用住院时的人口统计和基本患者健康风险指标来更好地预测患者费用,从而改善其现金流预测。

( 数据源 )
目标
构建和部署一个 web 应用程序,将患者的人口统计和健康信息输入到基于 web 的表单中,然后输出预测的收费金额。
任务
- 为部署培训和开发机器学习管道。
- 使用 Flask framework 构建 web 应用程序。它将使用经过训练的 ML 管道实时生成对新数据点的预测。
- 创建一个 docker 图像和容器。
- 将容器发布到 Azure 容器注册表(ACR)上。
- 通过发布到 ACR,在容器中部署 web 应用程序。一旦部署,它将成为公开可用的,可以通过一个网址访问。
由于我们已经在上一个教程中介绍了前两个任务,我们将快速回顾它们,并将重点放在上面列表中的剩余任务上。如果你有兴趣了解更多关于使用 PyCaret 在 Python 中开发机器学习管道和使用 Flask framework 构建 web app 的信息,可以阅读我们的上一篇教程。
👉开发机器学习管道
我们正在使用 Python 中的 PyCaret 进行训练,并开发一个机器学习管道,它将作为我们 web 应用程序的一部分。机器学习管道可以在集成开发环境(IDE)或笔记本中开发。我们使用笔记本运行了以下代码:
https://gist . github . com/py caret/ab 3838d 63 C2 6482 a 43 CEE cef 38 a 718 f
当您在 PyCaret 中保存一个模型时,基于在 setup() 函数中定义的配置的整个转换管道被创建。所有的相互依赖都是自动编排的。查看存储在“deployment_28042020”变量中的管道和模型:

使用 PyCaret 创建的机器学习管道
👉构建 Web 应用程序
本教程的重点不是构建 Flask 应用程序。这里讨论它只是为了完整性。现在我们的机器学习管道已经准备好了,我们需要一个 web 应用程序,它可以连接到我们训练过的管道,以实时生成对新数据点的预测。我们已经使用 Python 中的 Flask 框架创建了 web 应用程序。该应用程序有两个部分:
- 前端(使用 HTML 设计)
- 后端(使用 Flask 开发)
这是我们的 web 应用程序的外观:

本地计算机上打开的 Web 应用程序
如果你想看看这个 web 应用的运行情况,点击这里在 Heroku 上打开一个已部署的 web 应用(打开可能需要几分钟)。
如果你没有跟上,没问题。您可以简单地从 GitHub 派生这个库。如果你不知道怎么叉一个回购,请看这个官方 GitHub 教程。此时,您的项目文件夹应该是这样的:

https://github.com/pycaret/deployment-heroku
现在我们已经有了一个功能齐全的 web 应用程序,我们可以开始使用 Docker 将应用程序容器化的过程。
在 docker 容器中部署 ML 管道的 10 个步骤:
👉步骤 1 —安装 Docker 桌面 Windows 版****
你可以在 Mac 上使用 Docker 桌面,也可以在 Windows 上使用。根据你的操作系统,你可以从这个链接下载 Docker 桌面。在本教程中,我们将使用 Docker 桌面。

https://hub . docker . com/editions/community/docker-ce-desktop-windows/
检查安装是否成功的最简单方法是打开命令提示符并键入“docker”。它应该打印帮助菜单。

命令提示符
👉第二步——安装 Kitematic****
Kitematic 是一个直观的图形用户界面(GUI ),用于在 Windows 或 Mac 上运行 Docker 容器。你可以从 Docker 的 GitHub 库下载 Kitematic。

https://github.com/docker/kitematic/releases
下载完成后,只需将文件解压缩到所需的位置。
👉步骤 3 —创建 Dockerfile 文件
创建 Docker 映像的第一步是创建 Docker 文件。Dockerfile 只是一个包含一组指令的文件。该项目的 docker 文件如下所示:
https://gist . github . com/py caret/1ba 72057 c 21 df 43 ad 78 fa 5086d 06143 f
Dockerfile 区分大小写,必须与其他项目文件位于项目文件夹中。Dockerfile 没有扩展名,可以使用任何编辑器创建。我们使用了 Visual Studio 代码来创建它。
👉步骤 4-创建 Azure 容器注册中心
如果你没有微软 Azure 账号或者之前没用过,可以免费注册。当你第一次注册时,你可以获得前 30 天的免费积分。你可以利用这个积分在 Azure 上构建和部署一个 web 应用。注册后,请遵循以下步骤:
- 登录https://portal.azure.com。
- 点击创建资源。
- 搜索容器注册表,然后单击创建。
- 选择订阅、资源组和注册表名称(在我们的例子中: pycaret.azurecr.io 是我们的注册表名称)

https://portal.azure.com→登录→创建资源→容器注册
👉步骤 5—构建 Docker 映像
一旦在 Azure portal 中创建了注册表,第一步就是使用命令行构建 docker 映像。导航到项目文件夹并执行以下代码。
docker build -t pycaret.azurecr.io/pycaret-insurance:latest .

使用 anaconda 提示符构建 docker 映像
- pycaret.azurecr.io 是您在 Azure portal 上创建资源时获得的注册表名称。
- pycaret-insurance 是图像的名称, latest 是标签。这可以是你想要的任何东西。
👉步骤 6—从 docker 映像运行容器
既然已经创建了映像,我们将在本地运行一个容器并测试应用程序,然后将它推送到 Azure Container Registry。要在本地运行容器,请执行以下代码:
docker run -d -p 5000:5000 pycaret.azurecr.io/pycaret-insurance
一旦该命令成功执行,它将返回所创建容器的 ID。

本地运行 docker 容器
👉步骤 7 —在本地机器上测试容器
打开 Kitematic,您应该能够看到一个应用程序启动并运行。

kite matic——用于在 Mac 和 Windows 操作系统上管理容器的 GUI
你可以在你的网络浏览器中访问 localhost:5000 来查看这个应用程序。它应该会打开一个网络应用程序。

在本地容器(本地主机:5000)上运行的应用程序
确保一旦你这样做了,你停止使用 Kitematic 的应用程序,否则,它将继续利用你的电脑资源。
👉步骤 8-验证 Azure 凭据
将容器上传到 ACR 之前的最后一步是在本地机器上验证 azure 凭证。为此,请在命令行中执行以下代码:
docker login pycaret.azurecr.io
系统将提示您输入用户名和密码。用户名是您的注册表的名称(在这个例子中用户名是“pycaret”)。您可以在您创建的 Azure 容器注册表资源的访问键下找到您的密码。

portal.azure.com→Azure 容器注册表→访问密钥
👉步骤 9—将容器推送到 Azure 容器注册中心
现在您已经向 ACR 进行了身份验证,您可以通过执行以下代码将您创建的容器推送到 ACR:
docker push pycaret.azurecr.io/pycaret-insurance:latest
根据容器的大小,push 命令可能需要一些时间来将容器传输到云。
👉步骤 10——创建一个 Azure Web 应用程序,并查看您的模型的运行情况
要在 Azure 上创建 web 应用程序,请按照以下步骤操作:
- 在https://portal.azure.com上登录。
- 点击创建资源。
- 搜索 Web 应用程序,然后单击创建。
- 将您推入的 ACR 图像(上面的步骤 9)链接到您的应用程序。

portal.azure.com→Web 应用程序→创建→基础

portal.azure.com→Web App→创建→ Docker
轰!!这款应用现在已经在 Azure Web Services 上运行了。

https://pycaret-insurance2.azurewebsites.net
****注意:在这篇文章发表时,https://pycaret-insurance2.azurewebsites.net的应用将被移除,以限制资源消耗。
链接到 GitHub 仓库进行 Heroku 部署。 (不带 docker)
下一个教程
在下一个部署机器学习管道的教程中,我们将更深入地使用谷歌云和微软 Azure 上的 Kubernetes 服务来部署机器学习管道。
关注我们的 LinkedIn 并订阅我们的 Youtube 频道,了解更多关于 PyCaret 的信息。
重要链接
用户指南/文档
GitHub 资源库 安装 PyCaret
笔记本教程
贡献于 PyCaret
PyCaret 1.0.1 来了!
我们收到了来自社区的大力支持和反馈。我们正在积极改进 PyCaret,并准备我们的下一个版本。 PyCaret 1.0.1 会更大更好。如果您想分享您的反馈并帮助我们进一步改进,您可以在网站上填写此表格,或者在我们的 GitHub 或 LinkedIn 页面上发表评论。
想了解某个特定模块?
从第一个版本 1.0.0 开始,PyCaret 有以下模块可供使用。点击下面的链接,查看 Python 中的文档和工作示例。
另请参见:
笔记本中的 PyCaret 入门教程:
你愿意投稿吗?
PyCaret 是一个开源项目。欢迎每个人都来投稿。如果您愿意投稿,请随意处理未决问题。dev-1.0.1 分支上的单元测试接受拉请求。
如果你喜欢 PyCaret,请给我们 GitHub 回购的⭐️。
中:https://medium.com/@moez_62905/
领英:https://www.linkedin.com/in/profile-moez/
推特:【https://twitter.com/moezpycaretorg1 T43
在 Azure 上部署机器学习 Web 应用程序
使用 Azure Docker 容器将机器学习模型部署为 Web 应用程序的详细指南

照片由安迪·凯利 上Unsplash.com
作为一名机器学习工程师,你的角色不仅限于构建模型,还包括使模型可部署。后期由 DevOps 团队处理。在这个故事中,我将一步一步地向您展示如何在 Azure 上部署 ML 分类 Web 应用程序。本文是由微软学生合作伙伴(印度)项目发起的 MSP 开发者故事的一部分。
流线
首先,您需要先构建一个 web 应用程序。为此,您可以使用 Streamlit 。这是一个基于 python 的开源框架,可以帮助你在几个小时内显示文本、图表、地图、数据框架、构建交互界面等等。第一步,你只需要在本地机器上构建一个 app.py 文件,并确保它看起来像预期的那样。
通过在 shell 中从保存 app.py 文件的文件夹运行streamlit run app.py来启动您的 Streamlit 应用程序。每当保存 app.py 文件时,本地 web 应用程序都会自动更新。
在本地机器上完成构建后,下一个任务是将它部署到实际的互联网上,供其他人随时查看。现在你不能使用 GitHub pages,因为 Streamlit web app 是一个非静态网站。但是你肯定可以使用 GitHub 库来将其部署到 Azure。
看看 GitHub 中的 我的代码,你就会明白做一个 Streamlit web app 是多么简单。
Streamlit 的入门教程将有助于学习 API,因此我将直接跳到 Streamlit web 应用程序的部署。
对于这个例子,我将发布一个二元分类模型,显示蘑菇是可食用的还是有毒的。我将使用蘑菇数据集,你可以在我的 GitHub 上找到数据集。
建造码头集装箱
在您准备好发布 web 应用程序之后,您将在 Azure 容器注册中心创建一个 Docker 容器。该容器将包含运行 web 应用程序所需的所有文件。
我将完全使用 Azure Shell ,但是你可以使用 Azure Portal 或者在你的本地机器上安装 Azure CLI 。使用 Azure Shell 或 Azure CLI 是完全一样的,不同的是一个你将从浏览器使用,另一个你将从终端使用。
一旦你打开 Azure Shell,你将被要求登录你的 Azure 帐户。但是,如果您使用的是 Azure CLI,请键入以下命令:
az login
在您登录到您的 shell 后,您可以看到类似这样的内容。

来源:打开我的个人资料截图
接下来,您需要一个资源组来保存您的容器注册表和 Web App 服务。为此,请键入以下内容
az group create -l eastus -n MushroomApp
如果你使用 Azure Portal,那么按照他们的文档来构建资源组。
这里的位置是美国东部,名字是 MushroomApp 。您可以将其命名为不同的名称,但请确保在接下来的步骤中进行适当的更改。
然后,您将在资源组下构建容器注册表。
az acr create --name MushroomAppRegistry --resource-group MushroomApp --sku basic --admin-enabled true
如果您正在使用门户,请确保选择在上一步中创建的 MushroomApp 资源组。
Dockerfile、config 文件和 requirements.txt
回到你的 GitHub 库,添加几个有助于 web 应用运行的文件。首先,我们将制作 docker 文件。这将是 Docker 运行的指令。
关于编写 Dockerfile 的最佳实践,请参阅它们的官方文档。
本文档涵盖了构建高效映像的推荐最佳实践和方法。Docker 构建图像…
docs.docker.com](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/)
下面给出了可以用于这个项目的 docker 文件的代码。
对于配置文件,你需要 config.toml 和 credentials.toml。我推荐从他的 awesome-streamlit 存储库中复制 MarcSkovMadsen 的 config.toml 和 credentials.toml 文件。
接下来,您需要 requirements.txt 来添加运行 Web 应用程序所需安装的库。下面是 requirements.txt,我将在这个故事中使用。
streamlit
pandas
numpy
scikit-learn
matplotlib
在进入下一步之前,请确保您的 GitHub 存储库中有所有这些文件。

继续下一步之前需要的文件
接下来,我们将构建 docker 映像并保存到 Azure 容器注册表。
az acr build --registry MushroomAppRegistry --resource-group MushroomApp --image mushroom-app *<SOURCE_LOCATION>*
用您的 Git 克隆链接替换上面代码中的<source_location>。对于这个故事,我将使用的链接是https://github.com/sagnik20/ML-WebApp-using-Streamlit.git。</source_location>
如果构建成功,您可以看到类似于以下内容的输出: Run ID: ca1 在 2m26s 后成功。
如果您希望在容器注册表中看到图像,请登录到 Azure 门户并导航到您的资源组,单击您的容器注册表,然后在服务刀片下单击存储库。
从容器映像部署 Web 应用
你需要为你的 Web 应用创建一个应用服务计划。这将决定运行 Web 应用程序的虚拟机的大小。sku 的默认值是 B1,仅是 Free 上面的第一层。我们将利用这一点。
所有可用的定价等级有:F1(免费)、D1(共享)、B1(基本小型)、B2(基本中型)、B3(基本大型)、S1(标准小型)、P1V2(高级 V2 小型)、PC2(高级集装箱小型)、PC3(高级集装箱中型)、PC4(高级集装箱大型)、I1(独立小型)、I2(独立中型)、I3(独立大型)。选择一个你需要的。
az appservice plan create -g MushroomApp -n MushroomAppServicePlan -l eastus --is-linux --sku B1
运行以上代码创建您的应用服务计划。
通过运行以下命令,从容器注册表中的 docker 容器创建 Azure Web App。
az webapp create -g MushroomApp -p MushroomAppServicePlan -n census-web-app -i mushroomappregistry.azurecr.io/mushroom-app:latest
或者你也可以从门户网站做同样的事情。
现在,您应该可以在资源组中看到 3 个资源。

要查看您的新网站,请转到蘑菇-网络-应用程序资源,然后单击下图右上角的 URL。

第一次查看时,会有冷启动延迟,大约 5 分钟后可能会没有响应。返回到资源,再次单击 URL,您的 web 应用程序将出现在您的浏览器中!
重新部署您的网络应用
如果您需要对您的 app.py 文件进行任何更改,那么您可以通过重新部署您的 web 应用程序来轻松查看您的更改。再次运行下面的代码,替换 <源位置>再次。上面你已经做过一次了。
az acr build --registry MushroomAppRegistry --resource-group MushroomApp --image mushroom-app *<SOURCE_LOCATION>*
您可以添加功能或进行更改,只需重新部署 webapp 即可看到这些更改。
我构建的最终 web 应用程序看起来像这样👇

web 应用程序的屏幕截图
您也可以从:https://mushroom-web-app.azurewebsites.net/查看并与之互动(抱歉,该链接暂时无效)。
结论
我们已经成功地使用 Docker 和 Azure 将我们的机器学习模型部署为 Web 应用程序。完整代码可以在我的 GitHub Repo 上找到。**
感谢您的阅读!
我是 Sagnik Chattopadhyaya ,计算机科学大一新生(有机会)。推特: @sagnik_20 。YouTube: 学习溢出
希望你能从这个故事中吸取教训。❤
快乐学习!🐱💻
使用 docker compose 部署 MLflow
机器学习
借助 docker-compose 轻松部署 MLflow,跟踪您的机器学习体验

在建立和训练机器学习模型的过程中,跟踪每个实验的结果非常重要。对于深度学习模型,TensorBoard 是一个非常强大的工具,可以记录训练表现,跟踪梯度,调试模型等等。我们还需要跟踪相关的源代码,尽管 Jupyter 笔记本很难版本化,但我们绝对可以使用 git 这样的 VCS 来帮助我们。然而,我们还需要一个工具来帮助我们跟踪实验环境、超参数的选择、用于实验的数据集、结果模型等。正如其网站上所述,MLflow 是为此目的而专门开发的
MLflow 是一个管理 ML 生命周期的开源平台,包括实验、再现和部署。
为此,MLflow 提供了组件MLflow Tracking,这是一个 web 服务器,允许跟踪我们的实验/运行。
在这篇文章中,我将展示设置这样一个跟踪服务器的步骤,我将逐步添加组件,这些组件最终将被收集到 docker-compose 文件中。如果 MLflow 必须部署在远程服务器上,例如 EC2 上,docker 方法特别方便,而不必在每次需要新服务器时手动配置服务器。
基本本地服务器
安装 MLflow 服务器的第一步很简单,我们只需要安装 python 包。我假设 python 已经安装在您的机器上,并且您可以创建一个虚拟环境。为此,我发现 conda 比 pipenv 更方便
$ conda create -n mlflow-env python=3.7
$ conda activate mlflow-env
(mlflow-env)$ pip install mlflow
从这非常基本的第一步开始,我们的 MLflow 跟踪服务器就可以使用了,剩下的就是使用以下命令启动它:
(mlflow-env)$ mlflow server

在 [*http://localhost:5000*](http://localhost:5000*)找到跟踪服务器 UI
我们还可以指定主机地址,告诉服务器监听所有公共 IP。虽然这是一种非常不安全的方法(服务器未经认证和加密),但我们还需要在反向代理(如 NGINX)或虚拟专用网络中运行服务器来控制访问。
(mlflow-env)$ mlflow server — host 0.0.0.0
这里的0.0.0.0 IP 告诉服务器监听所有传入的 IP。
使用 AWS S3 作为工件商店
我们现在有一个正在运行的服务器来跟踪我们的实验和运行,但是为了更进一步,我们需要指定存储工件的服务器。为此,MLflow 提供了几种可能性:
- 亚马逊 S3
- Azure Blob 存储
- 谷歌云存储
- ftp 服务器
- SFTP 服务器
- 网络文件系统
- HDFS
因为我的目标是在云实例上托管 MLflow 服务器,所以我选择使用亚马逊 S3 作为工件商店。我们所需要的只是稍微修改一下命令来运行服务器
(mlflow-env)$ mlflow server — default-artifact-root s3://mlflow_bucket/mlflow/ — host 0.0.0.0
其中mlflow_bucket是先前创建的 S3 桶。这里你会问“我的 S3 桶到底是怎么访问的?”。嗯,简单看一下文件呵呵
MLflow 从您机器的 IAM 角色(一个~/中的配置文件)获取访问 S3 的凭证。aws/credentials 或环境变量 AWS_ACCESS_KEY_ID 和 AWS_SECRET_ACCESS_KEY,具体取决于哪一个可用。
所以更实际的做法是使用 IAM 角色,特别是如果我们想在 AWS EC2 实例上运行服务器。概要文件的使用与环境变量的使用非常相似,但是为了便于说明,我将使用环境变量,这将在使用 docker-compose 时进一步解释。
使用后端存储
SQLite 服务器
所以我们的追踪服务器在 S3 上储存了艺术品,没问题。但是,超参数、注释等仍然存储在主机上的文件中。文件可以说不是一个好的后端存储,我们更喜欢数据库后端。MLflow 支持各种数据库方言(本质上与 SQLAlchemy 相同):mysql、mssql、sqlite和postgresql。
首先,我喜欢使用 SQLite,因为它是文件和数据库之间的妥协,因为整个数据库存储在一个文件中,可以很容易地移动。语法与 SQLAlchemy 相同:
(mlflow-env)$ mlflow server — backend-store-uri sqlite:////location/to/store/database/mlruns.db — default-artifact-root s3://mlflow_bucket/mlflow/ — host 0.0.0.0
MySQL 服务器
请记住,我们希望使用 docker 容器,将这些文件存储在本地并不是一个好主意,因为我们会在每次重启容器后丢失数据库。当然,我们仍然可以在 EC2 实例上挂载一个卷和一个 EBS 卷,但是使用一个专用的数据库服务器会更简洁。为此,我喜欢使用 MySQL。因为我们将使用 docker 进行部署,所以让我们推迟 MySQL 服务器的安装(因为它将是一个来自官方 docker 映像的简单 docker 容器),并专注于 MLflow 的使用。首先,我们需要安装我们想要用来与 MySQL 交互的 python 驱动程序。我喜欢pymysql是因为它安装非常简单,非常稳定,并且有据可查。因此,在 MLflow 服务器主机上,运行以下命令
(mlflow-env)$ pip install pymysql
现在我们可以根据 SQLAlchemy 的语法更新命令来运行服务器
(mlflow-env)$ mlflow server — backend-store-uri mysql+pymysql://mlflow:strongpassword@db:3306/db — default-artifact-root s3://mlflow_bucket/mlflow/ — host 0.0.0.0
这里我们假设我们的服务器名是db,它监听端口3306。我们还使用用户mlflow和非常强的密码strongpassword。同样,它在生产环境中不是很安全,但是当使用 docker-compose 部署时,我们可以使用环境变量。
NGINX
如前所述,我们将在反向代理 NGINX 后面使用 MLflow 跟踪服务器。为此,我们将再次使用一个官方的 docker 映像,并简单地用以下内容替换默认配置/etc/nginx/nginx.conf
nginx.conf
如果需要进一步定制,您可以使用这个基本配置文件。最后,我们将对存储在/etc/nginx/sites-enabled/mlflow.conf中的 MLflow 服务器进行配置
mlflow.conf
请注意用于引用 MLflow 应用程序[http://web:5000](http://web:5000.) 的 URL。ml flow 服务器使用端口5000,应用程序将在 docker-compose 服务中运行,其名称将为web。
集装箱化
如前所述,我们希望在 docker 容器中运行所有这些。该架构很简单,由三个容器组成:
- 一个 MySQL 数据库服务器,
- 一种 MLflow 服务器,
- 反向代理 NGINX
对于数据库服务器,我们将使用官方的 MySQL 镜像,不做任何修改。
对于 MLflow 服务器,我们可以在 debian slim 映像上构建一个容器。Dockerfile 文件非常简单:
MLflow 跟踪服务器容器的 Dockerfile
最后,NGINX 反向代理也是基于官方图片和之前的配置
NGINX 的 Dockerfile
用 docker-compose 收集
现在我们已经设置好了,是时候把它们收集到 docker-compose 文件中了。然后,只需一个命令就可以启动我们的 MLflow 跟踪服务器,这非常方便。我们的 docker-compose 文件由三个服务组成,一个用于后端,即 MySQL 数据库,一个用于反向代理,一个用于 MLflow 服务器本身。看起来像是:
docker-compose.yml
首先要注意的是,我们构建了两个自定义网络来隔离前端(MLflow UI)和后端(MySQL 数据库)。只有web服务,即 MLflow 服务器可以与两者对话。其次,因为我们不想在容器关闭时丢失所有数据,所以 MySQL 数据库的内容是一个名为dbdata的挂载卷。最后,这个 docker-compose 文件将在 EC2 实例上启动,但是因为我们不想硬编码 AWS 键或数据库连接字符串,所以我们使用环境变量。这些环境变量可以直接位于主机上,或者位于 docker-compose 文件所在目录下的一个.env文件中。剩下的工作就是构建和运行容器
$ docker-compose up -d --build
-d选项告诉我们想要在守护模式下执行容器,而--build选项表明我们想要在运行它们之前构建 docker 映像(如果需要的话)。
仅此而已!我们现在有了一个完美运行的远程 MLflow 跟踪服务器,可以在我们的团队之间共享。多亏了 docker-compose,只需一个命令就可以轻松地将该服务器部署到任何地方。
机器学习快乐!
在 PyTorch 中部署模型🚀

由 SpaceX 在 Unsplash 上拍摄的照片
火炬来救援了!
本文中使用的所有代码都是 这里的
最近,PyTorch 推出了名为torchserve.的新生产框架来适当地服务于模型,因此,不多说了,让我们来介绍一下今天的路线图:
- 用 Docker 安装
- 导出您的模型
- 定义处理程序
- 为我们的模型服务
为了展示 torchserve,我们将提供经过全面培训的 ResNet34 来执行图像分类。
用 Docker 安装
公文 此处
安装 torchserve 最好的方法是用 docker。你只需要调出图像。
您可以使用以下命令保存最新的图像。
docker pull pytorch/torchserve:latest
所有的标签都可以在这里
更多关于 docker 和 torchserve 这里
经理人
正式文件 此处
处理程序负责使用您的模型从一个或多个 HTTP 请求中做出预测。
默认处理程序
Torchserve 支持以下默认处理程序
image_classifierobject_detectortext_classifierimage_segmenter
但是请记住,它们都不支持批处理请求!
自定义处理程序
torchserve 公开了一个丰富的接口,可以做几乎所有你想做的事情。An Handler只是一个必须有三个功能的类
- 预处理
- 推理
- 后处理
你可以创建自己的类或者子类BaseHandler。子类化BaseHandler的主要优点是可以在self.model访问加载的模型。下面的代码片段显示了如何子类化BaseHandler

子类化 BaseHandler 以创建您自己的处理程序
回到我们的图像分类例子。我们需要
- 从每个请求中获取图像并对其进行预处理
- 从模型中获得预测
- 发回回复
预处理
.preprocess函数接受一组请求。假设我们向服务器发送一个图像,可以从请求的data或body字段访问序列化的图像。因此,我们可以遍历所有请求,并单独预处理每幅图像。完整的代码如下所示。

预处理每个请求中的每个图像
self.transform是我们的预处理改造,没什么花哨的。对于在 ImageNet 上训练的模型,这是一个经典的预处理步骤。

我们的转变
在我们对每个请求中的每个图像进行预处理后,我们将它们连接起来以创建 pytorch 张量。
推论

对我们的模型进行推理
这一步非常简单,我们从.preprocess函数中得到张量,并提取每幅图像的预测。
后处理
现在我们有了对每幅图像的预测,我们需要向客户端返回一些东西。 Torchserve 总是期望返回一个数组。 BaseHandler也会自动打开一个映射为index -> label的.json文件(我们稍后会看到如何提供这样的文件)并存储在self.mapping。我们可以为每个预测返回一个带有label和index类的字典数组

把所有东西都包起来,我们光荣的训练员看起来像

因为所有的处理逻辑都封装在一个类中,所以你可以很容易地对它进行单元测试!
导出您的模型
公文 此处
Torchserve 期望提供一个.mar文件。简而言之,这个文件就是你的模型和所有的依赖关系。创建一个需要首先导出我们的训练模型。
导出模型
有三种方法可以导出 torchserve 的模型。到目前为止,我发现的最好的方法是trace模型并存储结果。通过这样做,我们不需要添加任何额外的文件到 torchserve。
让我们看一个例子,我们将部署一个经过全面训练的 ResNet34 模型。

为此,我们:
- 加载模型
- 创建一个虚拟输入
- 使用
torch.jit.trace通过模型追踪输入 - 保存模型
创造。标记文件
公文 此处
你需要安装torch-model-archiver
git clone https://github.com/pytorch/serve.git
cd serve/model-archiver
pip install .
然后,我们准备通过使用下面的命令来创建.mar文件
torch-model-archiver --model-name resnet34 \--version 1.0 \--serialized-file resnet34.pt \--extra-files ./index_to_name.json,./MyHandler.py \--handler my_handler.py \--export-path model-store -f
按顺序。变量--model-name定义了我们模型的最终名称。这非常重要,因为它将是负责其预测的端点的名称空间。也可以指定一个--version。--serialized-file指向我们之前创建的存储的.pt模型。--handler是一个 python 文件,我们在其中调用我们的自定义处理程序。一般来说,它看起来总是这样:

my_handler.py
它公开了一个handle函数,我们从这个函数调用定制处理程序中的方法。您可以使用默认名称来使用默认句柄(例如--handler image_classifier)。
在--extra-files中,您需要传递您的处理程序正在使用的所有文件的路径。在我们的例子中,我们必须将路径添加到包含所有人类可读标签名称的.json文件和包含MyHandler.类定义的MyHandler.py文件中
一件小事,如果你传递一个index_to_name.json文件,它将被自动加载到处理程序中,并且可以在self.mapping访问。
--export-path是存储.mar文件的地方,我还添加了-f来覆盖其中的所有内容。
如果一切顺利,您应该会看到resnet34.mar被存储到./model-store中。
为我们的模型服务
这是一个简单的步骤,我们可以用所有需要的参数运行 torchserve docker 容器
docker run --rm -it \-p 3000:8080 -p 3001:8081 \-v $(pwd)/model-store:/home/model-server/model-store pytorch/torchserve:0.1-cpu \torchserve --start --model-store model-store --models resnet34=resnet34.mar
我将容器端口 8080 和 8081 分别绑定到 3000 和 3001(8080/8081 已经在我的机器上使用)。然后,我从./model-store(我们存储.mar文件的地方)到容器默认的model-store文件夹创建一个卷。最后,我通过填充model-store路径和一个键值对列表来调用torchserve,在这个列表中,我们为每个.mar文件指定了模型名称。
在这一点上,torchserve 有一个端点/predictions/resnet34,我们可以通过发送图像来获得预测。这可以使用curl来完成
curl -X POST [http://127.0.0.1:3000/predictions/resnet34](http://127.0.0.1:3000/predictions/resnet34) -T inputs/kitten.jpg

kitten.jpg .来源
回应
{
"label": "tiger_cat",
"index": 282
}
成功了!🥳
摘要
概括地说,在本文中,我们讨论了:
- 用 docker 安装火炬服务器
- 默认和自定义处理程序
- 模型档案生成
- 用 docker 服务最终模型
这里所有的代码都是
如果你喜欢这篇文章和 pytorch,你可能也会对我的其他文章感兴趣
一个干净简单的模板来启动你的下一个 dl 项目🚀🚀
towardsdatascience.com](/pytorch-deep-learning-template-6e638fc2fe64) [## Pytorch:如何以及何时使用模块、顺序、模块列表和模块指令
Pytorch 1.5 更新
towardsdatascience.com](/pytorch-how-and-when-to-use-module-sequential-modulelist-and-moduledict-7a54597b5f17)
感谢您的阅读。
弗朗西斯科
在 AWS 上部署、监控和扩展机器学习模型
Cortex 如何帮助数据科学家将他们的机器学习模型投入生产。

泰勒·维克在 Unsplash 上的照片
部署健壮的和可扩展的机器学习解决方案仍然是一个相当手工和复杂的过程,需要大量的人工参与和努力。因此,新产品和服务需要很长时间才能上市,或者在原型状态下被放弃,从而降低了行业内的兴趣。那么,我们如何才能促进将机器学习模型投入生产的过程呢?
Cortex 是一个开源平台,用于将机器学习模型部署为生产 web 服务。它利用强大的 AWS 生态系统根据需要部署、监控和扩展与框架无关的模型。其主要特点可归纳如下:
- 框架无关: Cortex 支持任何一段 python 代码;TensorFlow、PyTorch、scikit-learn、XGBoost 都是由库支持的,就像任何其他 python 脚本一样。
- 自动伸缩: Cortex 自动伸缩您的 API,以处理生产工作负载。
- CPU / GPU 支持: Cortex 可以运行在使用 AWS IaaS 作为其底层基础设施的 CPU 或 GPU 环境上。
- Spot 实例: Cortex 支持 EC2 spot 实例以降低成本。
- 滚动更新: Cortex 在不停机的情况下将任何更新应用于模型。
- 日志流式传输: Cortex 保存来自已部署模型的日志,并使用类似 docker 的熟悉语法将它们流式传输到您的 CLI。
- 预测监控: Cortex 监控网络指标,跟踪预测。
- 最小配置: Cortex 部署配置被定义为一个简单的 YAML 文件。
在这个故事中,我们使用 Cortex 在 AWS 上部署一个图像分类模型作为 web 服务。那么,事不宜迟,我们来介绍一下 Cortex。
学习率是为那些对 AI 和 MLOps 的世界感到好奇的人准备的时事通讯。你会在每周五收到我关于最新人工智能新闻和文章的更新和想法。在这里订阅!
将您的模型部署为 Web 服务
对于这个例子,我们使用了 fast.ai 库,并从相关 MOOC 的第一门课程中借用了 pets 分类模型。接下来的部分将介绍 Cortex 的安装和 pets 分类模型作为 web 服务的部署。
装置
如果您还没有这样做,那么您应该做的第一件事就是在 AWS 上创建一个新的用户帐户,并提供编程访问。为此,选择IAM服务,然后从右侧面板选择Users,最后按下Add User按钮。为您的用户命名,然后选择Programmatic access。

接下来,在Permissions屏幕中选择Attach existing policies directly选项卡并选择AdministratorAccess。

您可以将标签页留空,查看并创建您的用户。最后,记下访问密钥 ID 和秘密访问密钥。
当您在 AWS 控制台上时,您还可以创建一个S3桶,来存储训练好的模型和您的代码可能产生的任何其他工件。你可以给这个桶取任何你喜欢的名字,只要它是一个唯一的名字。对于这个故事,我们创建了一个名为cortex-pets-model的桶。
下一步,我们必须在系统上安装 Cortex CLI 并启动 Kubernetes 集群。要安装 Cortex CLI,请运行以下命令:
bash -c “$(curl -sS https://raw.githubusercontent.com/cortexlabs/cortex/0.14/get-cli.sh)"
通过访问相应的文档部分,检查您是否安装了最新版本的 Cortex CLI
我们现在准备设置我们的集群。使用 Cortex 创建 Kubernetes 集群很简单。只需执行下面的命令:
cortex cluster up
Cortex 将要求您提供一些信息,例如您的 AWS 键、您想要使用的区域、您想要启动的计算实例以及它们的数量。Cortex 还会让您知道使用您选择的服务将支付多少费用。整个过程可能需要 20 分钟。

训练您的模型
Cortex 不关心你如何创建或训练你的模型。对于这个例子,我们使用 fast.ai 库和牛津-IIIT Pet 数据集。该数据集包含 37 种不同品种的狗和猫。因此,我们的模型应该将每张图片分为这 37 个类别。
创建一个trainer.py文件,如下图所示。
在本地运行脚本,就像任何其他 python 脚本一样:python trainer.py。但是,一定要提供您的 AWS 凭证和S3 bucket 名称。这个脚本获取数据,处理它们,符合预先训练的 ResNet 模型,并上传到S3。当然,您可以扩展这个脚本,使用多种技术使模型更加准确——更复杂的架构、有区别的学习率、针对更多时期的训练——但这与我们这里的目标无关。如果您想进一步了解 ResNet 架构,请阅读下面的文章。
从你的 ResNet 架构中挤出一点额外的东西。
towardsdatascience.com](/xresnet-from-scratch-in-pytorch-e64e309af722)
部署您的模型
既然我们已经在S3上训练并存储了我们的模型,下一步就是将它作为 web 服务部署到生产中。为此,我们创建一个 python 脚本,名为predictor.py,如下图所示:
该文件定义了一个预测器类。当它被实例化时,它从S3中检索模型,将其加载到内存中,并定义一些必要的转换和参数。在推断过程中,它从给定的URL中读取图像,并返回预测类的名称。预测器的接口正是如此。一个用于初始化的__init__方法和一个用于接收有效载荷并返回结果的predict方法。
预测器脚本有两个附带文件。记录库依赖关系的requirements.txt文件(如 pytorch、fastai、boto3 等。)和一个 YAML 配置文件。最低配置如下所示:
在这个 YAML 文件中,我们定义了运行哪个脚本进行推理,在哪个设备(例如 CPU)上运行,以及在哪里找到训练好的模型。文档中提供了更多选项。
最后,项目的结构应该遵循下面的层次结构。请注意,这只是最低要求,但是如果您已经为部署准备好了模型,您可以提交trainer.py。
- Project name
|----trainer.py
|----predictor.py
|----requirements.txt
|----cortex.yaml
准备就绪后,您可以简单地运行cortex deploy,几秒钟后,您的新端点就可以接受请求了。执行corted get pets-classifier监控端点并查看更多详细信息。
status up-to-date requested last update avg request 2XX
live 1 1 13m - -endpoint: [http://a984d095c6d3a11ea83cc0acfc96419b-1937254434.us-west-2.elb.amazonaws.com/pets-classifier](http://a984d095c6d3a11ea83cc0acfc96419b-1937254434.us-west-2.elb.amazonaws.com/pets-classifier)
curl: curl [http://a984d095c6d3a11ea83cc0acfc96419b-1937254434.us-west-2.elb.amazonaws.com/pets-classifier?debug=true](http://a984d095c6d3a11ea83cc0acfc96419b-1937254434.us-west-2.elb.amazonaws.com/pets-classifier?debug=true) -X POST -H "Content-Type: application/json" -d [@sample](http://twitter.com/sample).jsonconfiguration
name: pets-classifier
endpoint: /pets-classifier
predictor:
type: python
path: predictor.py
config:
bucket: cortex-pets-model
device: cpu
key: model.pkl
compute:
cpu: 200m
autoscaling:
min_replicas: 1
max_replicas: 100
init_replicas: 1
workers_per_replica: 1
threads_per_worker: 1
target_replica_concurrency: 1.0
max_replica_concurrency: 1024
window: 1m0s
downscale_stabilization_period: 5m0s
upscale_stabilization_period: 0s
max_downscale_factor: 0.5
max_upscale_factor: 10.0
downscale_tolerance: 0.1
upscale_tolerance: 0.1
update_strategy:
max_surge: 25%
max_unavailable: 25%
剩下的就是用curl和一只博美犬的图像来测试它:
curl [http://a984d095c6d3a11ea83cc0acfc96419b-1937254434.us-west-2.elb.amazonaws.com/pets-classifier](http://a984d095c6d3a11ea83cc0acfc96419b-1937254434.us-west-2.elb.amazonaws.com/pets-classifier?debug=true) -X POST -H "Content-Type: application/json" -d '{"url": "[https://i.imgur.com/HPRQ28l.jpeg](https://i.imgur.com/HPRQ28l.jpeg)"}'
打扫
当我们完成服务和集群时,我们应该释放资源以避免额外的成本。Cortex 让这一切变得简单:
cortex delete pets-classifier
cortex cluster down
结论
在这个故事中,我们看到了如何使用 Cortex,这是一个开源平台,用于将机器学习模型部署为生产 web 服务。我们训练了一个图像分类器,将其部署在 AWS 上,监控其性能并对其进行测试。
对于更高级的概念,如预测监控、滚动更新、集群配置、自动扩展等,请访问官方文档网站,以及该项目的 GitHub 页面。
我叫 Dimitris Poulopoulos,是希腊比雷埃夫斯大学BigDataStack的机器学习研究员和博士(c)。我曾为欧洲委员会、欧盟统计局、国际货币基金组织、欧洲中央银行、经合组织和宜家等主要客户设计和实施人工智能和软件解决方案。如果你有兴趣阅读更多关于机器学习、深度学习和数据科学的帖子,请在 twitter 上关注我的**LinkedIn或@ james2pl。******
使用 Flask、Docker 和 AWS Beanstalk 部署神经网络
如何部署预测语音情感的机器学习多类分类 Keras 模型?

第一部分:
构建 NN 模型,Flask 应用程序,包括用于录音机的 Html、CSS、js。
第二部分:
如何为你的 Docker 镜像选择合适的配置。
第三部分:
在 AWS 弹性豆茎上部署以及如何调整录音笔。
以上所有内容也包含常见的故障排除。其中一些你会在我的 StackOverflow 上找到。
第一部分 :
为什么要声情并茂?由于过去十年技术的指数增长,生活方式发生了变化,人们要求更快、更容易地使用服务。许多公司确实续签了合同,并且只通过一个电话就获得了合法有效的客户协议。更不用说所有的营销,客户成功和销售使用。从语音输入/电话中预测客户的情绪变得非常必要。
现在我们来看看语音情感模型。
用于训练模型的数据集:在受控环境中包含不同的说话者,主要是演员,并且确实传达了以下情绪,对于女性和男性:愤怒、厌恶、恐惧、高兴、中立、悲伤、惊讶。(14 节课——因为把女声和男声分开训练总是明智的)。
为了从音频中提取和转换数据特征(梅尔频率倒谱系数: MFCC ),我使用了 LibROSA 。使用Keras 建立模型:顺序带 Conv1D 层带批处理规范化、 Dropout、和 MaxPooling1D 。请随意试用我的 Kaggle 内核。
Flask 应用:向用户请求数据,并保存为 WAV 文件,以便以后处理和预测。这里需要记住几件事:
- 确保您的应用程序文件的名称是: application.py 和
application=FLASK(__name__) - 当谈到 Keras 和 Flask 时:你会发现 Keras 不是线程安全的,你需要使用
model._make_predict_function()为什么会这样,如何解决,在我的 StackOverflow 解决方案上找到它(这里你得到了使用上述方法的优点和缺点。
在我的 Github repo 中找到录音机的 Html、CSS 和 js 。可以在 recapp.js 中修改录音时间,只要记住 1 秒=1000 毫秒:setTimeout(function(){console.log("Recording:time up");stopRecording();},4000);

第二部分 :
我首先用 AWS Beanstalk 部署了 Flask 应用程序,发现服务器错误日志并不是那么详细和清晰,所以我发现 Docker 错误日志非常有用。
当然,Docker 附带了许多其他的一体化工具和功能,使得构建环境变得更加简单和紧凑。
这将帮助您在构建 Docker 映像和处理故障排除时做出正确的选择:
- 从一开始就考虑容器/图像大小的限制,并为 python 图像选择正确的版本。你将在你的 docker 文件中设置这个:
FROM python:3.6-slim(注意:现在将避免 Alpine Linux,因为一些不合适的东西:更少的库,不同的 C 库,等等。).选择最精简版本的唯一问题是,你可能需要安装一些库/依赖项。而且可能相当麻烦… python 依赖项,如 LibROSA、GCC 等的声音文件.. - 您可能需要安装系统软件包,为此,您将需要安装 sudo。附注:当提示 Y/N 时,不要忘记使用 -y ,否则如果没有键盘输入,安装将中止。
- 对于音频安装 libsndfile1-dev (这应该可以解决 Linux 和 Ubuntu 的所有问题)。
- 确保在一次运行中运行所有内容,以避免创建中间映像:
RUN apt-get update && \
apt-get -y --no-install-recommends install sudo && \
sudo apt-get -y --no-install-recommends install libsndfile1-dev && \
pip install --no-cache-dir -r requirements.txt && \
sudo rm -rf /var/lib/apt/lists/*
- 要确保软件包不安装主动提供的依赖项:
sudo --no-install-recommends或pip instal --no-deps #no dependencies尽管这在处理 Tensorflow 和 Keras(如 Scikit-learn、SciPy 等)时可能会很麻烦。)pip instal --no-cache-dir有助于额外的缓存,
-也有助于清理剩菜:sudo rm -rf /var/lib/apt/lists/*
- docker 文件中的其他行应该涵盖申请的其余部分,如:
WORKDIR /deploy/ # pick your working directory
COPY . . # useful for copying all folders and subfoldersEXPOSE 5000 # set port 5000 for Flask app
CMD [“python”, “application.py”] #application to be run

亚马逊网络服务和弹性豆茎看起来是个不错的选择。
我已经遵循了创建单个容器 docker 环境的所有说明。
如果你使用 AWS 控制台,事情就很简单了。如果您使用 AWS/EB CLI,请确保在安装 EB CLI 后设置路径:
echo 'export PATH="/Users/Daniel/.ebcli-virtual-env/executables:$PATH"' >> ~/.bash_profile && source ~/.bash_profile
您在 beanstalk 中创建新的应用程序和环境,上传 docker 应用程序文件夹内容的归档/zip。从控制台中,您可以修改容量、想要使用的实例、环境类型(负载平衡、自动伸缩)等等。
现在我们来看看故障排除:
- 现在所有问题都已解决并部署完毕,您可以访问 AWS beanstalk Http 链接,该链接将您带到您的应用程序,您可能会发现您的语音应用程序运行得非常好,只是您可以通过 web 浏览器请求访问您用户的麦克风。答案很简单:确保你在 https 上运行它。
- 然后 OpenSSL 注册并获得密钥以及自己签署 RSA (仅用于开发目的)。并将所有内容添加到 docker 下的 YAML 或 JSON 文件中。ebextensions”文件夹。(在我的 GitHub 上找到)
- 如果你是 Mac 用户,遇到 __MACOSX/错误,只需在命令行
zip -d Archive.zip __MACOSX/\*中对你的文档执行操作 - 如果你得到的错误为配置文件。应用程序版本…中的 ebextensions/filename.config 包含无效的 YAML 或 JSON。YAML 异常:无效的 Yaml:在解析"<阅读器>"行…等中的块映射时。:确保您的 RSA 密钥行对齐并且与 YAML 兼容。
- 为 HTTPS 配置 AWS Beanstalk 单实例 SSL 的结论(针对 Docker env):在花时间搞清楚 YAML 和制表符与空格(或者在键页脚后没有空格,或者..)在我的编辑器( Atom/Packages/Whitespace ),甚至将 YAML 转换为 JSON(Atom/Packages/YAML _ JSON 转换器)中,我已经意识到初始密钥被破解,不得不 生成一个新的集合!!!
以上所有代码和指令都可以通过我的 StackOverflow response 找到。
我希望这有所帮助(并且为你节省了几天的辛苦工作)现在你的应用程序运行顺利,你也喜欢这些预测。我的 Github 上提供的模型给出了略低于 50%的准确度——尽管乍一看这对于多类分类来说是相当好的。
保重,祝大家 2020 年,
指数级增长和创新的新十年!!!
丹尼尔(男子名)
使用 AWS Fargate(无服务器基础设施)部署 PyCaret 并简化应用程序

在 AWS Fargate 上封装和部署 ML pipeline serverless 的循序渐进的初学者指南
概述
在我们的上一篇文章中,我们展示了如何使用 PyCaret 开发机器学习管道,并将其作为部署在 Google Kubernetes 引擎上的 Streamlit web 应用程序。如果你以前没有听说过 PyCaret,你可以阅读这个公告来开始。
在本教程中,我们将使用我们之前构建的相同的 web 应用程序和机器学习管道,并演示如何使用 AWS Fargate 部署它,这是一种用于容器的无服务器计算。
在本教程结束时,您将能够在 AWS 上构建和托管一个全功能的容器化 web 应用程序,而无需提供任何服务器基础设施。

网络应用
👉本教程的学习目标
- 什么是容器?Docker 是什么?什么是 Kubernetes?
- 什么是亚马逊弹性容器服务(ECS)、AWS Fargate 和无服务器部署?
- 构建一个 Docker 映像并将其推送到 Amazon 弹性容器注册中心。
- 使用无服务器基础设施(如 AWS Fargate)部署 web 应用程序。
本教程将涵盖整个工作流程,从在本地构建 docker 映像开始,将其上传到 Amazon Elastic Container Registry,创建一个集群,然后使用 AWS 管理的基础设施定义和执行任务。
过去,我们已经讨论过在其他云平台上的部署,比如 Azure 和 Google。如果您有兴趣了解更多相关信息,可以阅读以下教程:
- 在谷歌 Kubernetes 引擎上部署 Streamlit 应用
- 使用 PyCaret 和 Streamlit 构建和部署机器学习 web 应用
- 在 AWS Fargate 上部署机器学习管道
- 在 Google Kubernetes 引擎上部署机器学习管道
- 在 AWS Web 服务上部署机器学习管道
- 在 Heroku PaaS 上构建和部署您的第一个机器学习 web 应用
💻本教程的工具箱
PyCaret
PyCaret 是 Python 中的开源、低代码机器学习库,用于训练和部署机器学习管道和模型到生产中。PyCaret 可以使用 pip 轻松安装。
pip install pycaret
细流
Streamlit 是一个开源的 Python 库,可以轻松地为机器学习和数据科学构建漂亮的定制 web 应用。使用 pip 可以轻松安装 Streamlit。
pip install streamlit
Windows 10 家庭版 Docker 工具箱
Docker 是一个工具,旨在通过使用容器来更容易地创建、部署和运行应用程序。容器用于打包应用程序及其所有必需的组件,如库和其他依赖项,并作为一个包发送出去。如果你之前没有用过 docker,本教程还涵盖了在 Windows 10 Home 上安装 Docker 工具箱(legacy)。在之前的教程中,我们介绍了如何在 Windows 10 Pro edition 上安装 Docker Desktop。
亚马逊网络服务(AWS)
亚马逊网络服务(AWS)是由亚马逊提供的一个全面且广泛采用的云平台。它拥有来自全球数据中心的超过 175 项全功能服务。如果你以前没用过 AWS,你可以注册免费账号。
✔️Let's 开始吧…..
什么是容器?
在我们开始使用 AWS Fargate 实现之前,让我们了解一下什么是容器,为什么我们需要容器?

https://www.freepik.com/free-photos-vectors/cargo-ship
您是否遇到过这样的问题:您的代码在您的计算机上运行得很好,但是当一个朋友试图运行完全相同的代码时,却无法运行?如果你的朋友重复完全相同的步骤,他们应该得到相同的结果,对不对?对此,一个词的答案是 环境。你朋友的环境和你不同。
环境包括什么?Python 等编程语言以及所有库和依赖项,以及构建和测试应用程序时使用的确切版本。
如果我们可以创建一个可以转移到其他机器上的环境(例如:你朋友的电脑或者谷歌云平台这样的云服务提供商),我们就可以在任何地方重现结果。因此,容器 是一种将应用程序及其所有依赖项打包的软件,因此应用程序可以从一个计算环境可靠地运行到另一个计算环境。
Docker 是什么?
Docker 是一家提供软件(也叫 Docker )的公司,允许用户构建、运行和管理容器。虽然 Docker 的集装箱是最常见的,但还有其他不太出名的替代品,如 LXD 的和 LXC 的。

现在,您已经从理论上了解了什么是容器,以及 Docker 如何用于容器化应用程序,让我们想象一个场景,其中您必须在一组机器上运行多个容器,以支持一个企业级机器学习应用程序,该应用程序在白天和晚上都有不同的工作负载。这在现实生活中很常见,尽管听起来很简单,但手动完成的工作量很大。
您需要在正确的时间启动正确的容器,弄清楚它们如何相互通信,处理存储考虑事项,处理失败的容器或硬件以及数以百万计的其他事情!
管理成百上千个容器以保持应用程序正常运行的整个过程被称为容器编排。先不要纠结于技术细节。
在这一点上,您必须认识到管理现实生活中的应用程序需要不止一个容器,并且管理所有的基础设施以保持容器正常运行是繁琐的、手动的和管理负担。
这就把我们带到了 T21。
什么是 Kubernetes?
Kubernetes 是谷歌在 2014 年开发的一个开源系统,用于管理容器化的应用程序。简而言之,Kubernetes 是一个跨机器集群运行和协调容器化应用的系统。

虽然 Kubernetes 是谷歌开发的开源系统,但几乎所有主要的云服务提供商都将 Kubernetes 作为托管服务提供。比如:亚马逊提供的亚马逊弹性 Kubernetes 服务(EKS) ,谷歌提供的谷歌 Kubernetes 引擎,微软提供的 Azure Kubernetes 服务(AKS) 。
到目前为止,我们已经讨论并理解了:
✔️一 集装箱
✔️码头工人
✔️·库伯内特
在介绍 AWS Fargate 之前,只剩下一件事要讨论,那就是亚马逊自己的容器编排服务亚马逊弹性容器服务(ECS)。****
AWS 弹性集装箱服务
亚马逊弹性容器服务(Amazon ECS)是亚马逊自己开发的容器编排平台。ECS 背后的思想类似于 Kubernetes (两者都是编排服务)。
ECS 是 AWS 本地服务,这意味着它只能在 AWS 基础设施上使用。另一方面, EKS 基于 Kubernetes,这是一个开源项目,用户可以在多云(AWS、GCP、Azure)甚至本地运行。
亚马逊还提供基于 Kubernetes 的容器编排服务,称为亚马逊弹性 Kubernetes 服务(亚马逊 EKS)。尽管 ECS 和 EKS 的目的非常相似,即编排容器化的应用程序,但在定价、兼容性和安全性方面还是有相当大的差异。没有最佳答案,解决方案的选择取决于使用案例。
无论您使用哪种容器编排服务(ECS 或 EKS ),都有两种方法可以实现底层基础架构:
- 手动管理群集和底层基础架构,如虚拟机/服务器/(也称为 EC2 实例)。
- 无服务器—完全不需要管理任何东西。只需上传容器就可以了。← 这是 AWS Fargate。

亚马逊 ECS 底层基础设施
AWS Fargate —集装箱的无服务器计算
AWS Fargate 是一个用于容器的无服务器计算引擎,它与亚马逊弹性容器服务(ECS)和亚马逊弹性库本内特服务(EKS)一起工作。Fargate 使您可以轻松地专注于构建应用程序。Fargate 消除了供应和管理服务器的需要,允许您为每个应用程序指定和支付资源,并通过设计应用程序隔离来提高安全性。
Fargate 分配适当的计算量,消除了选择实例和扩展集群容量的需要。您只需为运行容器所需的资源付费,因此不存在过度配置和为额外的服务器付费的问题。

AWS Fargate 如何工作—https://aws.amazon.com/fargate/
对于哪种方法更好,没有最佳答案。选择无服务器还是手动管理 EC2 集群取决于使用案例。有助于这一选择的一些要点包括:
ECS EC2(人工进近)
- 你全押在 AWS 上。
- 您有专门的运营团队来管理 AWS 资源。
- 您在 AWS 上已经有了足迹,即您已经在管理 EC2 实例
AWS 法盖特
- 您没有庞大的运营团队来管理 AWS 资源。
- 你不想要操作责任或想要减少它。
- 您的应用程序是无状态的(无状态应用程序不保存在一个会话中生成的客户端数据,以便在下一个与该客户端的会话中使用)。
设置业务环境
一家保险公司希望通过使用住院时的人口统计和基本患者健康风险指标来更好地预测患者费用,从而改善其现金流预测。

( 数据源 )
目标
构建和部署一个 web 应用程序,将患者的人口统计和健康信息输入到基于 web 的表单中,然后输出预测的收费金额。
任务
- 使用 PyCaret 训练、验证和开发机器学习管道。
- 构建一个前端 web 应用程序,具有两个功能:(一)在线预测和(二)批量预测。
- 创建 Dockerfile 文件
- 创建并执行任务,使用 AWS Fargate 无服务器基础架构部署应用程序。
由于我们已经在上一篇教程中介绍了前两项任务,我们将快速回顾一下,然后将注意力集中在上面列表中的剩余项目上。如果您有兴趣了解更多关于使用 PyCaret 在 Python 中开发机器学习管道以及使用 Streamlit 框架构建 web 应用程序的信息,请阅读本教程。
👉任务 1 —模型训练和验证
我们正在使用 Python 中的 PyCaret 进行训练,并开发一个机器学习管道,它将作为我们 web 应用程序的一部分。机器学习管道可以在集成开发环境(IDE)或笔记本中开发。我们使用笔记本运行了以下代码:
当您在 PyCaret 中保存一个模型时,基于在 setup() 函数中定义的配置的整个转换管道被创建。所有的相互依赖都是自动编排的。查看存储在“deployment_28042020”变量中的管道和模型:

使用 PyCaret 创建的机器学习管道
👉任务 2 —构建前端 web 应用程序
现在,我们的机器学习管道和模型已经准备好开始构建一个前端 web 应用程序,它可以在新的数据点上生成预测。该应用程序将通过 csv 文件上传支持“在线”以及“批量”预测。让我们将应用程序代码分成三个主要部分:
页眉/布局
该部分导入库,加载训练模型,并创建一个基本布局,顶部有一个徽标,一个 jpg 图像,边栏上有一个下拉菜单,用于在“在线”和“批量”预测之间切换。

app.py —代码片段第 1 部分
在线预测
本节处理初始 app 功能,在线逐一预测。我们正在使用 streamlit 小部件,如数字输入、文本输入、下拉菜单和复选框来收集用于训练模型的数据点,如年龄、性别、身体质量指数、儿童、吸烟者、地区。

app.py —代码片段第 2 部分
批量预测
批量预测是该应用的第二层功能。streamlit 中的 file_uploader 小部件用于上传 csv 文件,然后从 PyCaret 调用本机 predict_model() 函数来生成预测,使用 streamlit 的 write()函数显示这些预测。

app.py —代码片段第 3 部分
测试应用程序 在 AWS Fargate 上部署应用程序之前的最后一步是在本地测试应用程序。打开 Anaconda 提示符,导航到您的项目文件夹并执行以下代码:
**streamlit run app.py**

简化应用测试—在线预测
👉任务 3 —创建 Dockerfile 文件
为了将我们的应用程序进行容器化部署,我们需要一个 docker 映像,它在运行时成为一个容器。使用 docker 文件创建 docker 映像。Dockerfile 只是一个包含一组指令的文件。该项目的 docker 文件如下所示:
这个 Dockerfile 文件的最后一部分(从第 23 行开始)是特定于 Streamlit 的。Dockerfile 区分大小写,必须与其他项目文件位于项目文件夹中。
👉任务 4–在 AWS Fargate 上部署:
按照以下 9 个简单步骤在 AWS Fargate 上部署应用程序:
👉步骤 1 —安装 Docker 工具箱(适用于 Windows 10 家庭版)
为了在本地构建 docker 映像,您需要在您的计算机上安装 Docker。如果您使用的是 64 位 Windows 10:Pro、Enterprise 或 Education (Build 15063 或更高版本),您可以从 DockerHub 下载 Docker Desktop。
但是,如果你使用的是 Windows 10 Home,你需要从 Dockers GitHub 页面安装旧版 Docker 工具箱的最新版本(v19.03.1)。

https://github.com/docker/toolbox/releases
下载并运行 DockerToolbox-19.03.1.exe 文件。****
检查安装是否成功的最简单方法是打开命令提示符并键入“docker”。它应该打印帮助菜单。

Anaconda 提示检查 docker
👉步骤 2 —在弹性容器注册中心(ECR)中创建一个存储库
(a)登录您的 AWS 控制台并搜索弹性容器注册表:

AWS 控制台
(b)创建一个新的存储库:

在 Amazon 弹性容器注册表上创建新的存储库

创建存储库
点击“创建存储库”。
(c)点击“查看推送命令”:

pycaret-streamlit-aws 存储库的推送命令
👉步骤 3—执行推送命令
使用 Anaconda 提示符导航到您的项目文件夹,并执行您在上一步中复制的命令。在执行这些命令之前,您必须位于 docker 文件和其余代码所在的文件夹中。
这些命令用于构建 docker 映像,然后将其上传到 AWS ECR。
👉步骤 4-检查您上传的图像
单击您创建的存储库,您将看到上一步中上传的图像的图像 URI。复制图像 URI(这将需要在下面的步骤 6)。

👉步骤 5 —创建和配置集群
(a)点击左侧菜单上的“集群”:

创建集群—步骤 1
(b)选择“仅联网”并点击下一步:

选择仅网络模板
(c)配置集群(输入集群名称)并点击创建:

配置集群
点击“创建”。
(d)集群创建:

集群已创建
👉步骤 6 —创建新的任务定义
在 Amazon ECS 中运行 Docker 容器需要一个任务定义。您可以在任务定义中指定的一些参数包括:Docker 图像,用于您的任务中的每个容器。每个任务或任务中的每个容器使用多少 CPU 和内存。
(a)点击“创建新任务定义”:

创建新的任务定义
(b)选择“FARGATE”作为发射类型:

选择启动类型兼容性
(c)详细填写:

配置任务和容器定义(第 1 部分)

配置任务和容器定义(第 2 部分)
(d)点击“添加容器”并填写详细信息:

在任务定义中添加容器
点击右下角的“创建任务”。

👉步骤 7-执行任务定义
在最后一步中,我们创建了一个启动容器的任务。现在我们将通过点击动作下的“运行任务”来执行任务。

(a)点击“切换到发射类型”将类型切换到 Fargate:

(b)从下拉菜单中选择 VPC 和子网:

点击右下角的“运行任务”。
👉步骤 8-从网络设置中允许入站端口 8501
在我们看到我们的应用程序在公共 IP 地址上运行之前,最后一步是通过创建一个新规则来允许端口 8501(由 streamlit 使用)。为此,请遵循以下步骤:
(a)点击任务

(b)点击 ENI Id:

(c)点击安全组

(d)向下滚动并点击“编辑入站规则”

(e)添加端口 8501 的自定义 TCP 规则

👉恭喜你!您已经在 AWS Fargate 上发布了您的无服务器应用程序。使用带有端口 8501 的公共 IP 地址访问应用程序。

在 99.79.189.46:8501 发布的应用程序
****注意:在这篇文章发表时,该应用程序将从公共地址中删除,以限制资源消耗。
Google Kubernetes 部署的 GitHub 知识库链接
PyCaret 2.0.0 来了!
我们收到了来自社区的大力支持和反馈。我们正在积极改进 PyCaret,并准备我们的下一个版本。 PyCaret 2.0.0 会更大更好。如果您想分享您的反馈并帮助我们进一步改进,您可以在网站上填写此表格或者在我们的 GitHub 或 LinkedIn 页面上发表评论。
关注我们的 LinkedIn 并订阅我们的 YouTube 频道,了解更多关于 PyCaret 的信息。
想了解某个特定模块?
从第一个版本 1.0.0 开始,PyCaret 有以下模块可供使用。点击下面的链接,查看 Python 中的文档和工作示例。
另请参见:
笔记本中的 PyCaret 入门教程:
你愿意投稿吗?
PyCaret 是一个开源项目。欢迎每个人都来投稿。如果您愿意投稿,请随时关注未决问题。dev-1.0.1 分支上的单元测试接受拉请求。
如果你喜欢 PyCaret,请给我们 GitHub 回购的⭐️。
中等:【https://medium.com/@moez_62905/】T42
领英:https://www.linkedin.com/in/profile-moez/
推特:https://twitter.com/moezpycaretorg1
在 Heroku 上部署 Python Tesseract OCR
如何在 Heroku 上创建 OpenCV + Tesseract OCR 的一步一步的方法(包括截图和代码)

在数据科学领域工作了近五年后,我意识到,我们中的许多人专注于并强调提高算法的准确性,而不是专注于算法在现实生活中的可用性。这通常会导致业务团队和数据科学团队之间期望管理的差异。而且,即使我们创造了一个最复杂的算法,它也没有用,直到有效地部署在核心源。在这篇博客中,我们将学习如何在 Heroku 平台上使用 Python 编写的 Tesseract & OpenCV 部署 OCR。
但是首先,什么是 Heroku?
Heroku 是一个云平台,一种支持多种编程语言的服务。支持 Java、Node.js、Scala、Clojure、Python、PHP、Go 等多种编码语言。它为开发人员提供了跨大多数语言以相似的方式构建、运行和扩展应用程序的功能。
简而言之——我们可以使用 Heroku 将我们的 python 模型部署到生产环境中,这样它可以被任何人使用,并且不依赖于我的桌面或操作系统。
那么我们实际上要做什么?
索引
- 在 Python 上创建一个 Tesseract OCR + OpenCV 代码
- 冻结依赖关系
- 创建 Procfile
- 创建 Aptfile
- 配置 Heroku 帐户
- 把代码复制到 Heroku 服务器上
- 添加构建包和配置文件
- 测试我们的 OCR 应用程序
在 Python 上创建一个 Tesseract OCR + OpenCV 代码
上面提到的代码执行以下操作:
→输入:图像文件(。jpg,。png 等)
→ OpenCV:读取图像
→ Tesseract:对图像执行 OCR&打印出文本
→ FastAPI:将上面的代码包装起来,创建一个可部署的 API
###########pythoncode.py###############import numpy as np
import sys, os
from fastapi import FastAPI, UploadFile, File
from starlette.requests import Request
import io
import cv2
import pytesseract
import re
from pydantic import BaseModeldef read_img(img):
pytesseract.pytesseract.tesseract_cmd = ‘/app/.apt/usr/bin/tesseract’
text = pytesseract.image_to_string(img)
return(text)
app = FastAPI()class ImageType(BaseModel):
url: str[@app](http://twitter.com/app).post(“/predict/”)
def prediction(request: Request,
file: bytes = File(…)):if request.method == “POST”:
image_stream = io.BytesIO(file)
image_stream.seek(0)
file_bytes = np.asarray(bytearray(image_stream.read()), dtype=np.uint8)
frame = cv2.imdecode(file_bytes, cv2.IMREAD_COLOR)
label = read_img(frame)
return label
return “No post request found”
pytesserac . pytesserac . tesserac _ cmd = '/app/。' apt/usr/bin/tesseract' — 这是一行非常重要的代码,不要忘记将它添加到您的代码中。
冻结依赖关系
我们需要将项目相关的依赖项(使用的库)保存在 requirements.txt —快速快捷方式中
pip freeze > requirements.txt
创建 Procfile
Procfile—Heroku 应用包含一个 proc file,指定应用在启动时执行的命令。您可以使用 Procfile 来声明各种过程类型,包括:
- 你的应用程序的 web 服务器
- 多种类型的工作进程
- 单一进程,如时钟
- 部署新版本之前要运行的任务
web: gunicorn -w 4 -k uvicorn.workers.UvicornWorker pythoncode:app

注意,有 没有 扩展名的 Procfile
创建 Aptfile
Heroku 不支持几个 python 包。为了让他们在 Heroku 上工作,我们需要使用构建包。(我们将为宇宙魔方创建一个)。然后通过在应用程序的Aptfile中包含任何 APT 包来使用这个包。当我们部署您的应用程序时,buildpack 会在 dyno 上安装这些包。
出于我们的目的,我们将在 Aptfile 中添加以下内容
tesseract-ocr
tesseract-ocr-eng

注意 Aptfile 有 没有 扩展名
注意:我们将在 Heroku 控制台上添加宇宙魔方build pack
最后,将所有这些文件保存在一个文件夹中

配置 Heroku 帐户
→创建新账户或登录 https://id.heroku.com/login

→创建一个新的应用程序,并为其命名

→您应该已经登录控制台

把代码复制到 Heroku 服务器上
我使用 Heroku CLI(命令行界面)在 Heroku 上推送代码,但是你也可以使用 Github。Github 对代码的推送次数有每日限制,因此我更喜欢使用 CLI。
Heroku 为用户非常清晰地描述了步骤

这将与命令行中的以下内容相关联-
*$ heroku login
$ cd /Users/shirishgupta/Desktop/Heroku/heroku_sample/
$ git init
$ heroku git:remote -a tesseractsample*

*$ git add .
$ git commit -am "make it better"
$ git push heroku master*
**
这表明应用程序已经部署,但我们仍然需要做一件事,才真正使它工作。
添加构建包
→在 Heroku 控制台中,转到设置 →添加以下构建包
*[https://github.com/heroku/heroku-buildpack-apt](https://github.com/heroku/heroku-buildpack-apt)*

→添加宇宙魔方配置文件
*TESSDATA_PREFIX = ./.apt/usr/share/tesseract-ocr/4.00/tessdata*

提示——在 heroku 终端 中输入以下内容,找到宇宙魔方的正确路径
*$ heroku run bash
$ find -iname tessdata*

测试我们的 OCR 应用程序
完成所有步骤后,我们就可以开始测试 OCR 了。前往 heroku consule:
打开 App或输入'https://tesseractsample.herokuapp.com/docs'
输入图像

样本图像
输出图像

输出结果
暂时结束了。有什么想法来改善这一点或希望我尝试任何新的想法?请在评论中给出你的建议。再见。
查看博客- 使用 AWS EC2 实例 部署 Python + Tesseract + OpenCV Fast API
* [## 使用 AWS EC2 实例部署 Python + Tesseract + OpenCV 快速 API
关于如何创建 AWS EC2 实例并为…部署代码的分步方法(包括截图和代码)
towardsdatascience.com](/deploy-python-tesseract-opencv-fast-api-using-aws-ec2-instance-ed3c0e3f2888)*
使用 AWS EC2 实例部署 Python + Tesseract + OpenCV 快速 API
关于如何创建 AWS EC2 实例并为生产目的部署代码的分步方法(包括截图和代码)

作为数据科学家,我们可能有足够的能力构建非常复杂和错综复杂的数据科学算法,但如果说我们大多数人缺乏一项技能,那就是部署。除非部署,否则我们的模型和简单的演示一样好。为了扩展甚至投入生产,它需要作为 API 部署或嵌入到现有系统中。在本文中,我们将学习如何创建一个简单的 OCR 算法,并在 AWS EC2 实例上实时部署它。
首先是基础——什么是宇宙魔方?
除了明显的复仇者联盟的参考,宇宙魔方是各种操作系统的光学字符识别引擎。它是一个自由软件,在 Apache 许可下发布,版本 2.0,自 2006 年以来一直由 Google 赞助开发。2006 年,Tesseract 被认为是当时最精确的开源 OCR 引擎之一。
什么是 EC2 实例?
亚马逊弹性计算云(Amazon EC2 )是一个在云中提供安全、可调整计算能力的 web 服务。它旨在使开发人员更容易进行网络规模的云计算。Amazon EC2 的简单 web 服务接口允许您以最小的摩擦获得和配置容量。
索引
在这篇博客中,我们将更多地关注如何在 AWS EC2 实例上部署 python + tesseract + openCV 模型,而不是实际的准确性。不同的步骤。
1。如何配置一个 AWS 账户
2?安全组
3。SSH 到 EC2 实例
4。安装不同的依赖关系
5。将 Python 代码复制到 EC2
6。在服务器上运行应用程序
配置 AWS 帐户
在 AWS 上创建一个新账户非常容易。
→进入“https://signin.aws.amazon.com/”
→“创建一个新的 AWS 帐户”
→输入必要的信息,如名字、电子邮件地址、密码,就完成了。


您可以免费访问 AWS 账户 12 个月,包括 EC2 instance、Lambda、S3 buckets 和 Sagemaker。有关限额的更多信息,您可以查看:aws.amazon.com/free
创建 EC2 实例
登录后,通过找到控制台部分进入控制台,或在 URL
中输入https://console.aws.amazon.com/→在“查找服务”下输入“EC2”

→“启动新实例”

→在“仅自由层”下选择“ Ubuntu Server 18.04 LTS (HVM),SSD 卷类型”

→实例类型为“t2.micro”。提供 1 个 vCPU 支持和 1gb RAM,足以支持中小型算法。

→您可以将其余功能保留为默认,并启动 EC2 实例。它将要求您创建一个“私有”和“公共”密钥对。这对可以帮助您从笔记本电脑连接到 EC2 实例。因此,创建一个新的一对,并将其安全地保存在某个地方。(我们很快就会需要它)

V oila!您已经创建了您的第一个 EC2 实例。恭喜你!
安全组
只有端口 22 对入站和出站流量开放。这就是我们能够 SSH 到 EC2 实例的原因。(稍后会有更多相关内容)。但是我们希望我们的代码通过 HTTP 类型的端口 80 运行。
要进行此更改,请导航到控制台部分的安全组,并在两个入站规则中添加以下内容
→ Port = 80
→ Type = HTTP

现在可以通过端口 80 访问代码
现在我们已经创建了 EC2 实例,您可以转到 EC2 控制台并检查它是否正在运行。这个屏幕需要几样东西。
1。实例状态 —告诉我们实例是否正在运行。(当你不在做任何事情的时候,记得停止它,否则它会一直消耗空闲层的时间)
2。公共 DNS IPv4
3。IPv4 公共 IP

SSH 到 EC2 实例
接下来是 SSH 进入 EC2 实例。但是首先——什么是 SSH?
SSH 协议(也称为安全 Shell)是一种从一台计算机安全远程登录到另一台计算机的方法。它为强认证提供了几个备选选项,并通过强加密保护了通信的安全性和完整性。这里,SSH 将用于将我们的本地 pc 或笔记本电脑连接到基于 linux 的 EC2 实例
步骤:
→复制 IPv4 公共 IP
→在 MAC 或 Windows 上打开终端
→前往您拥有“密钥对”的目录
→更改 pem 文件的权限,使其可以“读取”
→ssh-I<keypairfile . PEM>Ubuntu @<IP v4 公共 IP >
示例:如果密钥对名称为“Pair.pem”
chmod 400 Pair.pem
ssh -i Pair.pem ubuntu@35.172.128.64
您现在位于 AWS 的 Linux 终端中

安装不同的依赖项
一旦进入 Linux 终端——我们需要下载与我们的 Python 代码相关的所有不同的库。
sudo apt-get update
sudo apt install python3-pip
sudo apt-get install libsm6 libxrender1 libfontconfig1 libice6 nginx gunicorn
pip3 install numpy==1.17.2 fastapi==0.54.1 starlette==0.13.2 opencv-python-headless==4.1.2.30 pytesseract==0.3.3 matplotlib==3.1.1 pydantic==1.4 uvicorn==0.11.3 gunicorn==20.0.4 python-multipart==0.0.5
非常重要 —将宇宙魔方下载到系统中
sudo apt update
sudo apt install tesseract-ocr
sudo apt install libtesseract-dev


以类似的方式下载其他库
将 Python 代码复制到 EC2
首先在实例中创建新目录。这是我们复制 Python 脚本的地方。
mkdir PythonDir
cd PythonDir

现在打开一个新的终端,输入以下内容:
scp -i ~/Pair.pem ~/Desktop/pythoncode.py ubuntu@ec2-35-172-128-64.compute-1.amazonaws.com:~/PythonDir/
上述代码将使用公共 DNS 访问 EC2 实例,并将代码从您的系统复制到 EC2 实例中的目录

不要担心——找到下面的 pythoncode.py
#####pythoncode.py#####import numpy as np
import sys, os
from fastapi import FastAPI, UploadFile, File
from starlette.requests import Request
import io
import cv2
import pytesseract
from pydantic import BaseModeldef read_img(img):
text = pytesseract.image_to_string(img)
return(text)
app = FastAPI()class ImageType(BaseModel):
url: str[@app](http://twitter.com/app).post(“/predict/”)
def prediction(request: Request,
file: bytes = File(…)):if request.method == “POST”:
image_stream = io.BytesIO(file)
image_stream.seek(0)
file_bytes = np.asarray(bytearray(image_stream.read()), dtype=np.uint8)
frame = cv2.imdecode(file_bytes, cv2.IMREAD_COLOR)
label = read_img(frame)
return label
return “No post request found”
接下来——我们需要配置 nginx 服务器。为此,首先从目录中出来,(这里: PythonDir )并创建一个新的配置文件。
cd /etc/nginx/sites-enabled/
sudo vim myApp
配置“myApp”文件。80 是网络服务器应该连接的端口。
server{
listen 80;
server_name 35.172.128.64;
location / {
proxy_pass [http://127.0.0.1:8000](http://127.0.0.1:8000/)
}
}
重新启动 ngnix 终端以反映更改。
sudo service nginx restart
加成:Vim 编辑提示
对于第一次使用 Vim editor 的人来说,它可能会非常令人沮丧。这里有一些快捷方式:

最后—在服务器上运行应用程序
转到应用程序目录并输入以下内容来启动应用程序服务器。
cd PythonDir
gunicorn -w 1 -k uvicorn.workers.UvicornWorker pythoncode:app
瞧,服务器已经启动,我们可以测试应用程序了。在 35.172.128.64/docs 身上测试一下
样本图像

输出

暂时结束了。有什么想法来改善这一点或希望我尝试任何新的想法?请在评论中给出你的建议。
附:如何在 Heroku 上部署 Python+tessera CT+OpenCV API
[## 在 Heroku 上部署 Python Tesseract OCR
如何在 Heroku 上创建 OpenCV + Tesseract OCR 的一步一步的方法(包括截图和代码)
towardsdatascience.com](/deploy-python-tesseract-ocr-on-heroku-bbcc39391a8d)
用舵图在 Kubernetes 上部署 RShiny

如果您想要一个非常健壮的解决方案来部署您的 RShiny 应用程序,AWS 或 EKS 上的托管 Kubernetes 服务是一个很好的选择!就部署容器化服务而言,Kubernetes 目前已经完全控制了 DevOps 和部署领域。
我应该使用 Kubernetes 部署我的 RShiny 应用程序吗?
和所有的事情一样,使用 Kubernetes 有优点也有缺点。
骗局
- Kubernetes 是一个野兽开始。
- 你需要把你的 RShiny 应用和 docker 打包在一起。
赞成的意见
- Kubernetes 得到了一系列提供商的支持,包括 AWS、GCP、Azure、Digital Ocean 等。
- Kubernetes 很复杂,但是伴随着复杂而来的是大批工程师,他们想把复杂的东西抽象成配置文件。因此,如果你坚持“成长的烦恼”,很可能你会得到很多好处,随着时间的推移,事情会变得不那么痛苦。
- Kubernetes 已经被“部署东西的人”社区所接受,这意味着有很多资源可以利用。
- 如果你需要扩展,Kubernetes 是一个很好的方法。
- Kubernetes 有很多优秀的特性,包括一个 JobsApi 和一个 CronJobsApi。这意味着您可以每天下载数据集,这对使用数据集的 RShiny 应用程序来说非常方便。
AWS 特定优势
其中很多可能适用于其他平台,但我在 AWS 上工作,所以我们在这里。
AWS 拥有托管解决方案
- 对于代码(想想 GitHub) — CodeCommit
- 对于私人码头集装箱(想想 dockerhub) — ECR
- 对于 CI/CD (CircleCi、Travis 等)—代码部署
也可以随意混搭。例如,您可以在 DockerHub 上托管您的私有映像,并且仍然部署到 AWS Kubernetes (EKS ),或者您可以使用 Circle 设置您的 CI/CD 管道,并且仍然使用 AWS。
接下来是这样一个事实,AWS 基础设施可以完全脱离人工干预并实现自动化。您不需要,也不应该通过控制台来创建像集群这样复杂的基础设施。相反,你可以使用类似于地形或云形成的工具。这些工具可以自动完成从创建 Kubernetes 集群到部署应用程序的所有工作。
我被卖了!现在怎么办?
首先,你需要一个 RShiny 图片来测试。我真的建议挑选一些非常简单的东西来测试,这样你就可以知道问题是出在你的图像上还是你的设置上。在本教程中,我们将使用摇杆闪亮图像。
您还需要有一个可用的 Kubernetes 集群。
创建您的舵图
我将一步一步地介绍你需要做哪些修改。如果你想跳过这一部分,你可以点击查看舵轮图。
(在安装舵 v3 之后)你要做的第一件事是创建一个舵图表。一点关于舵图!
Helm 使用一种叫做图表的打包格式。图表是描述一组相关 Kubernetes 资源的文件集合。一个图表可以用来部署简单的东西,比如 memcached pod,或者复杂的东西,比如带有 HTTP 服务器、数据库、缓存等的完整 web 应用程序堆栈。图表被创建为布局在特定目录树中的文件,然后它们可以被打包到要部署的版本化档案中。
来自 helm.sh
从这里开始,我们将边做边学,因此打开您的终端并运行:
helm create rshiny-eks
您将看到一个名为 rshiny-eks 的目录。顺便提一下,如果你安装了插件,许多编辑器和 ide 可以识别舵图。我发现它有一定的帮助。
让我们打开rshiny-eks/values.yaml看看吧!
指定图像
您可以通过更改image.repository键来指定图像。默认情况下,图表是用 nginx 创建的。如果您在一个全新的集群上,我强烈建议您按原样部署图表。我总是喜欢在任何新平台上部署 NGINX,因为如果我不能部署 NGINX,我会有更大更可怕的问题。;-)
# rshiny/values.yaml
image:
repository: nginx
pullPolicy: IfNotPresent
让我们改变这个摇杆/闪亮。
# rshiny/values.yaml
image:
repository: rocker/shiny
pullPolicy: IfNotPresent
注意—使用标签
该标签将默认为 Chart.yaml 中的 appVersion。实际上似乎没有人遵循这一点并在values.yaml中添加一个标签。
# rshiny/values.yaml
image:
repository: rocker/shiny
# add in a TAG key
# don't use latest!
tag: 3.6.1
pullPolicy: IfNotPresent
然后打开templates/deployment.yaml,对图像键进行更新。
改变这个-
# templates/deployment.yaml
image: "{{ .Values.image.repository }}:{{ .Chart.AppVersion }}"
收件人:
# templates/deployment.yaml
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
旁注
通常,helm 所做的是查看 appVersion 的【the appVersion 对应于标签。这对于自动部署来说是有问题的,因为无法从命令行对此进行更改。我发现修改舵图更容易。
加入会话属性
RShiny 喜欢无所事事。这只会让你的会话变得粘粘的,这意味着用户不会在体验中被拖来拖去。
打开您的rshiny-eks/templates/deployment.yaml,在 spec 下添加一个 sessionAffinity 键。
# rshiny-eks/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "rshiny-eks.fullname" . }}
labels:
{{- include "rshiny-eks.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
# ADD sessionAffinity HERE
sessionAffinity: ClientIP
更改文件中更靠下的端口:
# rshiny-eks/templates/deployment
# Change containerPort: 80 to containerPort 3838ports:
- name: http
containerPort: 3838
protocol: TCP
关于端口的一个注记
这个设置假设您的 RShiny 应用程序运行在容器的端口 80 上。如果不是,您需要更改rshiny-eks/templates/deployment.yaml中的 containerPort 值。
可选——很好地公开 URL 的依赖项
如果你只是作为测试部署,你不需要这些,因为 AWS 会给你一个公共的 IP 地址,但是如果你需要把你的 Kubernetes 实例映射到一个实际的 URL,你需要修改一些东西。
# Chart.yaml
dependencies:
- name: nginx-ingress
version: 1.27.0
repository: https://kubernetes-charts.storage.googleapis.com
- name: cert-manager
version: v0.12.0
repository: https://charts.jetstack.io
在values.yaml中,删除入口块并用此块代替。
# values.yaml
ingress:
enabled: true
annotations:
kubernetes.io/ingress.class: nginx
# if you need to have https uncomment
# cert-manager.io/cluster-issuer: letsencrypt-production
hosts:
# your real domain
# You will need to get the service url and add it to your DNS panel as an A name record.
# this may take some time to propogate the first time around due to DNS settings.
# Don't freak out!
- host: www.mydomain.com
paths:
- "/"
# Get the service url
# with kubectl get svc -o wide | grep MY_RELEASE_NAME
# Add this to your DNS panel as an A name to get the above to work
- host: lots-o-numbas.aws-region.elb.amazonaws.com
paths:
- "/"
tls: []
# If you're using https you'll need to update this
# - secretName: chart-example-tls
# hosts:
# - chart-example.local
展开你的舵图
开始部署吧!
将所有依赖项安装到 helmchart
您需要在 rshiny-eks 的父目录中运行这个命令。
helm dep up rshiny-eks
这将安装所有依赖项。如果你没有做可选的步骤,你就不会有任何选择,但是下次要记住这一点!
展开舵图
现在,helm 的一个非常方便的特性是你可以通过使用--set标志在命令行上修改values.yaml。我们在这里要做的是用我们的实际标签来设置图像标签。(我就继续保持破纪录吧。使用标签!不这样你会后悔的。)
# helm upgrade --install RELEASE_NAME ./path-on-filesystem
# If you didn't install the optional dependencies use the
# --set service.type=LoadBalancer
helm upgrade --install rshiny-eks ./rshiny-eks \
--set image.tag=$SOME_REAL_TAG_HERE \
--set service.type=LoadBalancer
# If you installed the optional dependencies you don't need to specify the service.type
helm upgrade --install rshiny-eks ./rshiny-eks \
--set image.tag=$SOME_REAL_TAG_HERE
获取服务地址
一旦你做到了这一点,你就可以获得该服务的 IP 地址,并把它放入你的浏览器中。
kubectl get svc -o wide | grep rshiny-eks | grep LoadBalancer
这会让你看到这样的东西-
rshiny-eks-nginx-ingress-controller LoadBalancer 172.20.108.106 lots-o-string.aws-region.elb.amazonaws.com 80:32168/TCP 1d app=nginx-ingress,component=controller,release=rshiny-eks
打开你的浏览器,输入lots-o-string.aws-region.elb.amazonaws.com!启动服务可能需要几分钟时间。
解决纷争
得到一个壳
我最喜欢 DevOps 的一点是,我们有所有这些超级奇妙的方式来部署几乎所有的东西。然后我们有后门,本质上是“好了闭嘴,给我一个壳”。Kubernetes 在这里也不例外。我们可以得到一个外壳,复制文件,转发端口。哈!
#If you used a different release name grep for that
kubectl get pods |grep rshiny
获取 pod 的名称,一旦有了这个名称,就可以直接在容器上获取外壳。
kubectl exec -it name-of-pod bash
查看日志
您还可以查看日志,这是抛出到 stdout/stderr 的所有内容。
kubectl logs name-of-pod
描述吊舱
如果你的容器失败了,你想知道为什么要描述这个容器。
kubectl describe pod name-of-pod
总结性的新闻报导
原来如此!一旦您的 Kubernetes 集群启动并运行,您就可以使用 helm 部署您的 RShiny 应用程序并发布这些精彩内容!
取得联系
如果你有任何问题,意见,或想要求一个教程,请与我联系在 jillian@dabbleofdevops.com。
使用摇杆/闪亮的 Docker 图像部署 RShiny

如果你用 docker 部署 RShiny,你可以滚动你自己的镜像,或者你可以使用摇杆 Dockerhub 镜像。
您选择哪种解决方案将取决于您自己的需求。通常,我使用大量的生物信息学和/或数据科学软件包,在我看来,没有什么能真正击败康达生态系统。另一方面,拥有一个已经安装了 RShiny 的映像真的很棒!我也很喜欢rocker/shiny图像的配置方式。你把你的文件放到一个目录中,只要你有你需要的包,你闪亮的应用程序就会直接启动!
使用摇杆/闪亮图像部署简单的闪亮应用程序
这是我们通常使用的闪亮应用程序,大部分是从闪亮文档中偷来的。;-)
#!/usr/bin/env Rscript
# This example comes from the r-shiny examples github repo.
# https://github.com/rstudio/shiny-examples/blob/master/001-hello/app.R
library(shiny)
# Define UI for app that draws a histogram ----
ui <- fluidPage(
# App title ----
titlePanel("Hello Shiny!"),
# Sidebar layout with input and output definitions ----
sidebarLayout(
# Sidebar panel for inputs ----
sidebarPanel(
# Input: Slider for the number of bins ----
sliderInput(inputId = "bins",
label = "Number of bins:",
min = 1,
max = 50,
value = 30)
),
# Main panel for displaying outputs ----
mainPanel(
# Output: Histogram ----
plotOutput(outputId = "distPlot")
)
)
)
# Define server logic required to draw a histogram ----
server <- function(input, output) {
# Histogram of the Old Faithful Geyser Data ----
# with requested number of bins
# This expression that generates a histogram is wrapped in a call
# to renderPlot to indicate that:
#
# 1\. It is "reactive" and therefore should be automatically
# re-executed when inputs (input$bins) change
# 2\. Its output type is a plot
output$distPlot <- renderPlot({
x <- faithful$waiting
bins <- seq(min(x), max(x), length.out = input$bins + 1)
hist(x, breaks = bins, col = "#75AADB", border = "white",
xlab = "Waiting time to next eruption (in mins)",
main = "Histogram of waiting times")
})
}
# If you want to automatically reload the app when your codebase changes - should be turned off in production
options(shiny.autoreload = TRUE)
options(shiny.host = '0.0.0.0')
options(shiny.port = 8080)
# Create Shiny app ----
shinyApp(ui = ui, server = server)
制作一个名为shiny-app的目录,将上面的app.R放进去。
提供您的 RShiny 应用程序
现在你有了一个应用程序,你需要知道两个基本的 docker 概念。如何公开端口以及如何挂载卷。
docker run --rm \
-v "$(pwd)/shiny-app":/srv/shiny-server \
-p 3838:3838
您应该会看到一条关于您的 RShiny 应用程序正在运行的消息。在localhost:3838打开浏览器,您应该会看到以下应用程序。

现在,这是摇滚形象非常简洁的地方。由于我们将应用程序直接放入/srv/shiny-server中,它会立即启动。要知道为什么会这样,让我们看看 docker 文件中的魔法。
深入摇滚/闪亮的形象
FROM rocker/r-ver:3.6.3
RUN apt-get update && apt-get install -y \
sudo \
gdebi-core \
pandoc \
pandoc-citeproc \
libcurl4-gnutls-dev \
libcairo2-dev \
libxt-dev \
xtail \
wget
# Download and install shiny server
RUN wget --no-verbose https://download3.rstudio.org/ubuntu-14.04/x86_64/VERSION -O "version.txt" && \
VERSION=$(cat version.txt) && \
wget --no-verbose "https://download3.rstudio.org/ubuntu-14.04/x86_64/shiny-server-$VERSION-amd64.deb" -O ss-latest.deb && \
gdebi -n ss-latest.deb && \
rm -f version.txt ss-latest.deb && \
. /etc/environment && \
R -e "install.packages(c('shiny', 'rmarkdown'), repos='$MRAN')" && \
cp -R /usr/local/lib/R/site-library/shiny/examples/* /srv/shiny-server/ && \
chown shiny:shiny /var/lib/shiny-server
EXPOSE 3838
COPY shiny-server.sh /usr/bin/shiny-server.sh
CMD ["/usr/bin/shiny-server.sh"]
我们在这里可以看到,rocker/shiny映像使用了一个 base R Docker 映像,然后安装了闪亮的包。它还将一个shiny-server.sh文件从构建目录复制到映像。shiny-server.sh正被用作启动CMD。(记住,RUN在构建期间执行命令,而CMD在使用docker run运行容器时执行命令。让我们研究一下shiny-server.sh启动文件。
#!/bin/sh
# Make sure the directory for individual app logs exists
mkdir -p /var/log/shiny-server
chown shiny.shiny /var/log/shiny-server
if [ "$APPLICATION_LOGS_TO_STDOUT" != "false" ];
then
# push the "real" application logs to stdout with xtail in detached mode
exec xtail /var/log/shiny-server/ &
fi
# start shiny server
exec shiny-server 2>&1
我们在这里看到的是,shiny-server.sh脚本正在执行一个命令,该命令带有一个选项,可以选择是否将日志推送到 stdout。这是你在 docker 容器中经常看到的东西。在构建时,您通常希望看到所有的日志信息,但对于生产系统,您通常希望将日志推送到文件或日志基础设施,如 logstash 或 elasticsearch。
闪亮服务器在做什么?
我总是喜欢深入容器本身,看看发生了什么,尤其是在启动命令和 web 服务器方面。
要在 docker 容器中挖掘,提供it标志(interactive 和 tty)并运行 bash 命令。这会让你直接变成一个空壳。
退出先前的 docker 运行命令或不提供端口。否则,此命令将失败,并显示一个关于端口已被监听的错误。
docker run -it --rm \
-p 3838:3838 \
-v "$(pwd)/shiny-app":/srv/shiny-server \
rocker/shiny bash
现在,如果我运行shiny-server --help,它会启动一个节点服务器,并告诉你它正在查看哪个配置文件。作为一个永远好奇的人,我想知道更多,所以我去看了一下 Github 回购。据我所知,请不要因为我不太懂 javascript 而坚持这样做,但它所做的是读取您的配置文件,并在/srv/shinyapps中为每个文件夹创建一个单独的 web 服务器,以及与您的文件夹名称对应的漂亮路径,这就是您如何获得漂亮的拖放和快速的闪亮效果!
创建一个定制的摇滚/闪亮的形象
现在,如果您想安装任何额外的系统软件包,您将需要创建一个新的映像。
我也喜欢将我的应用程序放在 docker 映像中,而不是出于生产目的将其安装在文件系统上,所以我们在这里也将这样做。
您的目录结构应该如下所示:
Dockerfile
shiny-app/
app-R
这里有一个样本 Dockerfile 文件。
# Dockerfile
FROM rocker/shiny:3.6.3
RUN apt-get update && apt-get install -y \
things-i-want-to-install
COPY shiny-app/app.R /srv/shiny-app/app.R
一旦你有了你的Dockerfile设置,你只需要建立你的形象。
docker build -t my-rshiny-app .
除了,你知道,有一个更好的名字和更具描述性的名字,绝对没有东西或东西在那里。
包裹
就是这样!你的 docker 图像将从 rocker/shiny 图像继承启动命令,所以需要在这里指定它。只需添加您的附加包,复制您的文件,并繁荣!
最初发表于https://www.dabbleofdevops.com。
在中部署 Sci-kit 学习模型。网络核心应用
使用 ONNX 和 ONNX 运行时来跨编程语言和技术栈共享单个模型。
对于试图将 ML 模型交付到产品的组织来说,一个常见的痛点是数据科学家和应用程序开发人员使用的工具和技术之间的差异。数据科学家最有可能使用 Python,使用 Sci-kit Learn、Tensorflow 或 PyTorch 等机器学习框架来构建和训练他们的模型,而应用程序开发人员通常使用 Java、C#或 JavaScript 等编程语言来构建企业应用程序,利用 Spring 或 ASP.NET Core 等流行的 Web 应用程序框架。
有许多方法可以弥补这个差距。几种最常见的方法是:
- 让数据科学家将模型的训练参数发送给应用程序开发人员,然后应用程序开发人员必须使用将使用模型的 web 应用程序的语言重写模型。
- 使用 Python web 框架(如 Flask 或 Django)开发一套单独的 web 应用程序来托管部署的模型。
这两个都不理想。对于第一种方法,手动重写步骤导致更慢的周期时间、逻辑的重复和人为错误概率的增加。第二种方法虽然比第一种更有吸引力,但仍然不太好,因为它妨碍了在所有应用程序之间共享开发模式、库和核心逻辑(如安全性、日志记录或公共集成逻辑)的能力。
在本文中,我们将探讨一种更好的方法,使用 ONNX 模型格式和 ONNX 运行时来弥合数据科学家和应用程序开发人员之间的技术差距。具体来说,我们将展示如何使用 Sci-kit learning 构建和训练一个模型,然后使用同一个模型在. NET 核心 Web API 中执行实时推理。

集成 ML 模型和应用程序开发生命周期。(图片由作者提供)
ONNX 是什么?
开放神经网络交换(ONNX)是一种开放的 ML 模型格式,类似于常用于保存和加载 Sci-kit 学习模型的 Pickle 格式,或 Tensorflow 模型的 SavedModel 格式。然而,ONNX 是框架不可知的,这意味着您可以从任何流行的机器学习框架中生成 ONNX 格式的模型。
除了 ONNX 模型格式,我们还将使用 ONNX 运行时,这是一个开源的运行时,允许我们在我们的。NET 核心应用程序。我们将使用 C # APIs,但是 ONNX 运行时也支持其他几种语言的 API,包括 Python、Java 和 Javascript。
你可以在这里阅读更多关于 ONNX 项目和支持的框架:https://onnx.ai/
你可以在这里了解更多关于如何在不同的语言和平台上使用 ONNX 运行时:https://microsoft.github.io/onnxruntime/
构建 ONNX 模型
首先,我们将使用加州住房数据集构建和训练一个 Sci-kit 学习模型。这里没有什么特别的,只是一个 GradientBoostingRegressor,它被训练来预测给定几个数据点(如中值收入、平均卧室数量等)的住宅价格。
我们需要安装 sklearn-onnx 库,这将允许我们将 sklearn 模型转换成 onnx 格式:
pip install skl2onnx
然后我们将使用convert_sklearn()方法进行转换:
initial_types参数定义了模型输入的维度和数据类型。这个模型有 8 个 float 类型的输入。输入维度[None,8]中的None表示未知的批量。
注意:将 Scikit-learn 模型转换为 ONNX 格式有一些限制。你可以在这里找到关于这些限制和 sklearn-onnx 库的细节:http://onnx.ai/sklearn-onnx/
使用 ONNX 模型执行推理
现在是 ASP.NET 核心应用程序,它将使用我们的 ONNX 模型,并将其作为 REST API 端点公开,支持作为服务的实时推理。我们将使用dotnet命令行工具创建一个空的 ASP.NET 核心 Web API:
dotnet new webapi
接下来,我们将安装微软。ML.OnnxRuntime NuGet 包,它将允许我们在。NET 核心应用程序:
dotnet add package Microsoft.ML.OnnxRuntime
在我们对模型评分之前,我们需要启动一个InferenceSession并将模型对象加载到内存中。在 Startup.cs 中的ConfigureServices方法中添加下面一行:
如果您不熟悉 ASP.NET 核心或依赖注入,上面一行只是创建一个类型为InferenceSession的单例实例,并将其添加到应用程序的服务容器中。这意味着推理会话将在应用程序启动时只创建一次,并且同一个会话将被对我们稍后将创建的推理 API 端点的后续调用重用。
您可以在这里找到关于服务容器、服务生命周期和依赖注入的更深入的信息:ASP.NET 核心中的依赖注入
注意,在上面的代码中,我们加载了。本地文件系统中的 onnx 模型文件。虽然这对于我们的示例来说很好,但是在生产应用程序中,为了将 ML 模型的版本控制从应用程序的版本控制中分离出来,您可能最好从外部模型存储库/注册中心(比如 MLFlow)下载模型对象。
现在,应用程序知道如何将 ONNX 模型加载到内存中,我们可以创建一个 API 控制器类,在 ASP.NET 核心应用程序中,它只是一个定义将由我们的应用程序公开的 API 端点的类。
下面是推理端点的控制器类:
关于上述类的几点注意事项:
[Route("/score")]属性指定我们可以通过路由/分数向该控制器的端点发出请求- 注意,该类的构造函数接受一个类型为
InferenceSession的对象作为参数。当应用程序启动时,它将创建我们的控制器类的一个实例,传入我们之前在 Startup.cs 中定义的InferenceSession的单例实例。 - 当我们调用
_session.Run()时,我们的模型对输入进行实际评分 - 类
HousingData和Prediction是简单的数据类,分别用于表示请求和响应主体。我们将在下面定义这两者。
这里是代表对我们端点的传入 API 请求的 JSON 主体的HousingData类。除了对象的属性,我们还定义了一个AsTensor()方法,将HousingData对象转换成一个Tensor<float>类型的对象,这样我们就可以将它传递给 ONNX 模型:
这里是定义响应结构的Prediction类,我们的 API 端点将使用该响应进行回复:
测试 API
仅此而已。我们现在准备运行我们的 ASP.NET 核心 Web API,并测试我们的推理端点。使用项目根目录下的dotnet run命令启动应用程序。您应该在输出中看到这样一行,指示应用程序正在侦听哪个端口:
Now listening on: [http://[::]:80](http://[::]:80)
现在应用程序已经启动并运行了,您可以使用您最喜欢的 API 请求工具(我的工具是 Postman )向它发送这样的请求:

通过 Postman 向/score 端点发送请求。(图片由作者提供)
现在你知道了!我们现在能够通过 API 请求从我们的模型中实时获得预测。尝试调整输入值,看看预测值如何变化。
结论
感谢阅读。在本文中,我们看到了如何使用 ONNX 模型格式和 ONNX 运行时来简化将 ML 模型集成到生产应用程序中的过程。虽然显示的示例是针对 Scikit-Learn 和 C#的,但 ONNX 和 ONNX 运行时的灵活性允许我们混合和匹配各种机器学习框架和技术堆栈(例如 Scikit-learn & Javascript、Tensorflow & Java 等)。
示例代码
您可以在这里找到包含所有用于训练和推理的示例代码的存储库:【https://github.com/gnovack/sklearn-dotnet
参考
- 【http://onnx.ai/sklearn-onnx/tutorial.html
- https://github . com/Microsoft/onnx runtime/blob/master/docs/cs harp _ API . MD #入门
欢迎在下面留下任何问题或评论。谢谢!
使用 Python、Flask 和 Docker 在 Kubernetes 上部署 Tensorflow 对象检测 API
在本文中,我们将使用 Flask 提供 Tensorflow 对象检测 API,对应用程序进行 Dockerize,并使用 Google Kubernetes 引擎将其部署在 Kubernetes 上。

介绍
TensorFlow 对象检测 API 是一个基于 TensorFlow 构建的开源框架,可以轻松构建、训练和部署对象检测模型。本文演示了如何使用 Flask 提供 Tensorflow 对象检测 API,如何使用 Google Kubernetes 引擎将应用程序 Dockerize 并部署到 Kubernetes 上。
部署后,您可以将 API 合并到您的自定义应用程序中,无论是移动应用程序还是 web 应用程序,都可以满足您的需求。
快速大纲
这些是我们将要采取的步骤:
- 设置 Tensorflow 对象检测 API
- 使用烧瓶供应 API
- 使用 Docker 将应用程序容器化
- 在 Kubernetes 上部署容器化应用程序
注意:我们不会深入讨论 Tensorflow 对象检测 API,因为这不是本文的重点。有兴趣可以去官方回购看看。如果你熟悉它,那会很有帮助。我们也不会经历设置环境的整个过程,因为我们可以使用 Docker 来简化它。不过,有兴趣可以参考这篇惊艳的文章。
入门指南
将我的存储库克隆到工作区中。我们将在整篇文章中使用这些代码。
git clone [https://github.com/wingedrasengan927/Tensorflow-2-Object-Detection-API-Flask-Application.git](https://github.com/wingedrasengan927/Tensorflow-2-Object-Detection-API-Flask-Application.git)
建立码头工人形象

码头工人
如果你还没有安装 Docker 在你的系统中。Docker 容器基本上打包了代码及其所有依赖项,因此应用程序可以在任何环境中快速可靠地运行。它包括运行应用程序所需的一切,并将依赖项与主环境隔离开来。
在您克隆的 repo 中,您会发现一个 Dockerfile 文件。Dockerfiles 描述了构建映像的不同过程,还可以包含一些元数据,描述如何基于该映像运行容器。我们的 docker 文件如下所示:
要从 Dockerfile 文件构建映像,请在 repo 内部运行以下命令:
docker build -t tf-od-api:latest .
-t 表示您赋予 Docker 图像的标签。这个建筑需要很多时间。如果你看到这样的东西:
Successfully built 64edf7b4c21f
Successfully tagged tf-od-api:latest
这意味着映像已成功构建。现在让我们从图像中运行一个容器。运行以下命令:
docker run -d -p 5000:5000 tf-od-api:latest
这确保了我们与运行中的容器分离,并且容器暴露在端口 5000 上。
现在让我们测试我们的应用程序。这可以通过运行脚本 client.py 来完成,该脚本位于 repo 中,带有必要的参数(您需要在工作区中安装 opencv 和 numpy 来运行该脚本):
python client.py --address [http://127.0.0.1:5000](http://127.0.0.1:5000) --image_path images/test_image.jpg --output_dir outputs/
如果您看到类似这样的输出,那么我们的应用程序正在按预期工作:
Detections are: [{‘person’: ‘79%’}, {‘chair’: ‘34%’}]
the image size is: size=1920x1281
the image is being written in outputs/
好吧…刚刚发生了什么!?
当我们从 docker 文件构建映像时,我们设置运行 Tensorflow 对象检测 API 所需的环境,这包括克隆存储库、编译协议缓冲区、设置环境变量、下载模型,当我们准备就绪时,我们克隆存储库,其中包含为 Flask 应用程序提供服务的代码,我们在端口 5000 上启动应用程序,并确保在运行容器时公开该端口。
这是应用程序代码:
您可以在此文件中更改参数、预训练模型。确保您的更改反映在 docker 文件中,您可以使用 docker 文件中的 COPY 将已更改的 repo 从您的本地环境复制到 docker 文件中,而不是克隆它。
在客户端,我们发送到端点的请求包含图像数据。我们可以使用 API 测试工具如邮差或 curl 命令来发送数据。我们得到的响应包含图像中的检测、图像大小和带有边界框覆盖的图像数据。我们把这个图像写到输出目录
注:
- 如果您已经设置了包括将所需路径添加到 PATH 环境变量的环境,则可以在本地系统上运行该应用程序。
- 如果 Docker 容器没有按预期运行,您可以通过运行 docker logs container_id 来检查日志,以检查哪里出错了
- 这是 API 的基础版本,您可以根据需要对其进行定制。
将图像推送到 Google 容器注册表

谷歌容器注册
在继续之前,您需要确保您在谷歌云平台上有一个工作帐户,安装了云 SDK ,并且创建了一个项目。
现在,我们在本地环境中有映像,要进行部署,我们需要将它托管在云上。在本节中,我们将把 Docker 图像推送到 Google 容器注册表。
我们开始吧
首先我们需要配置 Docker 来使用 gcloud 作为凭证助手。为此,请运行命令:
gcloud auth configure-docker
要将任何本地图像推送到容器注册中心,我们需要首先用注册中心名称标记它,然后推图像。要进行标记,请运行以下命令:
docker tag tf-od-api gcr.io/${PROJECT_ID}/tf-od-api
gcr.io 是主机名,它指定了存储映像的位置或存储库。
要推送标记的图像,请运行:
docker push gcr.io/${PROJECT_ID}/tf-od-api
要检查图像是否已被推送,请列出图像。为此,请运行:
gcloud container images list
如果成功推送,您应该会在输出中看到图像名称。
NAME
gcr.io/my-project-21212/tf-od-api
在 Kubernetes 部署

介绍
您肯定听说过 Kubernetes,它已经成为部署和管理容器化应用程序的标准。在本节中,我们将使用 Google Kubernetes 引擎在 Kubernetes 上部署我们的应用。
Kubernetes 是一个容器编排系统。它有助于在集群上部署和管理容器化的应用程序。Kubernetes 集群由一个主集群和节点组成,主集群负责管理集群,节点是运行应用程序的工作机。
我们开始吧
首先,让我们安装 kubectl 。 kubectl 用于与 Kubernetes 通信。要安装 kubectl ,运行:
gcloud components install kubectl
创建集群
让我们创建一个名为 object-detection 的双节点集群。如前所述,在 Kubernetes 中,节点是一个工作机,它可以是虚拟机,也可以是物理机,这取决于集群。要创建群集,请运行以下命令:
gcloud container clusters create object-detection --num-nodes=2**OUTPUT**
NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS
object-detection us-central1-a 1.14.10-gke.27 35.193.127.147 n1-standard-1 1.14.10-gke.27 2 RUNNING
创建集群后,它在 G oogle 计算引擎上启动两个 VM 实例,它们是集群的节点工作器。要查看它们,请运行以下命令:
gcloud compute instances list**OUTPUT**
NAME ZONE MACHINE_TYPE PREEMPTIBLE INTERNAL_IP EXTERNAL_IP STATUS
gke-object-detection-default-pool-cd7fa3ff-3zd6 us-central1-a n1-standard-1 10.128.0.4 34.67.58.20 RUNNING
gke-object-detection-default-pool-cd7fa3ff-z2hw us-central1-a n1-standard-1 10.128.0.5 35.222.93.20 RUNNING
部署
现在我们已经有了一个集群,让我们部署我们的容器化应用程序。为此,我们必须创建一个 Kubernetes 部署。该部署指导 Kubernetes 如何创建和更新我们的应用程序实例。当我们创建一个部署时,我们必须为我们的应用程序指定容器映像和部署的名称。运行以下命令创建部署:
kubectl create deployment object-detection --image=gcr.io/${PROJECT_ID}/tf-od-api
当我们创建部署时,Kubernetes 会创建 Pods 来托管应用程序实例。一个 Pod 代表一组一个或多个应用程序容器。一个 Pod 在一个节点上运行。要查看部署创建的 pod,请运行:
kubectl get pods**OUTPUT**
NAME READY STATUS RESTARTS AGE
object-detection-7c997cbfd8-5nz4j 1/1 Running 0 2m11s
向 internet 公开应用程序
我们必须允许从互联网到应用程序的流量,这样我们才能访问它。为此,请运行:
kubectl expose deployment object-detection --type=LoadBalancer --port 80 --target-port 5000
端口标志指定负载均衡器上配置的端口号,目标端口标志指定 tf-od-api 容器监听的端口号。
要获取外部 IP,请运行以下命令:
kubectl get service**OUTPUT**
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.51.240.1 <none> 443/TCP 30m
object-detection LoadBalancer 10.51.245.79 35.193.230.83 80:31667/TCP 4m57s
现在让我们检查一下我们的应用程序是否是可访问的。为此,我们将运行相同的 client.py ,但我们必须给出外部 IP 作为地址参数:
python client.py --address http://35.193.230.83/(my external IP) --image_path images/input_image.jpg --output_dir outputs/**OUTPUT**
Detections are: [{‘person’: ‘79%’}, {‘chair’: ‘34%’}]
the image size is: size=1920x1281
the image is being written in outputs/
如果您看到类似于我们之前运行时的输出,那么恭喜您!您已经在 Kubernetes 上成功部署了一个容器化的 Tensorflow 对象检测 API 应用程序。
清理
完成后不要忘记删除集群,因为这可能会产生费用。为此,请运行以下命令删除该服务:
kubectl delete service object-detection
要删除群集及其资源,请运行:
gcloud container clusters delete object-detection**OUTPUT**
Deleting cluster object-detection...done.
Deleted [[https://container.googleapis.com/v1/projects/temp-kubernetes/zones/us-central1-a/clusters/object-detection](https://container.googleapis.com/v1/projects/temp-kubernetes/zones/us-central1-a/clusters/object-detection)].
结论
在本文中,我们学习了如何使用 Flask 服务 Tensorflow 对象检测 API,使用 Docker 封装应用程序,以及在 Kubernetes 上部署应用程序。希望对你有所帮助。
如果您有任何反馈或希望取得联系,请在ms.neerajkrishna@gmail.com给我留言
使用 Github 操作部署到 Google 云运行
实践教程
一个 CI/CD 解决方案,可通过操作和云运行扩展到零

图片由作者
背景
当涉及到两个方面时,我在业余时间从事的项目和我与团队一起开发解决方案的时间有很多重叠。由于我自己开发时的空闲时间有限,以及我们团队的规模较小,我总是倾向于简单的解决方案,并且无需任何操作工作就可以缩减到零。
因此,当寻找一个 CI/CD 解决方案来支持我最喜欢的产品之一时,我想看看 Github Actions,这是谷歌云平台(GCP)提供的一款名为 Cloud Run 的产品。Github Actions 在这方面与 Cloud Run 非常相似,因为您只需为您使用的内容付费。
这些服务不仅得到了全面管理,并且可以缩减到零,而且它们还有一个额外的好处,我喜欢在自己进行试验时加以利用,那就是这两种服务都有一个免费层🙌
经过一点努力,我能够让这两个服务很好地配合。由于 GCP 在角色背后不可预测的行为,我在配置角色和权限时遇到了很多困难,但谢天谢地,我写下了我为获得可行的解决方案而经历的每一步,这样你就不需要花费数小时试错来完成 Github Actions 和 Google Cloud Run 之间的集成。
入门指南
我将带您浏览的例子是一个简单的 Flask 服务器,它通过 Github Actions 部署到 Google Cloud Run。在我介绍这个例子之前,我已经提供了一些概念,以及在本地运行这个例子所需的一些需求。
概念
Github Actions—Github 的自动化解决方案,允许您提供 yaml 配置来自动化 CI/CD 操作等任务。
Google Cloud Run——Google 提供的一个托管的无服务器平台,规模可以缩小到零。用户只需要为要运行的容器提供一个 docker 文件。
Flask—Python 开发者常用的 Python 微 web 框架。
要求
在这个例子中,我将带你经历你需要两样东西来本地运行它:Python 3.9 和 Flask。和我所有的例子一样,如果你通过 pip 在虚拟环境中安装你的需求,你的生活会少很多痛苦。如果你熟悉这两者,我也鼓励你使用 virtualenvwrapper ,它有一些非常好的扩展,可以进一步简化你的开发环境的工作流程。
步骤 1:启用谷歌云运行
如果你跳过这一步,你实际上会看到下面的错误,这实际上是非常有用的。

否则,只需点击下面的链接,并启用 API。
Google 云平台让您可以在同一基础设施上构建、部署和扩展应用程序、网站和服务…
console.developers.google.com](https://console.developers.google.com/apis/library/run.googleapis.com)
您应该会看到包含以下内容的屏幕。确保您已经选择了要部署到的项目,您应该会在左侧的导航栏上看到该项目。

步骤 2:设置谷歌认证
在这一步中,我们需要创建一个服务帐户,该帐户拥有从 Github Actions 部署到 Cloud Run 所需的一组权限。因此,导航到您的谷歌项目,并创建这个服务帐户。
创建服务帐户后,您需要选择以下角色。我尝试了许多不同的方法来删除非常宽松的项目查看者角色,但在撰写本文时,您的服务帐户将需要此角色,否则即使成功部署到 Cloud Run,部署也会在 Github 中失败。

剩下的就是为您的服务帐户导出一个凭证,您需要将它放在手边,因为我们稍后将使用它来提供一个凭证,该凭证将允许 Github 操作将我们的 web 服务器部署到 Cloud Run。
步骤 3:创建或克隆要部署的示例代码
现在我们可以开始这一步了,但是由于代码并不是我们过程中有价值的部分,我计划更多地关注 Google Cloud Run 和 Github Actions 之间的集成。
对于这一步,您可以做两件事之一。从头开始创建您自己的 Github 资源库,或者克隆下面的资源库。
[## Dylan Roy/谷歌-云-运行-github-操作
一个带有 Github 动作的示例项目,用于部署到 Google Cloud Run。为了自己部署这个项目…
github.com](https://github.com/dylanroy/google-cloud-run-github-actions)
完成该注释或创建简单的 hello world 端点后。下面的例子来自我们的 Github repo,只是提供了一个简单的例子,让我们看看我们的集成是否成功。
在本地运行项目所需的需求,以及我们将在 Docker 容器中启动的需求如下。
Flask
gunicorn
一个requirements.txt文件将需要在您的项目的基础级别创建,以便我们可以轻松地将它们安装在我们的容器中。
步骤 4:为容器创建 docker 文件
如果您已经在上一个步骤中克隆了回购,则下面提供的示例是相同的。下面是一个 docker 文件,它帮助我在 Google Cloud Run 上运行了一个简单的 Flask 服务器。
正如你所看到的,我们为 Python 3.9 提供了 slim 镜像,但是如果你想让之前运行的东西运行,比如 Ubuntu 的最新镜像,这可能会导致问题或者需要一些更新。
这个例子只是配置 python 从 Cloud Run 立即登录到 Google 的日志遥测,安装 Python 需求,并在 gunicorn 上提供我们的 Flask 服务器。
步骤 5:创建 Github 动作工作流
这只是一个简单的小玩具项目,我只是部署时,我推大师。根据您的部署工作流,您可能希望您的 Github 动作在不同的动作上触发。
上面的例子是在 repo 中提供的,您可能在前面的步骤中克隆了它,它需要存在于我命名为deploy.yml的文件中的.github/workflows目录中,但是您可以随意命名。
当代码被部署到main时,Github 动作工作流执行以下内容。
在该操作的第一步中,该操作检查刚刚部署的代码。如果你经常使用 Github 动作,你可能会把类似这样的步骤“记住”。
第二步我忘了名字,但有评论说Setup gcloud CLI就是这么做的。它使用我们之前创建的凭证设置 gcloud 命令行界面,并将作为秘密存储在 Github 中。
在名为Configure Docker的步骤中
现在我们已经有了 CLI 和权限设置,我们现在可以构建并向 GCP 发布我们的映像。
在我们的最后一步,我们可以最终完成我们的工作流与行动的预期目的,并部署到谷歌云运行。
如你所见,我们有许多尚未在工作流程中提供的秘密。既然我们已经提供了 Github 动作来执行部署到 Cloud Run 所需的步骤,那么是时候安全地配置我们的 Github 秘密了。
步骤 6:填充 Github 秘密
还记得我们之前在第一步中在 GCP 上创建服务帐户时下载的凭证吗?这是我们把它放在最终安息的地方的步骤。
接下来您需要导航到设置面板,在这里您可以添加以下 Github 秘密。对于克隆的回购,如果您想直接导航到您的回购位置,链接如下。
https://github . com/Dylan Roy/Google-cloud-run-github-actions/settings/secrets
否则,您只需单击回购导航栏中的设置,然后单击机密选项卡。
这里我们设置了以下 Github 秘密:
- GCP _ 应用 —您的 Google 服务帐户应用名称,用于您的云运行服务。
- GCP 凭证 —这是您需要在谷歌云控制台中生成的服务帐户凭证。你在第一步下载了这些。复制您创建的 JSON 文件的内容,将其作为一个值提供给这个 secret,然后删除该文件。
- GCP _ 电子邮件 —这是一封电子邮件,用于标识您在标记为
GCP_CREDENTIALS的密码中提供了凭据的服务帐户。 - GCP _ 项目 —你将部署到云运行的谷歌项目。
在这一点上,你的秘密应该被以下截图中显示的所有内容填充。

完成:运行新操作
在这一点上,测试它所需要的就是对你的主分支做一个样本推送,并观察它的步骤。

关键要点
除了 GCP 令人困惑的用户角色,在部署到 Google Cloud Run 时,用 Github 操作设置 CI/CD 并不太难。希望这篇文章为您节省了几个小时的时间来直接发现这个问题。感谢你一直读到最后,如果这有帮助的话,请随时订阅未来的教程,或者看看下面我写的其他教程。
阅读迪伦的其他教程
停止花费时间手动调整未对准的箭头
towardsdatascience.com](/create-beautiful-architecture-diagrams-with-python-7792a1485f97) [## 使用 Python 自动更新您的 Github 概要文件
通过自动化您的自述文件展示您的技能
towardsdatascience.com](/auto-updating-your-github-profile-with-python-cde87b638168) [## 具有 Github 操作的简单版本化数据集
不到 10 行 Python 代码,保存了著名 CEO 的历史
towardsdatascience.com](/simple-versioned-datasets-with-github-actions-bd7adb37f04b)
资源
使用 SageMaker 将定制 Docker 模型部署到使用 S3 的无服务器前端
如何使用 AWS 有效地部署模型

介绍
使用 AWS SageMaker 部署模型是允许用户或客户与之交互的一种很好的方式。虽然您可以使用 SageMaker 的 Python SDK 附带的许多算法和模型,但在许多情况下,您可能想要创建自己的算法。这就需要使用 Docker。
让人们与您的模型交互的最简单的方法是使用 AWS Lambda 和 API Gateway 来设置对模型的 API POST 请求。
最后,拥有一个用于发送请求和从模型接收推理响应的 API 是很棒的,但是一个简单好看的供用户与数据交互的 web 应用程序更好。这就是用 S3 托管静态网站和用 AJAX 访问端点的用武之地。
AWS 的所有这些组件协同工作允许一个圆滑的开发和推理服务框架。本教程还介绍了如何使用 AWS CloudWatch 来理解不明确的错误,例如自定义模型中的 500 个内部服务器错误。
查看下面提到的一些代码的回购,这里。
码头模型
要使用 SageMaker 部署定制模型,它必须由 SageMaker 的估计器类包装。这可以通过创建一个与该类接口的 Docker 映像来实现。
此外,如果你不知道 Docker 是什么以及为什么它在当今如此重要,请查看这篇帖子。
安装 Docker
用这些链接为各自的 OS 安装 Docker:Mac、 Ubuntu 和 Windows 。Windows 家庭版有点难,所以我将在这里介绍一些步骤,因为 Windows 是我使用的操作系统。首先遵循这些步骤,看看你能走多远。如果你卡住了,参考下面的步骤。
Windows Home edition 需要 WSL 2 才能运行 Docker Desktop。

单击“检查更新”并安装,直到没有更新,或找到 2004 年更新本身
首先,您必须更新到 Windows 2004,通过手动检查更新并安装任何出现的更新来完成(警告:这将占用大量内存和时间)。然后你就可以使用这些方向安装 WSL 2 了。
Docker 图像
本教程很好地解释了为我们的定制模型设置 Docker 图像的每个步骤。因此,按照教程,但首先要记住这些问题:
我在使用提供的模板时遇到的一个问题是安装 gevent。正如你在我的docker 文件中看到的,我使用了 easy_install 而不是 pip。
RUN easy_install gevent
重要提示:如果你在 Windows 上创建图像代码,那么你必须使文件与 Unix 兼容,因为行尾符号是不同的。这可以通过命令 dos2unix 来完成:
find some/directory -type f -exec dos2unix {} \;
其中 /some/directory 是图像代码的目录。
还有,确保允许模型/服务和模型/列车等文件执行:
chmod +x file/path
现在遵循另一个教程的步骤,直到您到达 AWS ECR 部分。确保创建图像并按照描述在本地测试您的模型。
唯推理模型
有时,您可能不需要在推断之前实际训练您的模型。这就是我的应用程序的情况,我将在本文结尾展示。不幸的是,SageMaker 仍然要求模型在部署之前必须是合适的。但是,您可以非常容易地在 Docker 映像中设置一个虚拟的训练脚本。例如,您可以打开模型路径并编写一个虚拟字符串作为训练。
以下是我的训练脚本:docker-image-code/anomaly-model/train
注册 Docker 图像
一旦您的模型图像被创建并且在本地工作,为了 SageMaker 能够访问它,它必须被存储在 AWS 弹性容器注册中心(ECR)中。
进入 AWS ECR 并点击“开始”。单击橙色的“创建存储库”。

在“存储库名称”下输入代表您的模型的名称。然后再次“创建存储库”。您不需要更改任何其他选项。
然后选择新的回购协议,并点击“查看推送命令”

遵循页面上显示的“macOS / Linux”命令。如果这是您第一次做这样的事情,您将需要 AWS 命令行界面(CLI)。遵循这些指令。并且用这个认证 Docker。一旦设置了 CLI 和身份验证,您就不必再重复了。
每当您想要更新您的模型时:更新图像代码,重新创建图像,在本地测试它,并再次遵循 push 命令。
Phew ,这可能需要一段时间和一些谷歌搜索,特别是如果你在 Windows 上,但希望我成功地帮你通过它。如果没有,请在评论中告诉我问题出在哪里。此时,您应该有了模型的工作 Docker 映像,并已将其存储在注册表中。
使用 SageMaker 部署
现在我们开始使用 AWS 的其他部分。首先,我们必须用 SageMaker 部署模型,然后使用 AWS Lambda 和 API Gateway 来设置一个 API,用于向模型发送数据并接收推理响应。
更详细地说,客户机调用用 API Gateway 创建的 API,并传入数据进行推理。然后,API Gateway 将这些数据传递给 Lambda 函数。在这里,它被解析并发送到 SageMaker 模型端点(称为“调用”)。该模型使用这些数据执行预测,输出通过 lambda 和 API 网关发回,后者使用预测值响应客户端。

来自这篇博文
SageMaker 笔记本
首先,我们将使用 SageMaker 部署我们的模型。
创建新的笔记本实例(或使用现有的实例)。您可以使用默认设置,并设置一个名称。从我的回购上传这个笔记本。唯一需要设置的是 docker_image_name 变量,它是你注册的 docker 图像的名称。可以在 ECR 的“储存库”下找到 URI:

下面我来解释一下笔记本的代码:
首先安装 SageMaker 版本 1.72(我无法让它与最新版本一起工作,但它现在可能工作了)。获取会话、客户机和执行角色,为模型输出创建一个存储桶。docker 图像名称是您上传的图像的 repo URI。
创建接受许多参数的估计器。可以根据你的需求改变的是 train_instance_type 。这是 AWS 云计算实例,将在调用 fit 时用于训练模型。注: m1.m4.xlarge 似乎是训练允许的最便宜的。此处列出了更多可能适用于也可能不适用于培训的实例类型。如果你需要更多的内存来训练,或者只是想让它更快,尝试更昂贵的实例。
接下来,我们调用 fit 来训练模型。这将运行 docker 图像模型目录中的训练脚本。您将需要调用 fit,即使模型的唯一目的是推理。我的项目就是如此。
最后,我们通过部署模型来建立端点。 endpoint_name 应该是可以识别的东西。用于推理的实例类型甚至可以比用于训练的更不密集,例如最便宜的 m1.t2.medium 。
这里更多的是关于 SageMaker 的价格。使用 AWS 成本管理 来跟踪您的模型的培训和部署成本(如果您不小心,成本可能会很快失控)。
现在我们已经部署了模型!让我们弄清楚如何真正让人们与它互动。
使用 Lambda & API 网关创建 API
我们必须创建一个 lambda 函数来调用端点。转到 AWS Lambda 并创建一个新函数。将其命名为有用的名称,将运行时更改为 Python 3.6,然后选择一个现有的执行角色,该角色有权调用模型端点或创建一个新的执行角色。

IAM 角色权限
要向您的角色授予调用模型端点的权限,请转到 AWS IAM ,然后在侧边栏上选择“角色”:

单击角色,在上面的例子中是“myLambdaFunction-role-…”。在打开的“权限”选项卡中,单击唯一策略。

应该会出现一个策略的 JSON 描述。点击“编辑策略”,然后点击“JSON”选项卡,添加一行“sagemaker:InvokeEndpoint”,如下所示:

这允许角色与 SageMaker 端点进行交互。点击底部蓝色的“审查政策”和“保存更改”。
回到 lambda,在“lambda_function”代码面板中用代码替换现有代码。
首先,您会注意到端点名称变量。这将我们模型的端点链接到这个函数。在我的例子中是异常检测端点:
用于部署模型的 SageMaker 代码;显示您选择的端点名称
编辑功能代码下的“环境变量”:

添加一个环境变量,关键字为 ENDPOINT_NAME ,值为 SageMaker 中的端点名称。在我的情况下,它将是异常检测端点。保存它。
回头看看 lambda 函数代码,下一件重要的事情是content type = ' application/JSON '调用端点。在我的例子中,输入数据是一个 JSON,因为我包含了一些用于推理的超参数,而不仅仅是模型的输入数据。然而,如果您不需要推理超参数,那么您可以创建类型‘text/CSV’,步骤都非常相似。
创建 API 网关
用 POST 请求访问已部署模型的最后一步是设置一个 API。登录后,进入 AWS API 网关,点击右上角的“创建 API”。然后选择“HTTP API”作为类型,并单击“构建”。添加一个 lambda 集成,并选择正确的 AWS 区域和刚刚创建的 Lambda 函数的名称。然后命名网关。大概是这样的:

点击“下一步”并添加路线。选择“过帐”作为方法。在“资源路径”中再次输入 lambda 名称,如 /myLambdaFunction 。并在“集成目标”下再次放置 lambda 函数名。

对于 stages,添加一个类似于 test 的 stage,并单击开关,这样这个 stage 就会自动部署。这将是后 URI 时代的一部分。

最后,点击底部的“创建”。
如果你回到你的 lambda 函数,你会在顶部的图中看到 API Gateway。单击它,然后显示详细信息。“API 端点”是 POST 请求的 URL,人们可以使用它从您的模型中获得预测。它遵循以下格式:
https://{restapi_id}.execute-api.{region}.amazonaws.com/{stage_name}/{resource_name}

最后,您可能希望允许这个 API 网关的 CORS 配置中的所有源和头,否则当您试图使用 AJAX 在您的静态 S3 网站中发出 POST 请求时,将会遇到 CORS 问题。
回到 API Gateway,点击你的 API。然后转到侧边栏“开发”下的“CORS”。

点击“配置”,添加 *** 为“访问-控制-允许-起源”*,** 为“访问-控制-允许-标题”,添加 POST 为“访问-控制-允许-方法”。那就省省吧。

您可能希望更具体地描述这些选项,因为通配符*允许所有可能的选项,例如访问此 API 的所有可能来源。
这是又一个完成的大部分!现在,API 被设置为从您的模型接收预测。在下一节中,我将描述如何用 Postman 测试调用,并使用 AWS CloudWatch 修复任何不明确的错误。
使用 Postman 和 CloudWatch 进行测试
让我们用 Postman 测试模型的推理代码,Postman 是一个 API 开发平台,有助于轻松检查我们的新 API。如果你还没有为你的操作系统安装 Postman 。然后创建一个新请求,并选择“过帐”作为类型。在 URL 选项卡中设置我上面提到的 URL。

您可以更改请求的某些内容,比如授权或标题,尽管我没有更改默认设置。
接下来,我们必须实际输入请求的正文。这将包含我们希望模型用来进行预测的数据。我发现最简单的方法是对 JSON 和 CSV 数据使用“Body”下的“raw”选项卡。这将避免数据的任何编码(除非您需要)。
对于 CSV 正文,将 CSV 数据本身作为原始字符串粘贴。格式为:
"First,Line\r\nSecond,Line\n\r......"
对于 JSON 主体,编写 JSON 字符串。如果实际的模型输入本身仍然是 CSV 格式的,那么您可以添加一个关键字,如 "data" ,其值与上述相同。类似于:
{"hyperparameter_1": #, "hyperparameter_2": #, "data": "First,Line\r\nSecond,Line\n\r......"}
然后点击“发送”!有可能有些东西不起作用。确保您的端点仍然在 SageMaker 上(笔记本本身不需要运行)。Lambda 连接到正确的端点(从 env 变量)。API Gateway 通过请求的正确 URL 连接到 Lambda。如果你得到一个“500 内部服务器错误”或者“ModelError ”,那么你的 Docker 镜像代码或者 lambda 函数代码就有问题。这就是 AWS CloudWatch 派上用场的地方。
AWS 云观察
找出哪一行代码触发了一个模糊错误的最好方法是使用 AWS CloudWatch。我不会详细介绍 CloudWatch,但我会提到一些有用的东西。AWS CloudWatch 允许您监控日志中记录的正在运行的 AWS 进程。例如,可以跟踪 SageMaker 培训工作、笔记本实例或端点。
要找出是什么触发了一个错误,进入 AWS CloudWatch ,在左侧栏进入“日志”下的“日志组”。您应该已经创建了一些日志组。首先检查你的 lambda 函数日志。点击它,你会看到一堆日志流。

最上面的一个是最近的,所以单击它,查看具体的消息。如果这个日志组有问题,那么应该归咎于你的 lambda 函数。
要检查的另一个日志组是连接到端点的日志组。此处出现的任何问题都表明您的 Docker 图像代码有问题。即使它在本地运行良好,在 AWS 中运行也会有问题。此外,这里还会显示许多 pings,忽略它们或尝试过滤它们。
希望,它现在运行顺利,你得到你期望的输出,如果没有留下评论,我会帮助修复它。
最后,我们有了一个可用的模型。如果你需要的只是文章的网址,你完全可以就此打住。然而,另一件有用的事情可能是创建一个漂亮的前端,让人们可以将自己的数据输入到模型中。一个简单的方法是使用 S3 创建一个静态网站来访问文章的 URL。
用 S3 创建一个静态网站前端
这篇中型文章很好地描述了如何一步一步地用 S3 创建一个静态网站。因此,与其自己重新创建,不如检查一下,并完成它的所有步骤(注意:你不需要建立一个 CNAME 记录)。
完成后,我建议您做的唯一一件事就是添加 CORS 策略,方法是转到“权限”->“CORS 配置”,然后粘贴以下内容:
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration ae kv" href="http://s3.amazonaws.com/doc/2006-03-01/" rel="noopener ugc nofollow" target="_blank">http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedHeader>*</AllowedHeader>
<AllowedMethod>POST</AllowedMethod>
</CORSRule>
</CORSConfiguration>
它将处理 CORS 问题,就像我们在 API Gateway 中处理它一样。
AJAX 向模型发送请求
最后,让我们在网站中用 AJAX 连接 API 调用。这个调用很简单,看起来像这样:
注意:将内容类型设置为 text/plain,以避免它像用 Postman 一样对您的请求数据进行编码(除非您希望这样)。
这就结束了使用 AWS 部署定制模型并使用面向用户的前端设置它的端到端开发链。如果您想对您的模型代码进行更改,那么重新制作 Docker 映像并将其推回 ECR。然后重新部署。另外,当您不希望从 SageMaker 控制台或笔记本代码中部署模型端点时,请删除它。
我的应用 Google 趋势数据的异常检测
我创建了一个自定义模型,该模型采用 google 趋势数据(CSV)并使用基于密度的带噪声应用聚类算法(DBSCAN)或黄土季节趋势分解算法(STL)分析异常图。

来自维基百科
简而言之, DBSCAN 是一种机器学习聚类算法,但可用于异常检测,因为与 K-means 不同,它不会对所有点进行聚类。这些剩余或未聚类的点可以被认为是异常值/异常值。

来自机器学习大师
STL 是时间序列数据的统计分解,目的是检测异常或探索数据元素。它将数据分解成季节模式、趋势和残差。然后,您可以对残差使用异常值检测测试,例如广义极端学生化偏差(GESD) 测试。对于具有季节性模式的数据,STL 往往比 DBSCAN 工作得更好,但是如果没有季节性模式,STL 就不能有效地使用。
查看我部署的模型前端这里。在 google trends 上搜索一个术语并下载 CSV:

然后上传到网站上,如果数据有季节性,填写给出的超参数。

绘制它,它看起来会像这样:

湖人受欢迎程度与异常积分的关系图
注意:网站可能不会一直打开
如果它还没出来,你想检查一下,或者你对评论中的这些步骤有任何问题,请告诉我!点击查看随附代码。
免费在 AWS 上部署数据应用程序
实践教程
让其他人立即访问您的数据应用程序

由 Austin Distel 在 Unsplash 上拍摄
在之前的帖子中,我们用 Python 和 Streamlit 创建了一个数据应用。它只在本地机器上工作,所以其他人不能使用它。
在本文中,我们将在 AWS EC2 实例上运行我们的数据应用程序,以便其他人可以访问它。
我们只需要在 AWS 上创建一个自由层账户。创建它非常简单,如果我们保持在免费层的范围内,我们不会被收取一分钱。免费层的范围对于学习来说已经足够了。
如果您已经有一个 AWS 帐户或刚刚创建了一个免费的一级帐户,我们已经准备好开始。
帖子的概要:
- 创建 EC2 实例
- 连接到 EC2 实例(Linux、Mac 和 Windows)
- 在 EC2 实例上运行应用程序
创建 EC2 实例
我们需要在 AWS 管理控制台上打开 EC2 仪表板。

(图片由作者提供)
在 EC2 仪表板上,向下滚动一点并单击 Launch Instance。

(图片由作者提供)
我们首先需要选择一个 Amazon 机器映像(AMI ),它提供启动实例所需的信息。AMI 包含软件配置(即操作系统)和一些预安装的软件包。
AMI 有很多选择。我们将选择第一个是亚马逊 Linux 2。

(图片由作者提供)
您可以选择另一个,但要确保它符合自由层条件。
下一步是选择实例类型。有一个符合免费层的条件。

(图片由作者提供)
下一步是配置实例细节,但我们可以保留默认选项。我们也可以跳过接下来的两项,即“添加存储”和“添加标签”。默认的存储选项就足够了。
下一步是配置安全组。可以认为它是一个实例级的防火墙。因此,它管理进出实例的流量。
我们将添加如下两条新规则:

(图片由作者提供)
然后我们将回顾并发布。最后一步是创建密钥对。确保创建一个密钥对并下载它。我们将需要它来连接到实例。

(图片由作者提供)
下载密钥对(。pem 文件),我们就可以启动实例了。该实例将在几分钟后准备好,我们可以在 EC2 仪表板上查看它。
连接到 EC2 实例
我目前使用的是 windows 计算机,因此我将向您展示如何从 windows 计算机连接到实例。
如果您使用 Linux 或 Mac,连接过程会简单得多。事实上,AWS 已经明确解释了这些步骤。在 EC2 仪表板上,选择您的实例并单击“Connect”。将打开一个带有说明的新页面:

(图片由作者提供)
让我们回到我们的 windows 机器案例。我们将使用 PuTTY,这是一个用于 windows 的免费 SSH 客户端。你可以从 putty.org 下载。
第一步是使用启动实例时下载的密钥对(pem 文件)创建一个 ppk 文件。
从 PuTTY 下的菜单中,打开 PuTTYGen。点击“加载”,然后选择 pem 文件。

(图片由作者提供)
然后点击“保存私钥”保存生成的 ppk 文件。

(图片由作者提供)
我们现在有了我们需要的 ppk 文件。下一步,我们将从 PuTTY 下的菜单中打开“PuTTY”。
在 EC2 仪表板上,单击实例 ID 以查看实例详细信息。复制 EC2 实例的 IP 地址(IPv4 公共 IP)。

(图片由作者提供)
然后在键入“ec2-user@”后将其粘贴到主机名框中,如下所示:

(图片由作者提供)
然后选择连接-> SSH -> Auth ->浏览并上传 ppk 文件。

(图片由作者提供)
暂时不要点击“打开”。下一步是为您的会话命名。单击“Session ”,在“Saved Sessions”框中键入名称并保存。

(图片由作者提供)
现在,我们可以单击“打开”来连接到实例。

(图片由作者提供)
我们现在连接到我们的实例。Putty 将打开一个终端,如下所示:

(图片由作者提供)
在 EC2 实例上运行应用程序
我们已经准备好上传实例的源代码和依赖项。
这个 EC2 实例预装了 Python 2.7,但我们需要 Python 3.6 或更高版本的 Streamlit。以下命令将安装 Python 3。
sudo yum install python3
我们将从 Github 库中克隆源代码,因此我们将安装 git。
sudo yum install git
我们现在可以在 EC2 实例中克隆存储库了。复制存储库的地址:

(图片由作者提供)
然后在“git 克隆”后粘贴到终端中:
git clone [https://github.com/SonerYldrm/stock-prices-app.git](https://github.com/SonerYldrm/stock-prices-app.git)
输入存储库:
cd stock-prices-app
下一步是安装依赖项:
sudo python3 -m pip install streamlit
sudo python3 -m pip install pandas
sudo python3 -m pip install pandas-datareader
由于这是一个简单的应用程序,我们没有太多的依赖。
源代码保存在 st1.py 文件中。您可以通过在终端中键入“ls”来查看存储库中的文件。
我们现在可以使用以下命令运行该应用程序:
streamlit run st1.py

(图片由作者提供)
恭喜你。我们的股票价格数据应用程序运行在 EC2 实例上,可以通过网络浏览器从任何地方访问。
在您的网络浏览器中输入外部 URL,您将看到该应用程序正在运行。这是保存在网络浏览器中的应用程序的简短屏幕记录。

(图片由作者提供)
注意 :第一次打开 app 时可能会看到关于数据源的警告。忽略它,输入一个股票名称就可以了。应用程序将顺利运行。
当你读到这篇文章时,我可能已经运行了这个实例。然而,您可以使用资源库中的源代码轻松创建自己的库。
结论
股价数据 app 就是一个简单的。它只是根据用户输入下载股票价格并显示出来。然而,创建更高级和更复杂的应用程序的过程是相同的。
我相信这个简单的应用程序和快速部署将有助于您创建数据科学或机器学习产品。一旦你熟悉了基础,你就可以稳步增加复杂度。
值得注意的是,这不是一个生产就绪的部署。适当的安全与 HTTPS 和证书是非常重要的真正的产品。还应该考虑预期的流量。最后,您可能希望获得一个主机名。
感谢您的阅读。如果您有任何反馈,请告诉我。
构建用于标记鳟鱼种类的深度学习模型 API
一个用于识别鳟鱼种类的全栈深度学习研究项目&更多
本博客参考了正在进行的 水视觉深度学习研究项目 的工作
我最近在蒙大拿迷上了干蝇钓鱼。这是一项技术运动,我还不是很好(目前为止!)但是,在河上航行是一种享受,每次航行都能学到更多东西。

蒙大拿州洛克克里克
当我出去钓鳟鱼时,我注意到的一件事是,我对不同种类的鳟鱼知之甚少。当我钓到鳟鱼时(这种情况仍然不常见),我发现自己在谷歌上搜索照片,并将它们与我钓到的鱼进行比较。我几乎无法区分不同的物种。这让我想到,也许有一种方法可以用计算机视觉深度学习来程序化地识别鳟鱼种类。我问了几个朋友,他们是专业的钓鱼向导和铁杆业余爱好者,因为我认为图像识别可能会有所帮助,他们是这样说的:
鳟鱼有大约 30 种,所以很难区分它们中的一些
“这对于所有的杂交鳟鱼物种来说都是非常有趣的,比如切弓鳟” (切弓鳟是割喉鳟和虹鳟的杂交品种)
我开始提出以下问题:
- 能否建立一个准确的深度学习计算机视觉模型,从图像中识别鳟鱼种类?
- 我能否构建一个 web 应用、REST API 和移动应用,作为深度学习模型的支持基础设施?
- 我是否可以建立一个开源的 trout 照片收集库,以鼓励进一步的深度学习模型开发、图像收集/标记和 trout 研究?
数据收集和机器学习管道

用于构建 Aqua Vision 深度学习 、深度学习应用和 API 的完整数据管道
数据
对于鳟鱼图像(更不用说任何其他鱼类)没有一个全面的标记数据集,所以我从头开始建立了自己的 500+图像数据集。我用下面列出的几种不同的方法收集图像。
数据来源:
- 谷歌图片搜索:在控制台中运行 Javascript 命令来抓取图片和下载文件
- hashtaginsta gram Scraper的命令行工具(即 #browntrout , #rainbowtrout )
- 从钓鱼博客和研究机构下载照片
收集完图像后,我手动检查了所有的照片,以确保图像与它们各自的鳟鱼种类标签相匹配,并删除了任何不属于它们的杂项图像(捕鱼设备、河流、钓具箱、错误标记的鱼种等)。数据收集和清理阶段大约需要三周时间。现在,我拥有了 500 多张跨越少数鳟鱼物种的图像,我有了一个初始图像数据集,可以开始构建一个深度学习鳟鱼识别模型。
构建深度学习模型
Fastai 深度学习库有一些非常好的内置工具,可以从谷歌图像搜索中抓取图像,然后将图像文件加载到一个ImageDataBunch对象中。然后,ImageDatabunch可以应用数据扩充转换器,设置图像像素分辨率的大小,加载迁移学习并将数据分成训练、验证和测试集。
对于数据扩充,我用默认设置保持它非常简单,但我确实随机水平翻转图像,以帮助标准化鱼面向每个方向的图像。


数据扩充:棕鳟鱼的水平翻转示例
数据增强真的很好,因为它本质上有助于规范化现有的数据集,以训练更多的例子,增强的图像看起来都很不同,但我们不必做任何额外的手动标记,所以它们就像免费的额外数据。我发现,试验数据扩充参数和数据集的领域专业知识确实是最大限度地扩充数据的方法。
我利用迁移学习,从 ImageNet 预加载模型权重,而不是从头开始初始化深度学习模型权重。ImageNet 是一个数据集,包含数百万张带有标签的高分辨率图像,大致属于 22k 个类别。这些图片是从互联网上收集的,并由人们使用众包工具进行标记。迁移学习是一种很好的方式,可以利用之前训练的模型并降低计算成本,然后根据特定领域的数据进行微调,以执行特定领域的任务。
然后将ImageDataBunch与神经网络架构和损失函数一起加载到Learner对象中,以训练深度学习模型。
learn = cnn_learner(ImageDataBunch, models.resnet.34, metrics=error_rate)
提高模型性能的一个小技巧是从较小的图像尺寸(224)开始训练,然后将这个拟合的模型在较大的图像尺寸(352)上进行一些拟合。这在几乎所有情况下都有助于提高性能。
我在 70%的图像上训练模型,并保留剩余的 30%用于测试。我喜欢使用 Paperspace 来训练深度学习模型,因为他们有免费的 GPU 支持的 Jupyter 笔记本,非常容易设置和加载到深度学习库中。
在通过数据(历元)的几次运行将数据拟合到更深的像素分辨率之后,该模型在测试集数据上达到 96%分类准确度的峰值。这已经足够好了,可以作为 web-app 和 API 的第一个深度学习鳟鱼标识符版本。
将深度学习模型部署为 API 和 Web 应用程序
我将训练好的深度学习模型导出,用于生产环境中进行预测。我将模型包装在 Python 的 web 框架 Flask 中,通过 web 应用程序和 REST API 进行预测。支持这个 Aqua Vision 深度学习研究项目的 web-app 和 API 文档可以在这里找到。
Rest API
目前有两个 API 端点可用:一个用于获取深度学习模型当前支持的类(物种),另一个通过发布图像文件进行物种预测。您可以通过从命令行执行以下 cURL 命令来测试 API。
目前支持的类(种):
您可以在端点查看模型当前支持的鳟鱼种类:
GET /api/classes
curl -X GET “https://aqua-vision.herokuapp.com/api/classes"
你会得到这样的回报:["brown_trout", "bull_trout", "rainbow_trout"]
物种预测
预测终点位于:
POST /api/predict
curl -X POST -F image=[@b](http://twitter.com/file_name)rown_trout.png “[https://aqua-vision.herokuapp.com/api/predict](https://aqua-vision.herokuapp.com/api/predict)"
-X标志和POST值表示我们正在执行 POST 请求。我们提供-F image=@brown_trout.jpg来表明我们正在提交表单编码数据。然后将image键设置为brown_trout.jpg文件的内容。在brown_trout.jpg之前提供@意味着我们希望 cURL 加载图像内容并将数据传递给请求。
你会得到这样的回报:{“class”:”rainbow_trout”,”success”:true}
通过 Python 以编程方式访问 API
下面是一个简单的 Python 脚本,它使用请求库向 API 提交数据,然后使用返回的预测。
正在进行的工作
您可以通过访问项目的网站和 GitHub 问题来查看正在进行的进度。
该项目的持续目标是:
- 建立开源鳟鱼照片库继续提高深度学习模型的准确性,增加鳟鱼种类识别的支持类数量(最终扩展到其他鱼类)
- 用边界框标记图像以将对象检测并入深度学习图像分类
- 带有坐标和时间戳的地理标签照片,用于未来的鳟鱼物种研究(种群分布、迁徙模式、杂交育种、地理空间分析等)
- 构建支持性的本地移动应用
密码
这个项目的代码可以在我的 GitHub 上找到
如果你想为这个项目做出贡献,或者有任何意见或问题,请发邮件给我:【perryrjohnson7@gmail.com】或者联系LinkedIn。
使用 Flask 部署深度学习模型

作者照片
无需成为 web 开发人员即可创建 web 部署
在之前的一篇文章中,我描述了使用 Facebook Messenger 和 Rasa chatbot 框架部署深度学习模型的过程。这种方法为正在讨论的模型提供了流畅的用户体验(预测多伦多有轨电车网络的延迟),但它有许多移动部分:配置一个脸书应用程序,训练一个 Rasa 聊天机器人,以及用 Python 为聊天机器人定义自定义操作,以应用深度学习模型来预测用户想要乘坐的有轨电车是否会延迟。

使用 Facebook Messenger 和 Rasa 进行模型部署的组件
我想以更简单、更传统的方式部署相同的深度学习模型。感谢 Flask web 框架,我能够为街车延迟预测模型创建一个简单的基于 web 的部署。在本文中,我将描述创建这个部署的步骤。
为深度学习模型的网络部署寻找框架
我正在为一本书创建 web 部署,这本书是我为曼宁出版社写的,内容是关于使用结构化数据进行深度学习的。本书的读者对如何部署简单的深度学习模型感兴趣。他们需要一个简单明了的部署示例,不要强迫他们费力地处理一大堆 web 编程细节。出于这个原因,我希望 web 部署解决方案尽可能多地保留 Python 中的代码。
考虑到这一点,我研究了两个基于 Python 的 web 部署选项: Flask 和 Django 。我选择 Flask 是因为它更适合我的书的读者,对他们来说,web 编程本身并不是目的。这篇文章很好地对比了 Flask 和 Django 的优缺点,它加强了我的直觉,即 Flask 是我的 web 部署的正确选择。
web 部署的用户体验
下图总结了 web 部署的预期用户体验。用户通过两个简单的网页与部署的深度学习模型进行交互:
- home.html:用于输入计划的电车行程的详细信息
- 显示-预测。html :显示模型对计划中的电车行程是否会延误的预测

web 部署的用户体验
用户将在网页 home.html 中选择关于他们电车旅行的细节,并点击获得预测。该预测(或者“是,预测到延迟”或者“没有预测到延迟”)将显示在网页 show-prediction.html 中。然后用户可以点击获得另一个预测返回 home.html,输入另一次有轨电车旅行的细节。
有了这个预期的用户体验,我就可以开始编写解决方案了。幸运的是,我在 Flask 上占了先机,因为我之前做过一个项目(在本文的中有所描述),我使用 Flask 来服务 Facebook Messenger 上下文中显示的网页。我使用该项目的 Flask 模块作为 web 部署应用程序的起点。
web 部署的关键代码
web 部署中的两个关键文件是:
- flask_server.py: 包含调用管道和训练模型的 flask 服务器代码和逻辑
- home.html: 包含获取旅行细节的代码。
下图总结了从收集来自用户的电车行程详细信息(路线、方向和时间/日期)到显示模型预测的端到端过程:

Web 部署端到端摘要
以下是 flask_server.py 中的关键代码段:
- 首先,我们读取配置文件,并为管道和模型文件设置文件名:
读取配置文件 deploy_web_config.yml 并设置管道和模型文件名
为管线和模型文件构建路径
- 接下来,我们有一个视图函数,当用户在浏览器中访问 localhost:5000 时,它会呈现 home.html:

home.html
home.html包含下拉列表的 HTML 代码,用户可以在其中选择旅行细节。它还包含两个 Javascript 函数,这两个函数从下拉列表中加载选择,并为用户单击 Get prediction 按钮时跟踪的链接构建一个 URL(包括具有路线、方向和时间/日期评分参数值的参数):
prefix = "/show-prediction/?"
window.output = prefix.concat("route=",route_string,"&direction=",direction_string,"&year=",year_string,"&month=",month_string,"&daym=",daym_string,"&day=",day_string,"&hour=",hour_string)
当用户点击获取预测时, flask_server.py 中的另一个视图函数被调用:
-
将评分参数实参从 URL 加载到字典中:
-
加载管线和模型:
-
创建加载有评分参数的数据帧,通过管道运行该数据帧,并将该模型应用于管道的输出以获得预测:
-
使用来自模型的预测来构建预测字符串,然后使用预测字符串作为参数来呈现show-prediction.html:

show-prediction.html
组成 web 部署的文件的摘要
你可以在这个 repo 中找到 web 部署的代码:https://github . com/ryanmark 1867/deep _ learning _ for _ structured _ data
这个 repo 包含整本结构化数据深度学习书的代码,包括准备输入数据集和训练模型的代码,以及模型的 Facebook Messenger 部署。对于本文,我们只对与 web 部署相关的文件感兴趣,如下所示:
├───deploy_web
│ │ custom_classes.py
│ │ deploy_web_config.yml
│ │ flask_server.py
│ │
│ ├───static
│ │ └───css
│ │ main.css
│ │ main2.css
│ │
│ └───templates
│ home.html
│ show-prediction.html
│
├───models
│ scmodelmar272020_5.h5
│
│
└───pipelines
sc_delay_piplelinemar272020.pkl
sc_delay_pipleline_keras_prepmar272020.pkl
以下是对构成 web 部署的文件的描述:
/deploy_web :
- flask_server.py :包含大部分部署代码的主 flask 模块
- custom_classes.py :管道使用的类的定义
- deploy _ web _ config . yml:flask _ server . py 读取的配置文件,用于设置关键参数,包括管道和模型文件的名称
/models: 包含保存为 h5 文件的经过训练的深度学习模型。部署中使用的模型是 deploy_web_config.yml 中的参数集
/pipelines: 包含用于已训练管道的 pickle 文件,这些管道将输入的有轨电车行程细节(路线、方向和时间/日期)转换为深度学习模型需要对行程细节进行评分的格式。部署中使用的管道是 deploy_web_config.yml 中设置的参数
运行 web 部署
一旦克隆了 repo,就可以按照以下步骤运行 web 部署:
-
转到 repo 的本地实例中的 deploy_web 子目录
-
编辑 deploy_web_config.yml 配置文件,以指定要用于部署的训练模型和管道文件。缺省情况下,将使用下面显示的管线和模型文件。
-
如果您尚未安装 Flask,请输入以下命令:
pip install flask
- 输入以下命令启动 Flask 服务器和相关代码:
python flask_server.py
- 在浏览器中输入此 URL 以加载 home.html:
localhost:5000
如果一切正常,你会看到 home.html:

结论
多亏了 Flask,我能够为深度学习模型创建一个简单的、基于 Python 的 web 部署。这种部署结合了 Python 代码、Javascript 和 HTML,提供了一个基本的界面,用户可以在其中输入评分信息(关于他们提议的有轨电车旅行的详细信息),并获取深度学习模型的预测。
在 Heroku 上部署 Flask 应用程序,并将其连接到 MongoDB 的 mLab
将带有 MongoDB mLab 数据库的 Python 应用程序部署到 Heroku 的简短指南。
By: 爱德华克鲁格*爱德华 哈尔曼四世道格拉斯富兰克林 。*

美国宇航局在 Unsplash 上拍摄的照片
像我们以前的云部署文章一样,我们将介绍如何使用 Pipfile.lock 将应用程序部署到云,并将应用程序连接到云数据库。有关虚拟环境的更多信息或开始使用环境和包管理器 Pipenv,请查看 这篇文章 !
部署问题
由于缺乏对虚拟环境的了解或经验,新开发人员通常在系统级别安装所有东西。用 pip 安装的 Python 包放在系统级。以这种方式为每个项目检索需求会在您的机器上创建一个无法管理的全局 Python 环境。虚拟环境允许你划分你的软件,同时保持一个依赖清单。
Pipenv 是一个用于环境和包管理的工具,它允许开发人员创建更容易部署、构建和修改的独立软件产品。
Pipenv 是什么?
Pipenv 将包管理和虚拟环境控制结合到一个工具中,用于安装、删除、跟踪和记录您的依赖关系:以及创建、使用和管理您的虚拟环境。Pipenv 本质上是将 pip 和 virtualenv 包装在一个产品中。
什么是 Heroku?
Heroku 提供许多软件服务产品。我们将需要 Heroku 云平台服务来托管一个应用程序和 mLab 来使用 MongoDB 数据库。别担心,创建一个帐户并使用这些功能是免费的!
云平台支持多种编程语言的应用,包括 Python、Node.js、Scala、Ruby、Clojure、Java、PHP 和 Go。我们将使用 Heroku GUI 部署一个数据库和一个 Python 应用程序。
云数据库的优势
在我们以前的部署中,我们使用 SQLite 和 JawsDB 数据库。当使用 SQLite 数据库时,每次应用程序重新部署都会重置您的数据库。JawsDB 非常适合部署 MySQL 关系数据库,该数据库将通过应用程序更新来保持。这一次,我们想要一个基于文档的数据库系统,以 MongoDB 在 Heroku 的 mLab 插件的形式。
准备部署
Heroku 允许我们从 GitHub 分支部署应用程序。一旦我们有了一个 Pipfile 被推送到 GitHub 的工作应用程序,请确保您的 Pipfile 在项目的根目录下,我们准备对存储库进行一些最终的更改,为部署做准备。
注意:这些变化允许我们的应用程序在 Unix 系统上运行。Gunicorn 与 PC 不兼容,因此您将无法在本地测试这些更改。
安装 gunicorn
Gunicorn 是一个 Python WSGI HTTP 服务器,它将为 Heroku 上的 Flask 应用程序提供服务。通过运行下面的代码行,您将 gunicorn 添加到您的 Pipfile 中。
*pipenv install gunicorn*
添加 Procfile
在项目根文件夹中创建一个 Procfile,并添加以下行:
*web: gunicorn app.app:app*
第一个应用程序(在。)表示 repo 中包含运行应用程序所需的所有文件的目录。第二个应用程序(在。)是运行您的应用程序的 python 文件的名称或应用程序所在的模块的名称,即 app.py。最后,第三个应用程序(在:)之后)表示您在 app.py 中的 flask 应用程序。此 Procfile 与 gunicorn 和 Heroku 的 Dynos 一起工作,以远程服务您的应用程序。
Heroku 云数据库的建立和部署
建立一个 Heroku 帐户如果你还没有,不要担心,我们在这里展示的所有功能都是免费的!
转到您在 Heroku.com 上的应用,然后单击资源。然后在 addons 框中输入“mLab MongoDB ”,如下所示。

从下拉列表中选择“Sandbox-free”并单击“Provision”如果您还没有 mLab 的帐户,Heroku 将引导您创建一个帐户。我们现在已经为我们的应用程序部署了一个 MongoDB 数据库!现在我们需要将这个新数据库集成到我们的应用程序逻辑中。

我们需要将 py mongo(Python MongoDB 库)添加到我们的 Pipfile 中,如下所示:
*pipenv install pymongo*
现在让我们得到我们的连接字符串,并为 pymongo 修改它。转到设置,用“显示配置变量”按钮查看配置变量。您会在“MONGODB_URI”旁边找到一个类似于下面的连接字符串:
*mongodb://heroku_l148hmql:tpna8npo399tsuuy82s7fgma2c@ds175222.mlab.com:51222/heroku_l148hmql*

与我们到 JawsDB 的连接不同,我们不需要通过在前面添加 pymongo 驱动程序来调整这个连接字符串。然而,我们仍然必须改变连接字符串。在文本编辑器中,将?retryWrites=false添加到字符串的末尾,使其类似于下面的字符串。
*mongodb://heroku_0hk44bz1:vrha0rbf397na30dgigjdtkgnc@ds151993.mlab.com:51993/heroku_0hk44bz1?retryWrites=false*
单击 Heroku 中配置变量旁边的 edit 按钮,然后复制并粘贴这个更新后的字符串,并单击“Save Changes”

隐藏连接字符串。包封/包围(动词 envelop 的简写)
创建一个名为.env的新文件,并将云数据库的连接字符串添加为 MONGODB_URI,如下所示。
*MONGODB_URI=”mongodb://root:PASSWORD@HOSTNAME:3306/db_name” [your connection string]*
注意:运行 pipenv shell 可以让我们访问这些环境变量。这种访问在下面一行中实现:
*client = pymongo.MongoClient(os.getenv(“MONGODB_URI”, “mongodb://127.0.0.1:27017/database”))*
当我们在 shell 中时,客户端会寻找 MONGODB_URI 环境变量。如果找不到,默认情况下,客户端连接到我们的本地数据库。
应用部署
一旦我们有我们的应用程序测试和工作在本地,我们把所有的代码推到主分支。然后在 Heroku 上,转到部署选项卡。选择包含应用程序的存储库,然后点击连接。

最后一步是点击“部署分支”

构建日志将开始填充页面上的控制台。注意,Heroku 首先查找 requirements.txt 文件,然后从 Pipenv 的 Pipfile.lock 安装依赖项。
一旦从 Pipfile.lock 构建了您的环境,并且构建成功,您将会看到下面的消息。

呜哇!该应用程序已成功部署!点击查看按钮,查看 Heroku 上部署的应用程序。

成功发射!照片由 Tim Mossholder 在 Unsplash 上拍摄
最初构建集合
最初,您需要在 mLab 中手动创建集合(MongoDB 的基于文档的模拟表)。如果第一个集合不存在,客户端将创建它。
但是,您可以选择在 mLab 中创建集合。如果你想这样做,请从 Heroku 的资源标签进入 mLab 网站。

在“收藏”下面,应该写着[目前没有]。在右边,点击“添加收藏”

重要提示:确保你给这个收藏起的名字和你在应用程序中的名字一样,否则将无法连接。在这个应用程序中,我们将集合称为“帖子”

自动部署
我们可以启用自动部署,让 Github master 的更改在推送时显示在 Heroku 上。如果您使用这种方法,您将希望确保始终有一个工作的主分支。
结论
对于希望在生产中部署、构建或使用代码的数据科学家和开发人员来说,实践适当的环境和包管理至关重要。
拥有一个管理良好的 GitHub 主分支允许 Heroku 的服务器用最少的故障排除来重建我们的应用程序。这使得我们可以在几分钟内将一个项目目录从 GitHub 转移到一个可用的、已发布的应用程序中。
使用云服务资源很重要,这样你的应用就可以在你自己的机器之外的机器上运行。如果您正在构建一个应用程序,您必须能够使本地构建环境适应其他人将要与之交互的环境。Heroku 的 MongoDB 插件 mLab 允许我们这样做,除了一个连接字符串之外,不需要改变太多!
我们希望本指南对您有所帮助!
使用 Streamlit 将 Prophet 预测模型部署到 Heroku
在 Python 应用程序中使用 Prophet 和 Streamlit 预测 COVID 数据的概述。

照片由 Hendrik Cornelissen 在 Unsplash 上拍摄
Streamlit 和脸书先知让我们能够以最少的努力和零成本创建一个干净的预测仪表板。这为概念工作流提供了可靠的证明。
在这个项目中,我们使用 Streamlit 和 Prophet 创建一个仪表板来展示数据和进行预测,然后将我们的应用程序部署到 Heroku。
这里有一个到 GitHub 仓库的链接,里面有我们的项目代码。注意,我们使用 Pipenv 来管理我们的依赖关系。
运行 pipenv install — dev 来安装 env。运行 pipenv 运行预提交安装来初始化 git 挂钩。运行 pipenv…
github.com](https://github.com/edkrueger/covid-forecast)
什么是 Streamlit?
Streamlit 是一个免费的开源应用框架,为数据科学家和机器学习工程师快速创建伟大的 Python 应用提供了一种简单的方法。Streamlit 固执己见的本性使构建前端变得容易。最后,Streamlit 可以让数据应用的实验和生产以及机器学习分析更容易进行和迭代。
在 GitHub 上查看一下。
streamlit-用 Python 构建数据应用程序的最快方法-streamlit/streamlit
github.com](https://github.com/streamlit/streamlit)
精简原则
Streamlit 非常优秀,因为它包含 Python 脚本,将小部件视为变量,并缓存数据和计算以供重用。这允许我们定制复杂的可视化,只需要加载一次。此外,Streamlit 可以在本地使用,也可以在云上运行。
安装和运行 Streamlit
先决条件
在开始之前,您需要 Python 3.6 或更高版本。
演示
首先,让我们安装 streamlit。如果您在设置您的机器时有问题,请随意使用我们项目存储库中的 Pipfile。
$ pip install streamlit
现在运行 hello world 应用程序,确保一切正常:
$ streamlit hello
这个命令会在你的计算机上打开一个 web 服务器,你可以在那里玩一些演示!第一次运行该命令时,可能会提示您添加一封电子邮件到~/.streamlit/config.toml。没有必要将您要使用的电子邮件添加到软件中。
值得注意的是,每次在没有完整的config.toml文件的情况下运行 Streamlit 时,都会出现这个电子邮件提示。为了解决这个问题,我们使用这个 bash 脚本来输入我们的电子邮件和我们想要运行的端口。
setup.sh
一旦我们运行这个setup.sh脚本,我们就有了我们的电子邮件和端口设置。
什么是脸书先知?
脸书预言家或 FB 预言家是一个合适的预测工具。我们将预测时间序列 COVID 数据,而不是预测结束时间。FB Prophet 使用熊猫,接收并输出一个数据帧。
传递给 FB prophet 的数据帧必须有“ds”和“y”列。然后,我们将只包含日期的数据帧输入
FB Prophet 和预测会填充缺失的值。
我们在 windows 10 机器上和 docker 容器中进行本地设置时遇到了一些问题。然而,我们在使用 GCP 人工智能平台笔记本电脑时没有遇到任何复杂情况。
安装 FB Prophet
您需要在安装fbprophet之前安装pystan。
pip install pystan
那么你应该可以运行:
pip install fbprophet
请注意,您可能会得到一个 FB Prophet 错误,指出它不能被发现。我们遇到了这个错误,包被找到了。如果你在设置上有问题,试试云虚拟机或者使用我们的 Pipfile!
构建我们的 Streamlit 应用
现在我们已经简化了它,并对它的功能有了基本的了解,让我们开始使用我们的预测应用程序。
Pandas 与 Streamlit 配合得很好,并且已经是 FB Prophet 的一个依赖项,所以我们在 load_data.py 文件中使用它来使我们的生活变得稍微容易一些。
我们所有的数据都在data.json文件里;我们需要将它加载到 Pandas 中,并将其转换成数据帧。
加载数据
我们的应用程序代码的其余部分相对简单,向我们展示了下拉选项和选择功能。这使得我们的应用程序可以在用户从下拉列表中选择一个选项时获取数据并生成图表。
点击查看app.py代码。
使用 fbprophet 预测 COVID-edkrueger/COVID-forecast 的 streamlit 应用程序
github.com](https://github.com/edkrueger/covid-forecast/blob/master/app/app.py)
运行应用程序
Streamlit 让我们像编写 Python 脚本一样编写应用程序。这意味着当我们在下拉菜单中选择一个新的选项时,整个应用程序文件将再次运行以生成绘图。
让我们运行我们的应用程序,看看默认视图。使用以下代码行在本地端口 8000 上运行您的 streamlit 应用程序。
streamlit run app/app.py --server.port 8000
默认情况下,我们的应用程序设置为加载数据并生成“所有—累积案例”图,如下所示。

COVID 预测—累积数据
由于我们的预测是实时的,在您从下拉列表中选择它们之后,可能需要一些时间来生成图表。为了减少加载时间,我们添加了 Streamlit 缓存来存储函数的结果,即我们的绘图。

下拉选项
我们的应用程序有一个下拉菜单,可以选择您想要查看的地块。当您选择非默认选项时,FB prophet 会按需运行预测。生成的数据帧然后被传递给 Streamlit,后者显示我们的数据。
我们用 Streamlit 缓存的不一定是数据。我们可以缓存任何东西,比如我们的预测!请注意,黄色警告“运行 make_forecast(…)”仅在第一次选择选项时出现。那么当我们重新选择“累积回收率”时,就没有预测;相反,我们的情节是从缓存中提取的。

按需预测
一旦进行预测,这种缓存允许在图之间平滑交换。
部署到 Heroku
要在 Heroku 上运行我们的应用程序,我们需要在 GitHub 存储库中添加一个Procifle,以便在他们的平台上运行我们的应用程序。这是我们的档案。
web: sh setup.sh && streamlit run app/app.py
注意,我们正在调用我们的setup.sh文件来设置 Heroku 机器上的电子邮件和端口。然后我们告诉 streamlit 运行我们的应用程序。只要把这个Procfile添加到你的项目根目录,你就可以在 Heroku 上运行了。
现在让我们访问 Heroku 的网站,使用 GUI 从 GitHub 部署我们的应用程序。

用于应用部署的 Heroku GUI
要连接您的存储库,请选择 GitHub,输入存储库的名称,然后点击 search。一旦您的用户名和存储库出现,单击连接。现在选择所需的分支并单击 deploy。
构建日志将开始填充页面上的控制台。注意,Heroku 首先查找 requirements.txt 文件,然后从 Pipenv 的 Pipfile.lock 安装依赖项。
一旦从 Pipfile.lock 构建了您的环境,并且构建成功,您将会看到下面的消息。

成功的应用部署
该应用程序已成功部署!点击查看按钮,查看 Heroku 上部署的应用程序。现在,我们可以在 Heroku 上实时查看我们的应用程序,并在他们的平台上运行预测。
点击这里查看我们的应用程序!
[## 细流
covid-预测-应用
st-covid-forecast.herokuapp.com](https://st-covid-forecast.herokuapp.com/)
自动部署
我们可以启用自动部署,让 Github master 的更改在推送时显示在 Heroku 上。如果您使用这种方法,您将希望确保始终有一个工作的主分支。

启用自动部署
结论
回顾一下,我们讨论了 Streamlit 和脸书预言家作为工具,使我们能够以最少的努力和零成本制作预测仪表板。Streamlit 坚持己见,易于使用,并允许我们将前端和后端代码放在一个文件中。
我们使用这些工具制作了一个显示 COVID 数据的简单仪表板,您将使用它们做什么?
感谢您的阅读!请告诉我们您使用什么工具制作仪表板,以及您希望了解更多信息。
使用 SKLearn 估算器、本地 Jupyter 笔记本和终端在 AWS 上部署 Scikit-Learn 模型
关于如何从本地设备在 AWS 上部署 scikit-learn 模型的分步教程。

从 Wikipedia.com(scikit-learn)和 aws.amazon.com 检索到的徽标。
亚马逊网络服务(AWS)是目前数据科学和机器学习专业人士最需要的云平台。鉴于此,本机器学习部署系列的第一批博客文章将概述如何在 AWS 上以多种不同的方式部署各种模型。
本系列其他帖子:
我们将涉及的第一个 AWS 部署将是一个简单的 Scikit-learn 模型的部署,该模型完全从一个人的本地计算机使用 AWS 预构建 Scikit-learn 估计器来完成。
在我们深入研究这些步骤之前,理解 AWS Sagemaker 如何训练和部署模型的基本概念很重要。如果你不熟悉 Docker,我推荐在这里阅读他们的概述文档。不涉及太多细节,AWS 本质上使用 Docker 容器来存储模型的配置,训练模型,并最终部署模型。通过将 ML 模型封装在 Docker 容器中,AWS 能够同时为通用 ML 框架提供一组预配置的 Docker 映像,同时还允许完全定制。
幸运的是,在 2018 年,AWS 将 Scikit-learn 添加到其支持的框架列表中。因此,我们可以使用预配置的 Docker 容器快速部署我们的模型。正如您将在下面看到的,我们将创建一个训练脚本,并使用 AWS Scikit-learn 估计器在容器内执行它。所以,事不宜迟,让我们开始吧。
你可以在我为这个博客系列开始的回购中找到这篇文章的代码。
第一步:账户设置
在开始之前,我们必须设置一个 AWS 帐户。如果您已经有一个 AWS 帐户,那么您可以跳到下一步。否则,让我们为你注册 AWS 和他们的 175(并且持续增长)服务。首先,导航到这一页创建你的免费 AWS 账户并获得 12 个月的免费层访问(这足以完成本文中的代码)。
步骤 2: AWS CLI 和 Pip 包
一旦您注册了 AWS,我们还需要下载 AWS 命令行界面(CLI ),这样我们就可以在本地设备上使用我们的 AWS 帐户。AWS 很好地解释了如何安装 , 配置,使用他们的 CLI。
我们还需要安装几个 python SDKs,以便在 python 脚本中访问 AWS。具体来说,我们将需要 Boto3 来处理数据上传,并需要 Sagemaker 来创建我们的 Scikit-learn 估算器。运行下面的 pip 命令来安装它们。
pip install boto3
pip install sagemaker
步骤 3:数据设置
为了专注于模型的部署,并避免陷入数据清理和模型调整的困境,我们将在 Iris 数据集上训练一个简单的逻辑回归模型。您可以在此下载数据集并将其保存到您的本地设备。
一旦我们部署了模型,我们将使用下面的代码块从数据集中提取一些样本来测试 API 调用,并将数据保存到两个名为 train.csv 和 deploy_test.csv 的新文件中。
注意:我们不考虑 ML 训练/测试集指南。在实践中,您应该总是将您的数据分成一个训练/测试集。然而,对于本教程,我们只是专注于部署模型,并将通过在最后调用 API 来检查模型如何预测我们在deploy _ test . CSV中保存的几个点。
为了让 AWS Sagemaker 在训练模型时访问这些数据,我们必须通过创建一个新的简单存储服务(S3)桶并将我们的训练数据添加到其中,将数据上传到我们的 AWS 帐户。为此,我们将使用上面安装的 boto3 SDK 在指定区域创建一个 S3 桶,然后将我们的 train.csv 文件保存在该桶的 train/ 文件夹中。 点击这里了解更多关于 S3 的信息。
注意:为了让 Sagemaker 访问数据,S3 存储桶和 Sagemaker 会话需要在同一个区域。鉴于 Sagemaker 仅在某些地区可用,请务必从这里列出的地区中为您的 S3 桶选择一个地区。
为了再次检查以上脚本是否正常工作,您可以导航到 AWS S3 控制台,登录,并查看我们在上面创建的 bucket 是否在那里。如果有了,我们就可以继续工作,创建我们的模型了!
第四步:模型脚本
为了使用 Scikit-learn Sagemaker SDK 将模型部署到 AWS,我们首先必须创建一个脚本,告诉 Sagemaker 如何训练和部署我们的模型。虽然比创建我们自己的 Docker 容器来部署我们的模型要简单得多,但是 SDK 确实要求我们坚持相当严格的准则。
首先,我们将导入我们需要的所有包,并创建几个字典来将目标标签从文本转换成数字,反之亦然。
在这些导入之后,我们需要将训练步骤包装在 main 函数中。我们还将在最后添加一行来保存模型。SKLearn Sagemaker SDK 将运行这个 main 函数,根据我们推送到上面的 S3 存储桶的数据训练一个模型,然后保存这个模型,以便以后我们想要部署它时可以使用它。
main 函数是唯一必需的函数。然而,我们有能力修改一些额外的函数,这些函数决定了模型在部署后如何处理 API 调用。这些可选功能是:
model _ fn:指定从何处以及如何加载正在部署的模型。*
input _ fn:将发送到部署模型的请求体格式化为可以馈入模型的格式。 predict _ fn:使用 model_fn 加载的部署模型和 input_fn 格式化的数据进行预测。 output _ fn:*将 predict_fn 做出的预测重新格式化为最终的格式,作为 API 调用的响应返回。**
下面的要点显示了我们模型的这些可选函数。每个函数上面的注释提供了关于每个函数的更多信息。关于这些函数及其默认行为的更多信息,请参见这里的。
步骤 5:创建 IAM Sagemaker 角色
不幸的是,当我说我们将在本地计算机上完成所有这些工作时,我撒了一个谎。如果您还没有 Sagemaker IAM 角色,我们需要导航到 AWS IAM 控制台并创建一个新角色。首先点击这里并登录。您应该会看到如下所示的屏幕:

AWS 选择 IAM 角色页
从这里,选择 Sagemaker 作为服务,并按下下一步。
通过选择下一页跳过下两页,直到您看到以下屏幕:

AWS 创建 IAM 角色名页
在此页面中,在点击创建角色之前,只需创建自己的角色名称 和(可选)角色描述。请务必记住您为您的角色命名的名称,因为我们将在下一步中用到它!*
第六步:部署模型
艰苦的工作完成后,让我们来部署您的模型。幸运的是,使用 AWS SKLearn 类,这只需要几行代码。只需确保 入口点 路径指向我们在步骤 4 中保存的脚本,并且 角色 变量是您在步骤 5 中创建的角色名称 。在这个片段中,我们还为模型和部署的端点指定了 instance_types。instance_type 指定了我们希望 AWS 为我们的服务分配多少计算能力。显然,功率越大,成本越高,所以对于这个例子,我们使用小实例。查看这里的以获得所有可用的 Sagemaker 实例类型的列表。*
注意:SKLearn()构造函数有许多可选参数,您可以添加这些参数来配置 Scikit-learn framework_version、超参数等。点击 此处 了解更多信息。
第七步:测试终点
为了测试端点,我们将 feed send 一个请求,其中包含我们在步骤 3 中保存到 deploy_test.csv 的数据样本。为了向部署的端点发送请求,我们首先需要将我们的测试样本转换成模型可以解析的格式(即,可以由我们在 aws_sklearn_main.py 中定义的 input_fn 函数解释的格式)。由于我们将模型配置为理解具有多个样本的请求,其中每个样本的特征由“,”分隔,每个单独的样本由“|”分隔,因此我们将 request_body 格式化为如下格式:
*'147,6.5,3.0,5.2,2.0|148,6.2,3.4,5.4,2.3|149,5.9,3.0,5.1,1.8'*
在这里,我们使用 boto3 创建一个 Sagemaker 会话,它将允许我们与部署的模型进行交互。为了调用我们的 Sagemaker 端点,我们使用了 invoke_endpoint 函数。对于这个函数,我们必须指定一个端点、一个内容类型和一个主体。还有一些可选参数,你可以在这里阅读更多关于的内容。在我们的例子中,我们将传递在上一步中输出的端点、content_type 'text/csv '和一个格式类似于上面的字符串。最后,一旦我们运行了这个方法并收到了响应,我们就在响应的正文中下标并读取返回的内容。
如果预期的响应与模型实际返回的相匹配,那么您已经成功地在 AWS 上训练和部署了一个有效的 Scikit-learn 模型!
步骤 8:清理资源
为了避免任何 AWS 费用,请务必清理您的资源。您可以通过取消步骤 6 中最后一行的注释并运行它来快速终止模型的端点。
*aws_sklearn_predictor.delete_endpoint()*
虽然这将删除端点,但要完全清除您在本教程中使用的所有资源的 AWS 帐户,请完成以下操作。
- 打开制袋机控制台
- 在推理下的侧栏菜单中,删除在模型、端点和端点配置选项卡上创建的资源。
- 打开 S3 控制台并删除我们创建的桶。
- 打开 IAM 控制台,删除我们创建的角色。
- 打开 Cloudwatch 控制台,删除所有/aws/sagemaker 日志。
回顾
总的来说,虽然学习曲线有点高,但一旦您能够在 AWS 服务中导航并理解 Sagemaker 原则,AWS SKLearn 估计器就成为快速部署 Scikit-learn 模型的一个不可思议的工具。
好处:
- 需要很少的配置,但有很多可用的
- 过多的文件
- 只需几行代码就可以部署模型
缺点
- 巨大的初始学习曲线
- 需要理解和使用的几个 AWS 服务
- 文档可能很难找到
本系列其他博文:
使用 TensorFlow.js 将简单的机器学习模型部署到 WebApp 中
你好,今天,你要构建一个简单的 WebApp,可以识别数字。看看下面的演示。
请在您的浏览器或手机中尝试一下:
https://carlos-aguayo.github.io/tfjs.html
TensorFlow.js 的美妙之处在于,您可以使用 Keras 或 TensorFlow 在 Python 中训练机器学习模型,并使用 TensorFlow.js 将其部署在浏览器上。无需外部服务来运行您的查询。

数字识别 WebApp
这个有趣而简单的应用程序让你画一个一位数,它使用简单的机器学习工具识别它。
如果你想直接看的话,下面是完整的代码:
让我们开始吧;这些是构建这个演示所需的成分和步骤。
配料和步骤:
- 培训用数据
- 培训环境
- 预处理数据
- 机器学习
- 将 Keras 模型转换为 Tensorflow.js
- HTML5 画布
- 把一切都连接起来
培训用数据
任何机器学习模型都需要高质量的数据。我们将使用 MNIST 数据集,这是一个手写数字的数据集。

约瑟夫·斯泰潘[ CC BY-SA
在这个数据集中,有 60,000 幅图像,所有图像的灰度都是 28 x 28 像素,像素值从 0 到 255。
有关加载和查看 MNIST 数据集的信息,请参见下面的代码片段。
培训环境
Google Colab 允许你在浏览器中编写和执行 Python。
Colab 是一个非常方便的 Jupyter Notebook Python 平台,预装了您需要的大部分 Python 机器学习库,这是一种让您快速启动并运行 ML 项目的便捷方法。
此外,它让您可以免费访问 GPU/CPU。
数据预处理
来自 MNIST 的数据需要进行一个小的预处理:
- 规范化输入:数据带有从 0 到 255 的值,我们应该将它们规范化为从 0 到 1 的范围。
- 一键编码输出。
# Normalize Inputs from 0–255 to 0–1**x_train = x_train / 255****x_test = x_test / 255**# One-Hot Encode outputs**y_train = np_utils.to_categorical(y_train)****y_test = np_utils.to_categorical(y_test)**num_classes = 10
机器学习
我们终于准备好做一些机器学习了。我们可以从一个非常简单的模型开始。我们将使用一个简单的神经网络,只有一个隐藏层。这个简单的模型足以获得 98%的准确率。
x_train_simple = x_train.reshape(60000, 28 * 28).astype(‘float32’)x_test_simple = x_test.reshape(10000, 28 * 28).astype(‘float32’)model = Sequential()**model.add(Dense(28 * 28, input_dim=28 * 28, activation=’relu’))****model.add(Dense(num_classes, activation=’softmax’))**model.compile(loss=’categorical_crossentropy’, optimizer=’adam’, metrics=[‘accuracy’])model.fit(x_train_simple, y_train, validation_data=(x_test_simple, y_test), epochs=30, batch_size=200, verbose=2)
如果你想变得花哨,你可以尝试一个深度学习模型。有了它,你可以把准确率提高到 99%。
x_train_deep_model = x_train.reshape((60000, 28, 28, 1)).astype(‘float32’)x_test_deep_model = x_test.reshape((10000, 28, 28, 1)).astype(‘float32’)deep_model = Sequential()**deep_model.add(Conv2D(30, (5, 5), input_shape=(28, 28, 1), activation=’relu’))****deep_model.add(MaxPooling2D())****deep_model.add(Conv2D(15, (3, 3), activation=’relu’))****deep_model.add(MaxPooling2D())****deep_model.add(Dropout(0.2))**deep_model.add(Flatten())deep_model.add(Dense(128, activation=’relu’))deep_model.add(Dense(50, activation=’relu’))deep_model.add(Dense(num_classes, activation=’softmax’))deep_model.compile(loss=’categorical_crossentropy’, optimizer=’adam’, metrics=[‘accuracy’])deep_model.fit(x_train_deep_model, y_train, validation_data=(x_test_deep_model, y_test), epochs=30, batch_size=200, verbose=2)
将 Keras 模型转换为 Tensorflow.js
现在我们有了一个训练好的模型,我们需要转换它,以便可以在 TensorFlow.js 中使用它。
首先,我们需要将模型保存到 HDF5 模型中。
model.save(“model.h5”)
之后,您可以通过点击左侧导航中的文件夹图标来访问保存的文件。

有几种方法可以转换模型。笔记本中的一个简单例子是这样的:
!pip install tensorflowjs!tensorflowjs_converter --input_format keras ‘/content/model.h5’ ‘/content/model’
/content/model.h5 是输入,输出保存在/content/model 文件夹中。

TensorFlow.js 需要指向 JSON 文件( model.json ),需要一个名为“ group1-shard1of1.bin ”的兄弟文件。你需要这两份文件。下载这两个文件。
HTML5 画布
让我们有一个简单的 HTML 页面,它使用 HTML5 Canvas 组件让我们在上面绘图。姑且称这个文件为“tfjs.html”。
核心绘图代码来自本网站:
使用 HTML5 Canvas 组件,我们可以将鼠标事件挂钩到画布中。
canvas.addEventListener('mousedown', function(e) {
context.moveTo(mouse.x, mouse.y);
context.beginPath();
canvas.addEventListener('mousemove', onPaint, false);
}, false);var onPaint = function() {
context.lineTo(mouse.x, mouse.y);
context.stroke();
};
然后,我们添加触摸事件,使其在移动设备上工作。
添加触摸动作以禁用滚动。这个代码的灵感来自于这个网站。
一旦我们可以绘制,让我们在鼠标抬起时获取图像。我们将把它缩小到 28 乘 28 像素,以便它与训练好的模型相匹配。
canvas.addEventListener('**mouseup**', function() {
$('#number').html('<img id="spinner" src="spinner.gif"/>');
canvas.removeEventListener('mousemove', onPaint, false);
**var img = new Image();
img.onload = function() {
context.drawImage(img, 0, 0, 28, 28);** data = context.getImageData(0, 0, 28, 28).data; var input = [];
for(var i = 0; i < data.length; i += 4) {
input.push(data[i + 2] / 255);
}
predict(input);
**};
img.src = canvas.toDataURL('image/png');** }, false);
然后,我们获取数据,将它保存在一个“输入”数组中,并将其传递给一个预测函数,我们将在后面定义该函数。
canvas.addEventListener('mouseup', function() {
$('#number').html('<img id="spinner" src="spinner.gif"/>');
canvas.removeEventListener('mousemove', onPaint, false);
var img = new Image();
img.onload = function() {
context.drawImage(img, 0, 0, 28, 28);
**data = context.getImageData(0, 0, 28, 28).data;
var input = [];
for(var i = 0; i < data.length; i += 4) {
input.push(data[i + 2] / 255);
}
predict(input);** };
img.src = canvas.toDataURL('image/png');
}, false);
数据是一个 1D 数组,其值为 RGBA 值。我们的模型只取 0 到 1 的值(或者从 255 的灰度中取 0)。假设我们正在画布上绘制 B lue,我们可以将数组分成四块,每隔一个元素取一个。
RG**B**ARG**B**ARG**...**
01**2**345**6**789...
把所有东西都挂起来
最后,让我们加载 TensorFlow.js 并运行预测。
<script src=”https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@1.5.2/dist/tf.min.js"></script>
你应该已经下载了文件 model.json 和 group1-shard1of1.bin ,并将它们保存到一个名为 model 的文件夹中,这个文件夹与你保存 HTML 文件的文件夹相同。
加载后,我们可以通过简单地执行以下操作来加载训练好的模型:
**tf.loadLayersModel**(‘**model/model.json**’).then(function(model) {
window.model = model;
});
鼠标一放,一旦我们有了数据,我们就可以把它输入到模型中:
**window.model.predict**([tf.tensor(**input**).reshape([1, 28, 28, 1])]).array().then(function(scores){
scores = scores[0];
predicted = scores.indexOf(Math.max(...scores));
$('#number').html(predicted);
});
在本地测试很简单,并且可以很容易地设置一个 HTTP 服务器来用 Python 进行测试:
python3 -m http.server 8080
如果你想用手机测试,你可以利用这个叫做 ngrok 的漂亮工具。
$ ngrok http 8080
这就打开了一个可以通过手机访问的 URL 的通道。
一旦你对结果感到满意,你就可以将你的 HTML 部署到一个虚拟主机站点。一个简单的地方就是 Github。如果你从未用 Github 创建过静态网站,你需要创建一个名为“{username}.github.io”的资源库。例如,我的存储库是:
https://github.com/carlos-aguayo/carlos-aguayo.github.io
然后,您可以通过以下方式访问它:
https://carlos-aguayo.github.io/tfjs.html
结论
请注意,我们可以多么轻松地在 Google Colab 中训练模型,导出训练好的模型,并在 JavaScript 中查询它,而无需离开浏览器!
我是 Appian 的软件开发总监兼机器学习工程师。我在 Appian 工作了 15 年,我一直很开心。如果你想知道我们是如何制作软件的,请给我发消息,让我们的客户开心!

为 Python 部署简单的 UI
Streamlit 共享:Python 项目的游戏规则改变者

瑞安·莫尔顿在 Unsplash 上的照片
使用 Streamlit 为 Python 项目创建用户界面是无缝的,Streamlit 是一个相对较新的基于浏览器的 Python 框架,允许您优雅地展示项目,而无需编写任何 HTML、CSS 或 Javascript 代码。
现在,通过 Streamlit Sharing,你可以免费部署你的项目,而不需要启动服务器或使用任何云服务,如 Heroku。
背景
在之前的文章中,我们构建了一个简单的迷宫求解器应用。简而言之,它允许用户上传一个迷宫的图像,并显示一个解决方案。用于促进用户交互的一些 Streamlit 功能包括:
滑块

文件上传和复选框:

要更深入地了解该应用如何实现 Streamlit 特性,请访问:
Streamlit:一个基于浏览器的 Python UI,不需要 HTML/CSS/JS
towardsdatascience.com](/building-a-simple-ui-for-python-fd0e5f2a2d8b)
部署
Streamlit 最近推出了 Streamlit 共享服务,以促进 Streamlit 项目的部署。使用该服务需要几个快速步骤。
1。创建一个 requirements.txt
您可以在项目环境中使用以下命令来创建它:
pip freeze > requirements.txt
2.将您的项目推送到 GitHub
为您的项目创建一个公共存储库,并确保提交 requirements.txt 以及任何项目文件。
如果你没有使用过 Github,这里有一个关于创建资源库的初级读本。
3.请求访问简化共享
虽然这项服务仍处于早期阶段,但你可以在这里申请访问。不到 24 小时,我就获得了 Streamlit 团队的访问权限。
收到访问邮件后,使用当前 GitHub 帐户登录 share.streamlit.io。
4.部署
登录后,点击“新建应用”并输入存储库信息。

注意:如果您的 python 依赖项需要操作系统级别的包,您可能需要将 packages.txt 文件添加到您的存储库中。例如,将 OpenCV Python 库与 Streamlit 一起使用需要主机服务器安装 ffmpeg。
在本课中,我们使用 Streamlit 共享免费快速部署了一个 Python 项目。你可以在这里查看最终部署的应用以及 Github 上的所有源代码。
要了解更多关于迷宫求解器背后的算法,或者如何使用 Streamlit 用很少几行 Python 代码创建友好的 web 界面,请查看本系列的第一部分和第二部分。
使用 Dijkstra 的算法和 OpenCV
towardsdatascience.com](/solving-mazes-with-python-f7a412f2493f) [## 为 Python 构建一个简单的 UI
Streamlit:一个基于浏览器的 Python UI,不需要 HTML/CSS/JS
towardsdatascience.com](/building-a-simple-ui-for-python-fd0e5f2a2d8b)
轻松将 TensorFlow 模型部署到生产环境中。
使用 TensorFlow 服务将深度学习模型部署到生产中。
学习使用 TensorFlow 服务将 TensorFlow 模型逐步部署到生产中。
您使用 Tensorflow 创建了一个深度学习模型,对模型进行了微调以获得更好的准确性和精确度,现在想要将您的模型部署到生产中,供用户使用它来进行预测。
将您的模型投入生产的最佳方式是什么?
快速、灵活地部署 TensorFlow 深度学习模型的方法是使用高性能和高度可扩展的服务系统——tensor flow 服务
TensorFlow 服务使您能够
- 轻松管理您的模型的多个版本,如实验版或稳定版。
- 保持您的服务器架构和 API 不变
- 动态发现 TensorFlow 流模型的新版本,并使用一致的 API 结构gRPC(远程过程协议)为其服务。
- 所有客户通过集中模型位置进行推理的一致体验
tensor flow 服务的哪些组件使部署到生产变得容易?

张量流服务架构
TF 服务的主要组成部分包括
- Servables:Servable 是一个底层对象,客户端使用它来执行计算或推理。TensorFlow 服务将深度学习模型表示为一个或多个服务对象。
- 加载器 : 管理服务程序的生命周期,因为服务程序不能管理自己的生命周期。加载器标准化用于加载和卸载服务的 API,独立于特定的学习算法。
- Source : 寻找并提供 servable,然后为 servable 的每个版本提供一个 Loader 实例。
- 管理者 : 管理服务对象的整个生命周期:加载服务对象,服务服务对象,卸载服务对象。
- TensorFlow Core:通过将加载程序和可服务程序作为不透明对象来管理可服务程序的生命周期和指标
假设您有一个模型的两个不同版本,版本 1 和版本 2。
- 客户端通过显式地指定模型的版本或者仅仅请求模型的最新版本来进行 API 调用。
- 管理器监听源代码,并跟踪 Servable 的所有版本;然后,它应用已配置的版本策略来确定应该加载或卸载哪个版本的模型,然后让我们加载适当的版本。
- 加载器包含加载 Servable 的所有元数据。
- 源插件将为 Servable 的每个版本创建一个 Loader 实例。
- 源对管理器进行回调,通知加载器的期望版本被加载,并将其提供给客户端。
- 每当源检测到 Servable 的新版本时,它会创建一个加载器,指向磁盘上的 Servable。
如何在 Windows 10 上部署使用 Tensorflow 服务的深度学习模型?
对于 Windows 10,我们将使用 TensorFlow 服务图像。
第一步:安装 Docker App
步骤 2:提取 TensorFlow 服务图像
**docker pull tensorflow/serving**
一旦你有了张量流服务图像
- 端口 8500 对 gRPC 开放
- 端口 8501 是为 REST API 公开的
- 可选环境变量
**MODEL_NAME**(默认为model) - 可选环境变量
**MODEL_BASE_PATH**(默认为/models)
步骤 3:创建并训练模型
这里,我从张量流数据集中提取了 MNIST 数据集
#Importing required libraries
**import os
import json
import tempfile
import requests
import numpy as np
import tensorflow as tf
import tensorflow_datasets as tfds**#Loading MNIST train and test dataset
#as_supervised=True, will return tuple instead of a dictionary for image and label
**(ds_train, ds_test), ds_info = tfds.load("mnist", split=['train','test'], with_info=True, as_supervised=True)**#to select the 'image' and 'label' using indexing coverting train and test dataset to a numpy array
**array = np.vstack(tfds.as_numpy(ds_train))
X_train = np.array(list(map(lambda x: x[0], array)))
y_train = np.array(list(map(lambda x: x[1], array)))
X_test = np.array(list(map(lambda x: x[0], array)))
y_test = np.array(list(map(lambda x: x[1], array)))**#setting batch_size and epochs
**epoch=10
batch_size=128**#Creating input data pipeline for train and test dataset
# Function to normalize the images**def normalize_image(image, label):
#Normalizes images from uint8` to float32
return tf.cast(image, tf.float32) / 255., label**# Input data pipeline for test dataset
#Normalize the image using map function then cache and shuffle the #train dataset
# Create a batch of the training dataset and then prefecth for #overlapiing image preprocessing(producer) and model execution work #(consumer)**ds_train = ds_train.map(
normalize_img, num_parallel_calls=tf.data.experimental.AUTOTUNE)
ds_train = ds_train.cache()
ds_train = ds_train.shuffle(ds_info.splits['train'].num_examples)
ds_train = ds_train.batch(batch_size)
ds_train = ds_train.prefetch(tf.data.experimental.AUTOTUNE)**# Input data pipeline for test dataset (No need to shuffle the test #dataset)
**ds_test = ds_test.map(
normalize_image, num_parallel_calls=tf.data.experimental.AUTOTUNE)
ds_test = ds_test.batch(batch_size)
ds_test = ds_test.cache()
ds_test = ds_test.prefetch(tf.data.experimental.AUTOTUNE)**# Build the model
**model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(input_shape=(28, 28, 1)),
tf.keras.layers.Dense(128,activation='relu'),
tf.keras.layers.Dense(196, activation='softmax')
])**#Compile the model
**model.compile(
loss='sparse_categorical_crossentropy',
optimizer=tf.keras.optimizers.Adam(0.001),
metrics=['accuracy'],)**#Fit the model
**model.fit(
ds_train,
epochs=epoch,
validation_data=ds_test,
verbose=2)**
第四步:保存模型
通过将 save_format 指定为“tf”将模型保存到协议缓冲文件中。
**MODEL_DIR='tf_model'
version = "1"
export_path = os.path.join(MODEL_DIR, str(version))**#Save the model
**model.save(export_path, save_format="tf")
print('\nexport_path = {}'.format(export_path))
!dir {export_path}**

当我们保存模型的一个版本时,我们可以看到包含文件的以下目录:
- Saved_model.pb :包含一个或多个模型的序列化图形定义,以及作为 MetaGraphDef 协议缓冲区的模型元数据。权重和变量存储在单独的检查点文件中。
- 变量:保存标准训练检查点的文件
您可以使用saved _ model _ CLI命令检查模型。
**!saved_model_cli show --dir {export_path} --all**
步骤 5:使用 Tensorflow 服务为模型提供服务
打开 Windows Powershell 并执行以下命令来启动 TensorFlow 服务容器,以便使用 REST API 端口为 TensorFlow 模型提供服务。
**docker run -p 8501:8501 --mount type=bind,source=C:\TF_serving\tf_model,target=/models/mnist/ -e MODEL_NAME=mnist -t tensorflow/serving**
用 Docker 成功服务 TensorFlow 模型。
- 使用-p 打开端口 8501 为模型提供服务
- Mount 将绑定模型基路径,该路径应该是保存模型的容器位置的绝对路径。
- 通过指定 MODEL_NAME,客户端将用来调用的模型的名称
- 使用-t 选项分配一个伪终端“tensorflow/serving”

docker run 命令的输出
步骤 6:请求模型预测一个 REST
我们将创建一个 JSON 对象来传递预测数据。
#Create JSON Object
**data = json.dumps({“signature_name”: “serving_default”, “instances”: X_test[:20].tolist()})**
请求模型的 predict 方法作为对服务器的 REST 端点的 POST。
**headers = {"content-type": "application/json"}
json_response = requests.post('**[**http://localhost:8501/v1/models/mnist:predict'**](http://localhost:8501/v1/models/mnist:predict')**, data=data, headers=headers)****predictions = json.loads(json_response.text)['predictions']**
检验预测的准确性
**pred=[ np.argmax(predictions[p]) for p in range(len(predictions)) ]
print("Predictions: ",pred)
print("Actual: ",y_test[:20].tolist())**

在下一篇文章中,我们将探索不同的模型服务器配置。
结论:
TensorFlow 服务是一种快速、灵活、高度可扩展且易于使用的方式,使用一致的 gRPC 或 REST APIs 为您的生产模型提供服务。
参考资料:
TensorFlow 服务是一个灵活、高性能的机器学习模型服务系统,专为生产…
www.tensorflow.org](https://www.tensorflow.org/tfx/guide/serving)
https://www . tensor flow . org/tfx/tutorials/serving/rest _ simple # make _ rest _ requests
在 Python 中部署文本分类模型

一个端到端的机器学习项目
学习使用 Dash 和 Heroku 部署基于机器学习的应用程序
本文是我介绍开发一个机器学习项目的整个过程的系列文章的最后一篇。如果你还没有看过前面两篇文章,我强烈建议你在这里做,在这里做。
该项目包括创建一个实时 web 应用程序,该应用程序从几家报纸收集数据,并显示新闻文章中讨论的不同主题的摘要。
这是通过监督机器学习分类模型实现的,该模型能够预测给定新闻文章的类别,通过 web 抓取方法从报纸上获取最新新闻,通过交互式 web 应用向用户显示获取的结果。
正如我在本系列的第篇文章中解释的那样,我写这些文章的原因是因为我注意到,大多数时候,互联网、书籍或文献上发布的关于数据科学的内容都集中在以下方面:我们有一个带标签的数据集,我们训练模型以获得性能指标。这意味着数据标签或模型部署等关键概念被忽略。
然而,事实证明,机器学习和数据科学旨在解决问题和提供有用的信息。所以,拥有一个 99%准确率的模型却不知道如何利用它,会让我们意识到我们已经失去了时间。
这就是为什么在这一系列帖子中,我试图从头到尾涵盖从头构建一个对最终用户有用的机器学习应用程序的所有必要步骤,并为他们提供有价值的见解或信息。
所以,这个项目的整个开发过程被分成了三个不同的岗位:
GitHub 回购可以在这里找到。它包括所有的代码和一个完整的报告。
在第一篇文章中,我们用 Python 开发了文本分类模型,它允许我们获得某篇新闻文章文本,并以整体良好的准确性预测其类别。
在第二篇文章中,我们创建了一个脚本,从不同的报纸上搜集最新的新闻文章并存储文本。
在这篇文章中,我们将把所有的部分放在一起,并部署我们的机器学习模型,以便它可以为最终用户提供有用的、方便的和实时洞察。我们将遵循以下步骤:
- 部署前的考虑事项
- Dash web 应用程序的创建
- 与 Heroku 一起部署
- 最后的想法
部署前的考虑事项
数据
此时,我们已经使用包含 2004 年至 2005 年新闻文章的数据集训练了一个机器学习模型。我们现在的目的是将该模型应用于实时、当前数据。
很容易理解,这可能是我们的 web 应用程序的第一个限制,我们将通过一个简单的例子来了解它:假设我们运行我们的 web 应用程序,并尝试对一篇谈论 iPhone 11 新发布的文章进行分类,并关注其令人惊叹的最先进的功能,如视网膜显示屏、5G 网络支持等…

如果我们回顾 2004 年,最畅销的手机之一是这个:

因此,我们在当前数据中发现的许多术语很可能在 2004 年甚至还不存在,因此也不存在于我们的数据集中。
例如,这是我们样本中一篇文章的摘录:
成千上万的人排了几个小时的队,只为买到运送给零售商的 20 万台 PSP 中的一台。这款掌上游戏机可以玩游戏、听音乐和看电影,明年将在欧洲和北美上市。尽管需求旺盛,索尼表示不会增加计划在年底前发货的 50 万台 PSP 的库存。
你们中的一些人甚至不会记得这个便携式游戏机!
我希望这能让下面的陈述变得简单明了:我们用于训练的数据和我们将在部署后输入模型的数据越相似,就越好。
如果两个阶段的数据不相似,我们将解决所谓的数据不匹配问题。而且,虽然我知道这听起来可能太明显了,但在实践中,我见过很多没有考虑这个问题的模型,这可能导致实时数据的性能非常差,即使我们有一个非常好的训练数据,并因此导致一个无用的应用。
我们如何解决这个问题?在训练我们的模型时,我们应该通过花费大量时间创建特征或者通过超参数调整来获得更高的精度吗?你猜对了:没有。解决这个问题的唯一方法是使用更新的语料库来训练模型。这里没有神奇的机器学习可以提供。
特性
为了将我们的原始文本文章转换为可以输入到机器学习模型中的数字,我们首先通过几个步骤清理文本:删除停用词、词条分类等。之后,我们应用了一个 TF-IDF 矢量化功能将文本转换为数字特征。
因此,当我们部署了我们的应用程序并从报纸上获取了新的文本时,我们将需要转换原始文本,就像我们转换一样。
例如,我们使用了 NLTK 中预先构建的停用词向量。这意味着当我们运行我们的 web 应用程序时,我们将需要以某种方式获得这个向量,以便可以删除这些单词。
关于 TF-IDF 矢量化,我们在这里有一个重要的观点:正如我们在第一篇文章中看到的,这个矢量化工具为文档 d、中的术语 t 计算该术语在该文档中的频率以及逆文档频率,这表示该术语是否在语料库中出现了很多(因此它是一个常用术语)或者没有出现(并且它是一个不常用术语,因此它有点“重要”)。

来源:自己创作
需要注意的是,我们所指的这个语料库是训练语料库。这意味着,当从 web 抓取过程中获取一篇新闻文章时,将只在该文章中计算术语频率,但将在训练语料库中计算逆文档频率。
因此,正如与最新 iPhone 相关的现代单词所发生的那样,如果我们从我们的实时数据中获得一个不在训练语料库中的单词,我们将无法计算 TF-IDF 分数。它将被忽略。我们再次看到了数据不匹配问题的重要性。
环境
我们一会儿会谈到它,但基本上我们的 web 应用程序将包含一个 python 脚本,它将被执行并向我们提供结果。因此,正如 NLTK 停用词向量所发生的那样,我们将需要创建一个环境,在这个环境中,脚本可以被执行,并且拥有所有可用的必要依赖项:从基本库(sklearn、numpy 等等)到训练模型、TF-IDF 向量器等等…
用户体验
最后,我们需要关注用户体验。因此,举个例子,如果我们花了 2 分钟从某份报纸上抓取最新的 5 篇文章,我们可能不应该把它作为用户的一个选项。
一旦我们总结了部署模型时需要考虑的所有事情,很明显,只关注在训练集中获得良好的准确性而不考虑所有这些因素会导致我们成为无用的 web 应用程序。
讨论完这些问题后,我们将看看如何用 Dash 创建应用程序,并用 Heroku 部署它。Dash 和 Heroku 有非常好的文档,所以我不会在这里花太多时间讨论技术细节。任何人都可以在几个小时内学会这两种方法,我认为我们一直在讨论的方法学问题更有价值。
Dash web 应用程序的创建
Dash 是一个用于构建 web 应用程序的高效 Python 框架。它是基于 Flask、Plotly.js 和 React.js 编写的,使用起来非常简单,但效果惊人。在 Dash 网页上有一个非常好的教程,它涵盖了从零开始创建一个 web 应用程序,解释了每一个步骤:安装、布局(定义了我们的应用程序的外观)、回调(定义了“发生的事情”)以及一些高级概念,这些概念将让我们按照我们想要的那样构建应用程序。
为了创建 web 应用程序的代码,我们可以在本地执行它,应用程序将显示在浏览器中。通过这种方式,我们可以在部署应用程序之前进行简单的更改并构建我们想要的应用程序。
我的 web 应用程序下的代码可以在这里找到。
在我们准备好代码之后,最后一步是部署应用程序。
与 Heroku 一起部署
有许多平台允许我们部署 web 应用程序。两个好的是 Dash Enterprise 和 Heroku。我使用 Heroku 是因为你可以免费部署一个应用程序(有一些限制),花很少的钱你就可以得到一个全功能的服务器。
同样,Heroku 有一个非常好的教程,可以在这里找到。它一步一步地涵盖了部署应用程序所需的所有内容。
对于这个项目,我通过 anaconda 在 Windows 中部署了这个应用程序。我遵循的步骤是:
# after signing in to Heroku and opening the anaconda prompt
# we create a new folder
$ mkdir dash-app-lnclass
$ cd dash-app-lnclass# initialize the folder with git
$ git init
之后,我们创建一个环境文件( environment.yml ),在这个文件中我们将指出我们将需要的依赖项:
name: dash_app_lnclass #Environment name
dependencies:
- python=3.6
- pip:
- dash
- dash-renderer
- dash-core-components
- dash-html-components
- dash-table
- plotly
- gunicorn # for app deployment
- nltk
- scikit-learn
- beautifulsoup4
- requests
- pandas
- numpy
- lxml
并激活环境:
$ conda env create
$ activate dash_app_lnclass
然后,我们用 app.py,requirements.txt 和一个 Procfile: 初始化这个文件夹
# the procfile must contain the following line of code
web: gunicorn app:server# to create the requirements.txt file, we run the following:
$ pip freeze > requirements.txt
最后,由于我们将使用 nltk 下载(用于停用词和其他功能)和 pickles,我们需要添加 nltk.txt 文件和 Pickles 文件夹。
最后,我们初始化 Heroku,将文件添加到 Git 并部署:
$ heroku create lnclass # change my-dash-app to a unique name
$ git add . # add all files to git
$ git commit -m 'Comment'
$ git push heroku master # deploy code to heroku
$ heroku ps:scale web=1 # run the app with a 1 heroku "dyno"
详细说明可以在这里找到。
一旦我们完成了所有的步骤,我们现在就可以使用我们的 web 应用程序了!可以在这个 链接 中找到。
请注意,此应用程序尚未进行定期维护,因此您可能会遇到一些错误。
最终想法
所以这一系列的文章就告一段落了。我们已经介绍了创建基于机器学习的应用程序的整个过程,从获取训练数据到创建和部署应用程序。我希望它是有用的,并且阐明了面对一个新项目时需要考虑的所有步骤和注意事项。我在这三篇文章中展示了我的想法和建议,它们可以用几个段落来概括:
永远不要忘记你正在追求的目标:机器学习模型确实很棒,但最终,如果它们不能提供一些实用性,它们就毫无价值。因此,重要的是要始终牢记我们为用户提供的是什么工具。
另外,不失去项目的端到端视野也是极为有利的。例如,当我们处于模型训练阶段时,我们需要记住这一步之前的事情,例如当部署应用程序时,数据将如何避免数据不匹配。
希望这些文章是有用的,如果你有任何问题,不要犹豫与我联系!
在 2.0 中使用 TensorFlow Serving + Docker 部署文本分类器
在本教程中,我们使用一个接受原始字符串进行推理的 API 端点来简化模型预测。我们还对模型签名进行了实验,以获得更加可定制的有效负载。

马库斯·温克勒在 Unsplash 上的照片
这里是GitHub repo的全部代码。
大约一年前,我写了Deploy a Keras Model for Text Classification 使用 tensor flow Serving在 TensorFlow 1.X 中部署文本分类器。x 更容易使用,我很难找到我需要的文档,特别是关于部署和迁移 TensorFlow 服务的已弃用的 V1 功能。
我已经收集了我的知识,并将通过一个玩具示例演示模型部署。
如果这是你第一次用 TensorFlow 2。x,我建议学习这个课程来构建、训练和部署模型。
本课程的重点是利用 TensorFlow 2.x 和 Keras 的灵活性和“易用性”来构建、培训和…
click.linksynergy.com](https://click.linksynergy.com/link?id=J2RDo*Rlzkk&offerid=759505.12488204614&type=2&murl=https%3A%2F%2Fwww.coursera.org%2Flearn%2Fintro-tensorflow)
在 TF 1 中,文本预处理是一场噩梦。X …

Sebastian Herrmann 在 Unsplash 上拍摄的照片
特别是 2。x 引入了几个新功能,使得使用文本模型变得更加容易。1 的最大痛点之一。x 是如何处理矢量化层。要求消费者应用程序为我的推理 API 提供向量输入并不总是可行的。
因此,创建了许多丑陋的变通方法来允许模型接受原始字符串。点击这里查看我的标记化/截断/填充回退。
在许多情况下,预测端点必须包装在另一个端点中,以处理预处理步骤。这造成了一种令人讨厌的情况,即预处理逻辑位于两个不同的地方:用于训练模型的模块和将客户机的原始文本转换成向量的包装器。
让我们看看如何在 2.X 中解决这个问题。*
目标:创建一个 API 端点,该端点以原始字符串的形式接受电影评论,并返回评论为正面的概率
这是一个标准的情绪分析任务。为了确保我们构建的解决方案是端到端的:
- 服务端点将负责预处理原始字符串,并为模型对其进行矢量化
- 除了 TensorFlow 服务,我们不会使用任何其他框架
如果你想更进一步,有很多关于将 TensorFlow 模型部署到云平台(如 GCP 或 AWS)的课程和资源。
* [## 基于 GCP tensor flow 的端到端机器学习
由谷歌云提供。在本专业的第一门课程中,我们将回顾机器中涵盖的内容…
click.linksynergy.com](https://click.linksynergy.com/link?id=J2RDo*Rlzkk&offerid=759505.13223275109&type=2&murl=https%3A%2F%2Fwww.coursera.org%2Flearn%2Fend-to-end-ml-tensorflow-gcp)
属国
我建议分叉或克隆我的 GitHub repo 并从那里开始跟进。
本文对每个步骤进行了更详细的解释。如果您只是想让一些东西启动并运行起来,那么可以按照我的 README.md 中的说明来做。README.md 包括如何训练和服务模型的细节。
数据集:IMDB 电影评论

乔恩·泰森在 Unsplash 上的照片
该数据集包含 25,000 条用于训练的高度极性电影评论,以及另外 25,000 条用于测试的评论。每条影评都标注为 0(负面情绪)或 1(正面情绪)。关于数据集的更多信息可以在这里找到。
我们将训练一个二元分类器来预测给定电影评论是正面的概率。
代码
我将在一个ModelTrainer类中组织我的大部分代码,该类处理模型的端到端训练和部署。让我们一步一步来。
依赖关系
首先,我们加载将要使用的库。我还定义了一个logger来跟踪培训过程中的重要事件。在较大的项目中,日志记录通常比打印语句更受青睐,因为它更容易跟踪(更容易看到日志来自哪里)、可配置并且更容易存储。
模特教练班
我在这里将模型架构参数定义为属性。在一个更复杂的项目中,将它们移动到一个配置文件中可能更有意义。下面是每个属性所指内容的快速分类:
embed_size:每个令牌嵌入的维度max_features:你词汇量的最大值epochs:训练集的迭代次数batch_size:一次处理的观察次数max_len:每次观察的令牌数;较短的长度将被填充,而较长的长度将被截断
稍后我们将讨论tf_model_wrapper属性。
获取数据
在这个类中,我定义了一个名为fetch_data的方法,它将通过编程从tensorflow_datasets下载训练和测试数据。这种下载数据集的方法效率很低。数据集不会保存在任何地方,每次执行脚本时都需要重新加载。
矢量化图层
这是获取原始字符串并将其转换为与我们的模型架构兼容的矢量化输出的层。我们还在这一层中构建了预处理步骤,以便在矢量化之前对原始文本进行预处理。
预处理在custom_preprocessing方法中定义。我们在这里做三件事:
- 将文本转换为小写
- 在我们的影评中经常出现的脱衣
<br /> - 去除标点符号
在init_vectorize_layer中返回的TextVectorization对象将返回一个完全适合的层,该层适应于所提供的文本(这是来自我们的训练数据的电影评论)。除了自定义预处理功能,我们还定义了最大令牌数、输出序列长度和输出模式。
初始化模型
首先,我们创建vectorize_layer并定义输入类型(单个字符串)。我们通过矢量化层传递原始输入,然后将输出传递给模型架构的其余部分。
我已经把一个简单的 RNN 和一个双向 GRU 层放在了一起。出于说明发球的目的,我没有花太多时间来完善这个模型。我敢肯定,找到一个针对该数据集实现更好结果的模型架构并不困难。
训练模型
我们在train方法中做的第一件事是使用fetch_data加载训练数据。在这个玩具示例中,我们将不会加载测试数据,因为我们跳过了模型评估。模型评估非常重要,在更实际的场景中不应该被忽略。
我们使用init_model方法初始化模型,并通过train_examples来拟合我们的矢量化图层。接下来是在训练数据上拟合模型。
在这个要点的第 4 行,我们最终通过创建一个新的TFModel类的实例来定义我们的tf_model_wrapper对象。该对象的目的是将签名合并到服务模型中。
我将在这里绕道谈论模型签名,以及为什么您可能想要合并它们。
模型签名
TensorFlow 文档上的这个页面解释了签名用于提供“识别函数输入和输出的一般支持,并且可以在构建 SavedModel 时指定”。
签名定义需要指定:
inputs作为字符串到 TensorInfo 的映射。
outputs作为字符串到 TensorInfo 的映射。
method_name(对应加载工具/系统中支持的方法名)。
通过定制输入,我们可以在推理之前加入额外的预处理步骤。通过定制输出,我们可以定制来自服务模型的有效负载。
在本例中,我们将创建一个签名,以便在预测中包含一些有用的元数据。
创建支持签名的包装器
我们将创建一个TFModel作为模型的包装器。初始化时,TFModel对象将接受一个tf.keras.Model并将它保存为一个model属性。这个初始化步骤非常灵活,可以用来传递额外的参数。
我们使用@tf.function装饰器定义了一个prediction方法。这个装饰器将函数转换成可调用的张量流图。input_signature参数指定将提供给签名的形状和数据类型。这个方法的输出成为我们服务模型时的输出。
我们的服务模型有效载荷将有两个字段:一个包含模型输出的prediction字段和一个硬编码的description字段。
对于我们的用例,模型输出相当直观,不完全需要description。然而,当类标签不清楚或者额外的元数据可能有帮助时,这就变成了一个有用的指示器。
我们还想传递哪些元数据?
世界是你的!这里有一些想法可能会让你以后的生活更轻松。
可听度和再现性
考虑添加有助于调查和重现特定预测的元数据。
- 用于训练该模型的数据集是什么?
- 如果我想在我的机器上重建这个模型,我可以在哪里找到模型资产?
- 用于训练模型的代码在哪里?使用了什么版本的代码(即 Git SHA/pull 请求编号)来训练模型?
解释
你的模型的最终消费者可能不是熟悉机器学习的人。在没有任何解释的情况下传递类别概率和相应标签的列表可能会令人困惑。考虑通过顶部预测和相关概率。
使用
有时,输出反映您的预期用途可能会有所帮助。也许你有一个不同型号的标量输出的阈值?您可以使用元数据来明确您的预期用途。*
部署模型
部署步骤非常简单。我们将模型保存到本地目录,并将serving_default签名定义为来自我们tf_model_wrapper.的prediction方法
实际上拯救了什么?
该模型被序列化为 SavedModel 对象,可用于推理。在此过程中,整个 TensorFlow 会话被导出为包含在单个目录中的语言不可知格式。
该目录具有以下结构:
*assets/
assets.extra/
variables/
variables.data-?????-of-?????
variables.index
saved_model.pb*
- saved_model.pb 定义数据流结构
- 资产是包含所有辅助模型文件的子目录
- assets.extra 是包含由其他库生成的资源的子目录
- 变量是一个子目录,包含用于恢复模型的权重
指定模型版本
默认情况下,TensorFlow 服务将始终为您的模型提供最新版本。“最新”版本是从 SavedModel 目录名推断出来的。对于这个例子,我根据训练时的整数时间戳命名了 SavedModel 目录,因此总是提供最新的模型。
为模型服务
确保您在此步骤之前训练了模型。可以通过在克隆的 repo 的根目录下运行python -m classifier.train来训练模型。这将运行上述代码。
是时候为模特服务了!确保为这一步安装了 Docker。
- 使用
docker pull tensorflow/serving获取 TensorFlow 服务图像的最新版本 - 在您克隆 GitHub repo 的根目录中,根据 SavedModel 文件的路径创建一个环境变量。如果你按照自述文件上的说明,这将是
export ModelPath=”$(pwd)/classifier” - 启动服务器并为 REST API 端点公开端口 8501:
*docker run -t --rm -p 8501:8501 \
-v "$ModelPath/saved_models:/models/sentiment_analysis" \
-e MODEL_NAME=sentiment_analysis \
tensorflow/serving*
会出现一堆日志。每个日志中的第一个字符将指示进程的状态。
- E =错误
- W =警告
- I =信息
下面是最初几行可能的样子。
*docker run -t --rm -p 8501:8501 -v "$ModelPath/:/models/sentiment_analysis" -e MODEL_NAME=sentiment_analysistensorflow/servingI tensorflow_serving/model_servers/server.cc:82] Building single TensorFlow model file config: model_name: sentiment_analysis model_base_path: /models/sentiment_analysis
I tensorflow_serving/model_servers/server_core.cc:461] Adding/updating models.*
如果每个日志都以 I、开头,那么恭喜您——该模型已经成功提供了!
注意:让日志淹没你的终端可能有点烦人。使用分离模式,所以它不会这样做。下面命令的唯一区别是增加了一个-d标志。
*docker run -t -d --rm -p 8501:8501 \
-v "$ModelPath/saved_models:/models/sentiment_analysis" \
-e MODEL_NAME=sentiment_analysis \
tensorflow/serving*
有用的 Docker 命令
这里有两个有用的 Docker 命令,在使用模型服务器时可能会派上用场:
docker ps-显示哪些 Docker 容器正在运行;这对于获取容器 id 以便进一步操作非常有用docker kill [container id]-如果您构建了错误的模型,您可以终止当前容器来释放端口并重启服务器
发布请求
既然我们的模型服务器已经在本地机器上启动并运行,我们就可以发送一个示例 POST 请求了。POST 请求可以通过 curl 发送,这是一个用于在服务器之间传输数据的简单工具,也可以通过 Python 中的request库发送。
样本卷曲命令:
我们通过了“史上最差电影”的评论。
*curl -d '{"inputs":{"review": ["worst movie EVER"]}}' \
-X POST http://localhost:8501/v1/models/sentiment_analysis:predict*
对应输出:
不出所料,“史上最差电影”被认为不太可能是正面评价。
*{ "outputs": { "prediction": [[ 0.091893291 ]], "description": "prediction ranges from 0 (negative) to 1 (positive)" } }*
这次到此为止。希望这篇文章对你有帮助!快乐大厦。
参考
- https://keras . io/examples/NLP/text _ class ification _ from _ scratch/
- https://www.tensorflow.org/api_docs
感谢您的阅读!
通过 Medium 关注我的最新动态。😃
作为一个业余爱好项目,我还在www.dscrashcourse.com建立了一套全面的免费数据科学课程和练习题。
再次感谢您的阅读!📕
使用 Flask 部署已训练的 ML 模型
端到端 ML 项目教程系列的第 2 部分

继我上一篇关于端到端机器学习项目教程的文章之后,我们讨论了构建一个健壮的 ML 模型的主要任务,这篇文章为你提供了一个在 web 上部署 ML 模型的简单快速的解决方案。
这是我们在这里开始的端到端 ML 油耗项目的最后一项任务。
部署应用程序需要什么?
为了部署任何经过训练的模型,您需要以下内容:
- 准备部署的已训练模型 —将模型保存到文件中,以供 web 服务进一步加载和使用。
- 一个 web 服务——为你的模型在实践中的使用提供一个目的。对于我们的燃料消耗模型,它可以使用车辆配置来预测其效率。我们将使用 Flask 来开发这项服务。
- 云服务提供商——你需要特殊的云服务器来部署应用程序,为了简单起见,我们将使用 Heroku(数据工程系列将涵盖 AWS 和 GCP)来完成这一任务。
让我们从逐一查看这些流程开始。
保存训练好的模型
一旦您有足够的信心将经过培训和测试的模型带入生产就绪环境,第一步就是将它保存到. h5 或。使用类似于pickle的库来绑定文件。
确保您的环境中安装了pickle。
接下来,让我们导入模块并将模型转储到一个.bin文件中:
import pickle##dump the model into a file
with open("model.bin", 'wb') as f_out:
pickle.dump(final_model, f_out) # write final_model in .bin file
f_out.close() # close the file
这将把您的模型保存在您当前的工作目录中,除非您指定一些其他的路径。
是时候测试我们是否能够使用该文件加载我们的模型并进行预测了,我们将使用相同的(如 prev blog 中所定义的)车辆配置:
##vehicle config
vehicle_config = {
'Cylinders': [4, 6, 8],
'Displacement': [155.0, 160.0, 165.5],
'Horsepower': [93.0, 130.0, 98.0],
'Weight': [2500.0, 3150.0, 2600.0],
'Acceleration': [15.0, 14.0, 16.0],
'Model Year': [81, 80, 78],
'Origin': [3, 2, 1]
}
让我们从文件中加载模型:
*##loading the model from the saved file*
**with** open('model.bin', 'rb') **as** f_in:
model = pickle.load(f_in)
在vehicle_config上做预测
##defined in prev_blog
predict_mpg(vehicle_config, model)##output: array([34.83333333, 18.50666667, 20.56333333])
输出与我们之前使用final_model预测的一样。
开发网络服务
下一步是将这个模型打包到一个 web 服务中,当通过 POST 请求获得数据时,该服务会返回 MPG(英里/加仑)预测作为响应。
我使用的是 Flask web 框架,这是一个常用的用 Python 开发 web 服务的轻量级框架。在我看来,这可能是实现 web 服务最简单的方法。
Flask 只需要很少的代码就可以让您入门,并且您不需要担心处理 HTTP 请求和响应的复杂性。
以下是步骤:
- 为您的 flask 应用程序创建一个新目录。
- 使用 pip 设置安装了依赖项的专用环境。
- 安装以下软件包:
pandas
numpy
sklearn
flask
gunicorn
seaborn
下一步是激活这个环境,并开始开发一个简单的端点来测试应用程序:
创建一个新的文件,main.py,并导入烧瓶模块:
from flask import Flask
通过实例化 Flask 类来创建 Flask 应用程序:
##creating a flask app and naming it "app"
app = Flask('app')
创建一个路由和与之对应的函数,该函数将返回一个简单的字符串:
[@app](http://twitter.com/app).route('/test', methods=['GET'])
def test():
return 'Pinging Model Application!!'
上面的代码利用了 decorator——一种高级的 python 特性。你可以在这里阅读更多关于装饰者的信息。我们不需要对装饰者有很深的理解,只需要在test()函数上添加一个装饰者@app.route就可以将 web 服务地址分配给那个函数。
现在,要运行应用程序,我们需要最后这段代码:
if __name__ == ‘__main__’:
app.run(debug=True, host=’0.0.0.0', port=9696)
run 方法启动我们的 flask 应用程序服务。这 3 个参数指定:
debug=True—当应用程序遇到任何代码变化时,自动重启应用程序host=’0.0.0.0'—公开 web 服务port=9696—我们用来访问应用程序的端口
现在,在你的终端运行main.py
python main.py

在浏览器中打开 URLhttp://0 . 0 . 0 . 0:9696/test将在网页上打印响应字符串:

现在,应用程序正在运行,让我们来运行模型:
创建一个新目录model_files来存储所有与模型相关的代码。
在这个目录中,创建一个 ml_model.py 文件,该文件将包含数据准备代码和我们在这里编写的预测函数。
复制并粘贴您在第一部分中导入的库和预处理/转换函数。该文件应该如下所示:
在同一个目录中,也放置您保存的model.bin文件。
现在,在main.py中,我们将导入 predict_mpg 函数来进行预测,但是要这样做,我们需要创建一个空的__init__.py 文件来告诉 Python 这个目录是一个包。

您的目录应该有这样的树:
接下来,定义将接受来自 HTTP POST 请求的vehicle_config并使用模型和predict_mpg()方法返回预测的predict/路由。
在您的 main.py 中,第一次导入:
import pickle
from flask import Flask, request, jsonify
from model_files.ml_model import predict_mpg
然后添加predict路线和相应的功能:
- 这里,我们将只接受函数的 POST 请求,因此我们在装饰器中有
methods=[‘POST’]。 - 首先,我们使用
get_json()方法从请求中获取数据(vehicle_config ),并将其存储在变量 vehicle 中。 - 然后,我们从
model_files文件夹中的文件将训练好的模型加载到模型变量中。 - 现在,我们通过调用 predict_mpg 函数并传递
vehicle和model来进行预测。 - 我们为预测变量中返回的数组创建一个 JSON 响应,并将这个 JSON 作为方法响应返回。
我们可以使用 Postman 或requests包来测试这个路由,启动运行 main.py 的服务器,然后在您的笔记本中,添加以下代码来发送带有vehicle_config的 POST 请求:
import requestsurl = “[http://localhost:9696/predict](http://localhost:9696/predict)"
r = requests.post(url, json = vehicle_config)
r.text.strip()##output: '{"mpg_predictions":[34.60333333333333,19.32333333333333,14.893333333333333]}'
太好了!现在,到了最后一部分,当部署在远程服务器上时,同样的功能应该工作。
在 Heroku 上部署应用程序

要在 Heroku 上部署这个 flask 应用程序,您需要遵循以下非常简单的步骤:
- 在主目录中创建一个
Procfile——它包含在服务器上运行应用程序的命令。 - 在 Procfile 中添加以下内容:
web: gunicorn wsgi:app
我们使用 gunicorn(之前安装的)来部署应用程序:
Gunicorn 是一个用于 WSGI 应用程序的纯 Python HTTP 服务器。它允许您通过在一个 dyno 中运行多个 Python 进程来同时运行任何 Python 应用程序。它提供了性能、灵活性和配置简单性的完美平衡。
3.创建一个wsgi.py文件并添加:
##importing the app from main file
from main import appif __name__ == “__main__”:
app.run()
确保从main.py中删除运行代码。
4.将所有 python 依赖关系写入 requirements.txt:
你可以使用pip freeze > requirements.txt或者简单地把上面提到的包列表+你的应用程序正在使用的任何其他包。
5.使用终端,
- 初始化一个空的 git 存储库,
- 将文件添加到临时区域
- 将文件提交到本地存储库:
$ git init
$ git add .
$ git commit -m "Initial Commit"
6.创建 Heroku 帐户如果您还没有,请登录 Heroku CLI:
heroku login
弹出页面时批准从浏览器登录:
7.创建烧瓶应用程序:
heroku create <name of your app>
我把它命名为mpg-flask-app。它将创建一个 flask 应用程序,并会给我们一个应用程序将被部署的 URL。
8.最后,将所有代码推送到 Heroku remote:
$ git push heroku master
瞧啊。您的 web 服务现在已经部署在 https://mpg-flask-app.herokuapp.com/predict 的上了。
同样,通过发送相同的车辆配置,使用request包测试端点:

这样,您就拥有了构建更复杂的 ML 应用程序所需的所有主要技能。
这个项目可以参考我的 GitHub 资源库:
70 年代和 80 年代车辆油耗预测的端到端机器学习项目。GitHub 是超过 50 个…
github.com](https://github.com/dswh/fuel-consumption-end-to-end-ml)
你可以和我一起开发整个项目:
下一步!
这仍然是一个简单的项目,在接下来的步骤中,我建议你使用一个更复杂的数据集,也许可以选择一个分类问题并重复这些任务直到部署。
数据科学与 Harshit —我的 YouTube 频道
但是如果你不想等待,这里是我的 YouTube 频道上的完整教程系列(播放列表),你可以在这个项目上跟随我。
通过这个渠道,我计划推出几个覆盖整个数据科学领域的系列。以下是你应该订阅频道的原因:
- 这些系列将涵盖每个主题和子主题的所有必需/要求的高质量教程,如数据科学的 Python 基础。
- 解释了为什么我们在 ML 和深度学习中这样做的数学和推导。
- 与谷歌、微软、亚马逊等公司的数据科学家和工程师以及大数据驱动型公司的首席执行官的播客。
- 项目和说明实施到目前为止所学的主题。了解新的认证、训练营以及破解这些认证的资源,例如 Google 举办的 TensorFlow 开发者证书考试。
使用 OpenVINO 部署 AI Edge 应用程序
在我之前的文章中,我已经讨论了 OpenVINO 工具包的基础,OpenVINO 的模型优化器和推理机。在这篇文章中,我们将探索:-
- 计算机视觉模型的类型。
- OpenVINO 的预训练模型。
- 下载预先训练好的模型。
- 使用预先训练的模型部署 Edge 应用程序。

图片:来源
计算机视觉模型的类型
有不同类型的计算机视觉模型用于各种目的。但是三个主要的计算机视觉模型是:-
- 分类
- 目标检测
- 分割
分类模型识别给定图像或图像中对象的“类别”。分类可以是二元的,即“是”或“否”,或者成千上万的类别,如人、苹果、汽车、猫等..有几种分类模型,如 ResNet、DenseNet、Inception 等..
对象检测模型用于确定图像中存在的对象,并且经常在检测到的对象周围绘制边界框。它们还使用分类来识别边界框内对象的类别。您还可以设置边界框的阈值,以便拒绝低阈值检测。RCNN、Fast-RCNN、YOLO 等。是对象检测模型的一些例子。
分割模型在给定图像中执行逐像素分类。有两种不同类型的分段-语义分段和实例分段。在语义分割中,属于同一类的所有对象被认为是相同的,而在实例分割中,每个对象被认为是不同的,即使它属于同一类。例如,如果在一幅图像中有五个人,语义分割模型将把他们都视为相同,而在实例分割模型中,他们都将被不同地对待。优信网、DRN 等..
OpenVINO 中的预训练模型
预训练模型,顾名思义,是已经被训练得具有高精度甚至尖端精度的模型。训练深度学习模型需要大量的时间和计算能力。虽然,创建自己的模型并通过微调超参数(隐藏层数、学习率、激活函数等)来训练它是令人兴奋的。)以达到更高的精度。但是,这需要几个小时的工作。
通过使用预先训练的模型,我们避免了大规模数据收集和长时间高成本培训的需要。了解如何预处理输入和处理网络输出后,您可以将这些内容直接插入到您自己的应用程序中。
OpenVINO 在模型动物园里有很多预先训练好的模型。模型动物园有自由模型集和公共模型集,自由模型集包含已转换为中间表示的预训练模型。xml 和。bin)使用模型优化器。这些模型可以直接用于推理机。公共模型集包含预先训练的模型,但是这些模型不会被转换为中间表示。
下载预先训练的模型
在本文中,我将从开放模型动物园加载“车辆-属性-识别-障碍-0039”模型。
要下载预先训练的模型,请遵循以下步骤(在命令提示符/终端中键入命令):-
- 导航到模型下载器目录
对于 Linux:-
cd /opt/intel/openvino/deployment_tools/open_model_zoo/tools/model_downloader
对于 Windows:-
cd C:/Program Files (x86)/IntelSWTools/openvinodeployment_tools/open_model_zoo/tools/model_downloader
我在上面的命令中使用了默认的安装目录,如果您的安装目录不同,那么请导航到适当的目录。
2.运行下载程序. py
下载器 Python 文件需要一些参数,您可以使用“-h”参数来查看可用的参数。
python downloader.py -h
让我们下载模型,
python downloader.py --name vehicle-attributes-recognition-barrier-0039 --precisions -FP32 --output_dir /home/pretrained_models
- —名称 →型号名称。
- —精度 →型号精度(FP16、FP32 或 INT8)。
- — output_dir →保存模型的路径。
成功下载模型后,导航到下载模型的路径,您将找到。xml“和”。bin "文件的模型。
请参考文档以了解关于该模型的更多细节(输入和输出)。
部署边缘应用
现在,由于我们已经下载了预训练模型,让我们在 Edge 应用程序中部署它。
让我们创建一个文件“inference.py”来定义和使用推理引擎。在我的上一篇文章中,关于推理引擎,我已经使用了不同的函数,但是这里我将定义一个类。
from openvino.inference_engine import IENetwork, IECore**class** Network:
**def** __init__(self):
self.plugin = None
self.network = None
self.input_blob = None
self.exec_network = None
self.infer_request = None **def** load_model(self):
self.plugin = IECore()
self.network = IENetwork(model='path_to_xml', weights='path_to_bin')
### Defining CPU Extension path
CPU_EXT_PATH= "/opt/intel/openvino/deployment_tools/inference_engine/lib/intel64/ libcpu_extension_sse4.so" ### Adding CPU Extension
plugin.add_extension(CPU_EXT_PATH,"CPU") ### Get the supported layers of the network
supported_layers = plugin.query_network(network=network, device_name="CPU") ### Finding unsupported layers
unsupported_layers = [l **for** l **in** network.layers.keys() **if** l **not** **in** supported_layers] ### Checking for unsupported layers
**if** len(unsupported_layers) != 0:
print("Unsupported layers found")
print(unsupported_layers)
exit(1) ### Loading the network
self.exec_network = self.plugin.load_network(self.network,"CPU") self.input_blob = next(iter(self.network.inputs))
print("MODEL LOADED SUCCESSFULLY!!!) **def** get_input_shape(self):
return self.network.inputs[self.input_blob].shape **def** synchronous_inference(self,image):
self.exec_network.infer({self.input_blob: image}) **def** extract_output(self):
return self.exec_network.requests[0].outputs
别糊涂了!我会解释每一个功能。
- init(self):
它是类网络的构造器,在那里我初始化了类的数据成员。
- load_model(self):
顾名思义,它用于加载模型(预训练),在这个函数中我们:-
▹声明了一个 iecore 对象。
▹声明了一个 ienetwork 对象。
▹加载了模型 xml 和 bin 文件。
▹检查了不受支持的层
▹在 iecore 对象中加载 ienetwork 对象。
- 获取 _ 输入 _ 形状(自身):
返回模型所需的输入形状
- 同步 _ 推论(自我,形象):
对输入图像执行同步推理
- 提取 _ 输出(自我):
推理完成后返回模型的输出。
这就是“推论. py”,现在让我们创建一个文件“main.py”。
import cv2
import numpy as np
from inference import Network def preprocessing(image,height,width): ### Resize the Image
image = cv2.resize(image,(width,height)) ### Add color channel first
image = image.transpose((2,0,1)) ### Add Batch Size
image = np.reshape((image,(1,3,height,width))
return image
- 使用 OpenCV 的 resize()调整图像大小时,应该先给出宽度,再给出高度。
- 根据文档,模型首先读取通道,然后读取图像尺寸,但是 OpenCV 首先读取图像尺寸,然后读取通道,所以我使用了 transpose(),首先带来颜色通道。
- 该模型将输入作为(batch_size,color_channels,height,width ),因此我们对图像进行整形,以给出为 1 的“batch_size”。
def main():
### Read the image
image = cv2.imread('path_to_image') ### Declare a Network Object
plugin = Network() ### Input shape required by model
input_shape = plugin.get_input_shape() height = input_shape[2]
width = input_shape[3] ### Preprocess the input
p_image = preprocessing(image,height,width) ### Perform Synchronous Inference
plugin.synchronous_inference(p_image) ### Extract the output
results = plugin.extract_output()
根据文档,模型的输出(结果)是一个字典,其中包含以下信息
- “颜色”,形状:[1,7,1,1] —七种颜色类别的 Softmax 输出[白色、灰色、黄色、红色、绿色、蓝色、黑色]
- “类型”,形状:[1,4,1,1] —跨四个类型类别[轿车、公共汽车、卡车、货车]的 Softmax 输出
由于它是 softmax 输出,我们需要将最大值的索引与颜色和类型进行映射。
color = ['white','grey','yellow','red','green','blue','black']
vehicle = ['car','bus','truck','van'] ### Finding out the color and type
result_color = str(color[np.argmax(results['color'])])
result_type = str(vehicle[np.argmax(results['type'])])### Add details to image
font = cv2.FONT_HERSHEY_SIMPLEX
font_scale = 1
col = (0, 255,0) #BGR
thickness = 2
color_text= 'color: '+result_color
type_text = 'vehicle: '+result_type
cv2.putText(image,color_text,(50,50), font, font_scale, col, thickness, cv2.LINE_AA)
cv2.putText(image,type_text,(50,75), font, font_scale, col, thickness, cv2.LINE_AA) ### Save the image
cv2.imwrite('path/vehicle.png',image)if __name__=="__main__":
main()
我尝试了两辆车,得到了以下输出:-


来源:作者
好了,大家都到齐了。我希望现在你已经对如何使用 OpenVINO 部署 AI edge 应用程序有了正确的理解。OpenVINO 为多种应用提供了各种预训练模型。尝试实现 OpenVINO model zoo 中可用的不同预训练模型,并创建自己的 edge 应用程序。非常感谢您阅读我的文章。
使用 Python 部署影像分类 Web 应用程序
如何使用 Streamlit 和 Heroku 部署您的机器学习模型

图片来源: Unsplash
毫无疑问,做一个数据科学和机器学习项目,从收集数据开始,处理数据,可视化关于数据的见解,并开发一个机器学习模型来完成预测任务,是一件有趣的事情。更有趣和可行的是,我们可以在本地机器上完成所有这些步骤,然后就可以完成了。
然而,如果其他人可以利用我们的机器学习模型来做有趣和酷的事情,这不是很棒吗?当我们的模型可以进入其他人的手中,他们可以从中做有用的东西时,机器学习的真正魔力就来了。
创建一个 web 应用程序是解决方案之一,这样其他人就可以利用我们的机器学习模型。幸运的是,现在创建一个 web 应用程序非常简单。
如果您正在使用 Python,您可以使用 Streamlit 库在本地机器上创建一个简单的机器学习 web 应用程序。要部署 web 应用程序,使其可供其他人访问,那么我们可以使用 Heroku 或其他云平台。在本文中,我将一步一步向您展示如何使用 Python、Streamlit 和 Heroku 创建自己的简单图像分类 web 应用程序。
如果您还没有安装 Streamlit,您可以通过在提示符下运行以下 pip 命令来安装它。
pip install streamlit
图像分类数据
对于这个图像分类示例,将使用 Laurence Moroney 创建的石头-纸-剪刀数据集。你可以在他的网站上下载数据。总之,石头-纸-剪刀是一个合成的数据集,它包含人们形成石头、纸或剪刀形状的手。总共有 2520 幅训练图像和 372 幅测试图像。
下面是合成图像数据的预览图:

先睹为快石头剪刀布数据集的训练图像
总的来说,本文将涵盖三个步骤:
- 创建第一个 Python 文件来加载数据、构建模型并最终训练模型。
- 创建第二个 Python 文件来加载模型和构建 web 应用程序。
- 使用 Heroku 部署 web 应用程序。
加载数据、构建模型和训练模型
首先,下载训练集和测试集,并将其保存到您选择的目录中。接下来,您需要解压缩它们。将有两个文件夹,一个称为‘RPS’用于训练图像,另一个称为‘RPS-test-set’用于测试图像。之后创建一个名为rps_model.py的 Python 文件来加载数据,建立机器学习模型,训练模型。
加载数据
在构建模型之前,您需要首先使用os库指定本地机器中训练集文件夹和测试集文件夹的路径。
import ostrain_dir = os.path.join('directory/to/your/rps/')
test_dir = os.path.join('directory/to/your/rps-test-set/')
接下来,我们可以使用 TensorFlow 库中的图像生成器来生成训练集和测试集,并自动标记数据。使用 image generator 的另一个优点是,我们可以“即时”进行数据扩充,通过缩放、旋转或移动训练图像来增加训练集的数量。此外,我们可以将训练集的某一部分拆分为验证集,以比较模型的性能。
from tensorflow.keras.preprocessing.image import ImageDataGenerator def image_gen_w_aug(train_parent_directory, test_parent_directory):
train_datagen = ImageDataGenerator(rescale=1/255,
rotation_range = 30,
zoom_range = 0.2,
width_shift_range=0.1,
height_shift_range=0.1,
validation_split = 0.15)
test_datagen = ImageDataGenerator(rescale=1/255)
train_generator = train_datagen.flow_from_directory(train_parent_directory,
target_size = (75,75),
batch_size = 214,
class_mode = 'categorical',
subset='training')
val_generator = train_datagen.flow_from_directory(train_parent_directory,
target_size = (75,75),
batch_size = 37,
class_mode = 'categorical',
subset = 'validation')
test_generator = test_datagen.flow_from_directory(test_parent_directory,
target_size=(75,75),
batch_size = 37,
class_mode = 'categorical') return train_generator, val_generator, test_generator
在创建了上面的函数之后,现在您可以调用该函数,并使用您之前定义的train_dir和test_dir变量传递参数。
train_generator, validation_generator, test_generator = image_gen_w_aug(train_dir, test_dir)
而到了这一步,就已经加载好数据了!
建立机器学习模型
作为一个机器学习模型,如果你愿意,你可以建立自己的 CNN 模型。但在本文中,迁移学习法将被应用。使用来自 ImageNet 的具有预训练权重的 InceptionV3 模型。
但是,由于这个模型非常深,所以使用的模型将一直到称为mixed_5的层,并且直到这一层的所有权重都是固定的,以加快训练时间。从该图层开始,模型将被展平以连接到密集图层,然后连接到最终的密集输出。mixed_5 之后的所有重量都是可训练的。
from tensorflow.keras.applications.inception_v3 import InceptionV3
from tensorflow.keras.layers import Flatten, Dense, Dropoutdef model_output_for_TL (pre_trained_model, last_output): x = Flatten()(last_output)
# Dense hidden layer
x = Dense(512, activation='relu')(x)
x = Dropout(0.2)(x)
# Output neuron.
x = Dense(3, activation='softmax')(x)
model = Model(pre_trained_model.input, x)
return modelpre_trained_model = InceptionV3(input_shape = (75, 75, 3),
include_top = False,
weights = 'imagenet')for layer in pre_trained_model.layers:
layer.trainable = Falselast_layer = pre_trained_model.get_layer('mixed5')
last_output = last_layer.output
model_TL = model_output_for_TL(pre_trained_model, last_output)
如果您还没有导入 InceptionV3 模型,下载该模型需要几分钟时间。
在这一步,您已经建立了模型!接下来,我们需要训练模型。
训练并保存机器学习模型
现在是我们训练模型的时候了。在训练模型之前,首先需要编译模型。在本文中,优化器将是 Adam,因为我们有一个分类问题,那么我们应该使用分类交叉熵作为损失。对于指标,我们将使用准确性。
编译完模型后,现在我们可以训练模型了。模型训练完成后,我们需要保存训练好的模型。然后,在与 Python 文件相同的目录中,您应该有一个名为“my_model.hdf5”的新 hdf5 文件。
model_TL.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])history_TL = model_TL.fit(
train_generator,
steps_per_epoch=10,
epochs=20,
verbose=1,
validation_data = validation_generator)tf.keras.models.save_model(model_TL,'my_model.hdf5')
现在你已经完成了建模过程。您可以保存并关闭 Python 文件。
创建 Streamlit Web 应用程序
要用 Streamlit 创建一个 web 应用程序,我们需要做的第一件事是创建一个新的 Python 文件,姑且称之为rps_app.py。在这个 Python 文件中,首先我们需要加载之前保存的训练模型。
import tensorflow as tfmodel = tf.keras.models.load_model('my_model.hdf5')
下一步是编写一个标题和任何其他你想放入你的 web 应用程序的文本。要写标题,只需使用 Streamlit 的write属性,然后在文本前加上#。要写一个简单的文本,我们也可以使用write的方法,然后在不添加#的情况下继续你的文本
要让用户将自己的图像上传到您的 web 应用程序,只需使用 Streamlit 库中的file_uploader属性。有关 Streamlit 上其他可用选项的更多详细信息,您可以在 Streamlit API 文档页面 查看。
import streamlit as stst.write("""
# Rock-Paper-Scissor Hand Sign Prediction
"""
)st.write("This is a simple image classification web app to predict rock-paper-scissor hand sign")file = st.file_uploader("Please upload an image file", type=["jpg", "png"])
下一个重要步骤是处理用户上传的图像。该处理步骤包括将图像调整到与训练和验证图像相同的大小。调整图像大小后,加载的模型应该预测该图像属于哪个类别。
import cv2
from PIL import Image, ImageOps
import numpy as npdef import_and_predict(image_data, model):
size = (150,150)
image = ImageOps.fit(image_data, size, Image.ANTIALIAS)
image = np.asarray(image)
img = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
img_resize = (cv2.resize(img, dsize=(75, 75), interpolation=cv2.INTER_CUBIC))/255.
img_reshape = img_resize[np.newaxis,...]
prediction = model.predict(img_reshape)
return predictionif file is None:
st.text("Please upload an image file")
else:
image = Image.open(file)
st.image(image, use_column_width=True)
prediction = import_and_predict(image, model)
if np.argmax(prediction) == 0:
st.write("It is a paper!")
elif np.argmax(prediction) == 1:
st.write("It is a rock!")
else:
st.write("It is a scissor!")
st.text("Probability (0: Paper, 1: Rock, 2: Scissor")
st.write(prediction)
之后,您需要将 Python 文件保存在与之前的 Python 文件相同的目录中。
我们现在基本上都准备好了!要检查我们的 web 应用程序的外观,请打开提示符,然后导航到 Python 文件的工作目录。在工作目录中,您可以键入以下命令:
streamlit run rps_app.py
现在,您将从提示中看到,您可以在本地主机上检查您的 web 应用程序。如果你再等一会儿,在你运行你的 Streamlit 应用程序后,一个新的窗口将会马上打开。下面是简单图像分类 web app 的截图。

使用 Heroku 部署您的 Web 应用程序
到目前为止,您已经在本地计算机上构建了 web 应用程序。为了让其他人能够使用你的网络应用,你可以使用 Heroku。
用于部署的附加文件
在部署 web 应用程序之前,除了我们为构建应用程序而创建的 Python 文件之外,我们还需要创建另外三个文件。这三个文件是:
- requirements.txt: 这是我们需要创建的文本文件,用来告诉 Heroku 安装部署我们的机器学习模型所需的必要 Python 包。在本教程中,我们使用了四个 Python 库来构建应用程序:numpy、streamlit、tensorflow 和 pillow。因此,我们需要在这个文本文件中指定这些库的相关版本。
tensorflow==2.0.0
streamlit==0.62.0
numpy==1.16.5
pillow==6.2.0
如果您不确定您正在使用的 Python 库的版本,您可以在您的 Python 环境中使用'_ _ version _ _ '属性,或者在 conda 提示符中键入'conda list '。
- setup.sh: 这个文件是处理我们在 Heroku 上的应用的服务器和端口号所必需的。
mkdir -p ~/.streamlit/ echo "\
[server]\n\
port = $PORT\n\
enableCORS = false\n\
headless = true\n\
\n\
" > ~/.streamlit/config.toml
- Procfile: 这是你的配置文件,用来告诉 Heroku 如何以及执行哪些文件。
web: sh setup.sh && streamlit run rps_app.py
现在已经有了这三个文件,将它们放在与 Python 文件相同的目录中。
接下来,让我们跳到 Heroku。
创建您的 Heroku 帐户
如果你已经有了 Heroku 账号,可以跳过这一步。如果你还没有,那么你可以直接去 Heroku 。在那里你会发现一个“注册”按钮,点击该按钮并填写必要的信息。之后,你需要用你的电子邮件确认你的新 Heroku 账户。
用 Heroku Git 部署您的 ML 模型
创建好 Heroku 账号后,接下来需要做的事情就是安装 Heroku CLI (命令行界面)。接下来,打开命令提示符,键入以下命令。
heroku login
该命令将引导您使用 Heroku 帐户登录。
接下来,使用命令提示符移动到应用程序文件的目录。在应用程序文件的目录中,键入以下命令。
heroku create your_app_name
您可以根据自己的喜好更改your_app_name作为应用名称。接下来,您需要通过键入以下命令来启动一个空的 git 存储库。
git init
接下来,您希望将所有应用程序文件提交到刚刚创建的空存储库中。为此,您可以键入git add .命令,然后您需要通过键入commit和push命令来推送它们,如下所示。
git add .
git commit -m "your message"
git push heroku master
现在,您的应用程序文件将通过 Heroku Git 部署到 Heroku,在该过程完成后,您将看到您的 web 应用程序的 URL,可以通过互联网访问。您的 web 应用程序 URL 的格式类似于your _ app _ name . heroku app . com .
下面是一个用 Heroku 部署的简单 web 应用程序的例子。

就是这样!您的影像分类 web 应用程序已部署!
如果想看本教程中 web app 的代码或者其他必要的文件,可以在我的 GitHub 上看到。
使用 JavaScript 部署图像分类器
推断图像分类模型的另一种方式是通过直接部署在静态网站或节点 web 应用中来减少推断时间。

图片来源:novasush.com
使用机器学习模型可能会很有趣。你必须确保你已经设置了硬件和软件优化的管道,然后你的模型就可以投入生产了。但是有时用 image 对后端进行 HTTP 调用,然后在前端返回结果可能是一项单调乏味的工作。如果您使用的是重型模型,并且您的服务器配置较低,那么会有很多限制,比如后期推断。
这就是为什么他们说模型部署是数据科学领域 80%的工作。

金钱大劫案教授说 |来源:imgflip.com
用 JavaScript 进行机器学习
TensorFlow.js ,这是一个开源库,您可以使用 Javascript 和高级层 API,完全在浏览器中定义、训练和运行机器学习模型。如果您是刚接触 ML 的 Javascript 开发人员,TensorFlow.js 是开始学习的好方法。JavaScript 是一种客户端脚本语言,在浏览器中完全在客户端运行机器学习程序会带来新的机会,如交互式 ML。
我们开始吧
我已经在 Keras 上训练了一个简单的猫和狗的分类器。想自己培养模特可以参考我的笔记本档案。我们将使用 tensorflowjs_converter 工具将 Keras (.h5)权重转换为 tfjs 格式。
tensorflowjs_converter 附带了 tensorflowjs python 库,我们来安装吧。
pip install tensorflowjs
使用 tensorflow.js 转换器将保存的 Keras 模型转换为 JSON 格式。(假设重量模型的名称. h5)
创建一个目录来存储转换后的权重并提及其路径(jsweights)
tensorflowjs_converter --input_format=keras ./model.h5 ./jsweights
如果你做的没错,你现在应该有一个名为model.json的 JSON 文件和各种.bin文件,比如group1-shard1of10.bin。.bin文件的数量将取决于您的模型的大小:您的模型越大,的数量就越大。bin 文件。这个model.json文件包含了你的模型和的架构。bin 文件将包含模型的重量。

来源:https://novasush.com/blog/images/js_in_action.jpg
让我们开始吧
我们需要创建一个 js 文件,其中包含用于加载模型和从给定图像进行推断的代码。
确保您在文件中为加载model.json设置了正确的位置。此外,预测函数和模型加载函数应该是异步的。
//classifier.js
var model;
var predResult = document.getElementById("result");
async function initialize() {
model = await tf.loadLayersModel('/weights/catsvsdogs/model.json');
}async function predict() {
// action for the submit buttonlet image = document.getElementById("img")
let tensorImg = tf.browser.fromPixels(image).resizeNearestNeighbor([150, 150]).toFloat().expandDims();
prediction = await model.predict(tensorImg).data();if (prediction[0] === 0) {
predResult.innerHTML = "I think it's a cat";} else if (prediction[0] === 1) {
predResult.innerHTML = "I think it's a dog";} else {
predResult.innerHTML = "This is Something else";
}
}
initialize();
在你的 Html 文件中设置一个图片路径。把路径换成你要预测的图像就行了。你只需要给出一个相对的图像路径。
<img src="./images/courage.jpg">
将这个文件和 tensorflowjs CDN 链接添加到您的 HTML 文件中的</body>标签之后。
<script src="[https://cdn.jsdelivr.net/npm/@tensorflow/tfjs/dist/tf.min.js](https://cdn.jsdelivr.net/npm/@tensorflow/tfjs/dist/tf.min.js)"> </script>
<script src="/classifier.js"></script>
一旦我们的设置完全就绪,我们就可以加载我们的 Html 页面并检查预测。
注意事项
即使所有的文件都是静态的,我们的 Html 文件仍然需要一个服务器来加载 model.json 文件。就像托管网页一样。最简单的方法是使用 python HTTP 服务器模块,它可以作为静态网页的托管服务器。最好的部分是,我们不需要安装任何额外的库来加载 HTTP 模块。另外,你也可以使用 apache 或 Nginx 这样的托管服务器。对于 windows 用户来说,WAMP 服务器也很有用。
可以使用以下命令在 Html 文件目录中启动 Python HTTP server。
python3 -m http.server
运行上述命令后,您将获得以下输出:
Serving HTTP on 0.0.0.0 port 8000 ([http://0.0.0.0:8000/](http://0.0.0.0:8000/)) ...
在浏览器中打开 URL,查看通过 js 权重预测的图像输出。
这里是我的模型的输出

来源:novasush.com
亲自尝试
这是我这个项目的 GitHub 回购链接。尝试训练和转换重量,然后自己在网站上部署。
JavaScript 中的猫狗分类器训练一个 Keras 分类器并保存其权重安装 tensorflowjs python 库使用…
github.com](https://github.com/novasush/image-classifier-in-javascript)
这是所有的乡亲

再见| novasush.com
参考
[1] Tensorflow.js
[2] 转换器工具的 Tensorflowjs python 库
[3] 猫狗图像分类教程来自 TensorFlow 官方网站
【4】加菲猫人物参考为猫。
勇敢懦弱的狗(我的最爱)
[5] 金钱大劫案人物
和几杯咖啡😉
部署 NLP Web 应用程序:棘手的问题

你是否已经建立了一个很酷的 NLP 模型,并试图部署到 web 上,以便向你的朋友和家人展示你有多酷?如果是这样,那么这篇文章可能会让你感兴趣!
在游戏的这个阶段,你已经完成了 Jupyter,你正在使用你的 Flask 应用程序向人们展示你的模型是多么的平庸。你的应用程序看起来很简单,但在本地可以正常工作。
你现在可能处于这样一个阶段,你已经浪费了无数个小时试图用 Google App Engine 进行部署,结果却放弃了,并开始在 Heroku 上投入无数个小时。这两种解决方案基本上都应该是一行代码,但它们并不适合您。
您最终在 Procfile 中正确地设置了端口,但却遇到了新的障碍。该应用程序将顺利部署,但不会启动,并将抛出 H10 或 H13 错误。“应用崩溃”。本地一切都正常,您已经正确设置了端口,并验证了确实有 Dynos 启动并运行。
您现在已经调试了整个过程,并且您意识到 pickle 文件中有可疑之处。你为什么要加载 pickle 文件?因为这是你保存矢量器和模型的方法。
鉴于这是一个 NLP 应用程序,您至少有一个 pickle 用于您的矢量器(因为您需要对输入文本进行矢量化),至少有一个 pickle 用于您的模型(因为您需要基于来自矢量器的矢量进行预测)。
你开始尝试。你把它拆下来,在没有腌渍文件附带的功能的情况下运行,它就工作了。很好。看来你已经把问题隔离了。pickle 文件一定太大了,或者 pickle 文件可能有某种问题。
到目前为止,您已经通过简单地上传静态文件夹中的 pickle 文件进行了部署。尽管当您在本地运行它时这样做是可行的,但是您决定将它们全部放入 s3 桶中,并在启动时从那里访问它们。
H10 应用程序崩溃
几个小时的调试之后,您发现罪魁祸首实际上只是经过腌制的矢量器。
因为您使用了定制的预处理器和记号赋予器,所以当您加载 pickle 矢量器时,您必须在加载 pickle 的模块中使用这两个函数。
正如用户blckknight在 StackOverflow ( link )上比我更优雅地解释的那样:“Pickle 不转储实际的代码类和函数,只转储它们的名字。它包含了每个定义模块的名字,所以它可以再次找到它们。如果您转储在作为脚本运行的模块中定义的类,它将转储名称__main__作为模块名称,因为这是 Python 使用的主模块名称(如if __name__ == "__main__"样板代码所示)。”
这很有道理,但你已经知道这一点,因为你在最初构建应用程序时已经处理过这个问题。当问题最初出现时,由于 IDE 中更好的错误追溯,您无需任何谷歌搜索就能进行调试。因此,在主应用程序模块中已经有了预处理程序和标记器函数。为什么这他妈的又成问题了?
我不清楚具体是如何和为什么,但我清楚的是你的主文件——你运行 Flask 应用程序的那个——不是 Heroku 服务器作为 main 运行的。这意味着当你加载你的 pickled 矢量器时,它会寻找类 main。我的 _ 预处理器,它找不到。
现在,解决方案非常简单,在上面提到的论坛帖子中有概述:重新拾取矢量器,但这次是通过导入预处理器,并且从一个可访问的位置将标记器函数从文件中取出。
现在
您可能会注意到,当您处理这些不同的文件时,模型将占用大约 50Kb,然而,您的矢量器可能会占用大约 500Mb。只是重申一下:您的矢量器可能是 500Mb +!这是疯狂的,将挫败任何部署这种模式的企图。
我在 BrainStation 的一位导师的帮助下找到了下一个技巧,在此之前,我尝试了几天不同的部署方法,最终建立了我自己的 Linux 服务器。事实证明,与大多数代码相关的问题一样,解决方案实际上一直摆在我面前。
在所选矢量器(在我的例子中是 tfidf)的文档页面上的一个小部分中,有一个小注释,说明默认情况下,由于某种不为人知的原因,fit 矢量器将所有停用词(在这种情况下,不仅是常规停用词,实际上还有所有未包含在矢量化中的标记)作为属性存储。
完整注释声明:“酸洗时,stop_words_属性会变大并增加模型尺寸。此属性仅用于自检,可以使用 delattr 安全删除,或者在酸洗前设置为 None。
在我的例子中,如上所述,完整的 pickle 文件大约有 500Mb。由于没有逻辑原因而作为属性存储的无用令牌列表被删除后,它下降到大约 200Kb。那是 3 个数量级。
这是一个很小的腌渍错误案例,但我希望它能帮助人们不像我一样用头撞墙几个小时。
泡菜# TFIDF # Heroku #烧瓶#NLP
使用 Kubernetes 部署 BERT
谷歌云平台,Docker,微服务,NLP

伯特:形象信用
**简介 **
BERT 是 Google 广泛使用的 NLP 模型。2019 年被认为是 BERT 年,取代了大多数生产系统。BERT 使用基于自我关注的方法,该模型本身由变压器块组成,变压器块是一系列自我关注层。与基于 RNN 的序列对序列模型相比,BERT 证明了自我注意的使用导致了更优越的性能,特别是在 Stanford 问答数据集(SQUAD)上。我们已经跳过了所有的理论细节,如 RNN,LSTM 模型,自我关注,因为它们在吴恩达课程和博客文章s herehere(作者 Jay Alammar)的课程中会讲到。另一个很棒的帖子提供了基于 BERT 的主要模型。请注意,注意力机制最初被应用于改善基于 RNN 的序列对序列模型的性能。Lilian Weng 也发表了一篇关于注意力机制的概述,她在其中解释了 transformer 架构。特别是键、值和查询概念,其中键和值相当于编码器输出,即存储器,而查询是解码器输出,然而,作为原始论文,它们是位抽象的,并且作用于所有字。ukasz Kaiser 解释了为什么它们更有效和高效的原因
从实现的角度来看,BERT 是一个拥有 1.1 亿或更多参数的大型模型,从头开始训练非常具有挑战性,正如 Google 的博客中所强调的。它需要有效的计算能力,模型结构必须仔细编程以避免错误。因此,为了使 BERT 模型易于使用,谷歌开源了它的实现,它可以在大约 30 分钟内微调到各种任务。一个例子是情绪分析任务,正如这里的所解释的。限制参数数量的研究工作正在进行中。然而,微调 BERT 也是广泛使用的方法。
目标
这篇文章的目标是部署一个经过训练的 BERT 模型,作为一个微服务,对流媒体 tweets 进行情感分析。这个简单的例子揭示了为 ML 开发微服务的关键挑战。目标是涵盖强调训练和部署 ML 模型的高级工具需求的关键概念。这篇文章中涉及的主要任务是
- 流数据(tweets)的数据预处理:就 ETL 而言,真实世界的系统要复杂得多
- 使用经过训练(微调)的 BERT 模型进行推理
训练模型需要额外的考虑,以供审查和保留。这些将在另一篇文章中讨论。
我们的架构如下

采用的技术有(通过相关的 python API)
- 伯特,张量流,张量流服务,雷迪斯,
- 容器:Docker 容器和用于编排的 kubernetes
Docker 和 kubernetes 的背景信息
我们将开发微服务,使用容器部署它们,并使用 K8S 来管理这些容器。简而言之,容器是将代码和依赖项打包在一起独立运行的抽象。如果你不熟悉容器,请查看 docker 网站获取更多信息和教程。Kubernetes (K8S)由 Google 开发,用于管理多个容器,它可以在本地计算集群或云上运行。所有主要的云提供商都支持 Kubernetes。这篇文章需要的主要 Kubernetes 概念如下
- 基本 kubernetes 组件和 it 架构。视频这里
- pod 和部署
- 持久性卷和持久性卷声明
- Kubenetes 服务公司
- Kubectl :用来创建资源的命令。我们通过 yaml 文件创建各种资源
#Create deployment/pods
kubectl create -f tensorflowServing.yaml #Delete deployment/pods
kubectl delete -f tensorflowServing.yaml#Check pods and service
kubectl get pods
kubectl get svc#Check persistance volume and persistance volume cliam
kubectl get pv
kubectl get pvc
这里的和这里的提供了对这些概念的快速概述,而 youtube 的播放列表提供了对这些概念的更详细的阐述。微软也开发了好的资源来开始 K8S。谷歌提供的资源是广泛的,最初可能有点令人不知所措。一旦你对 K8S 的概念有了概念,并尝试“你好世界”这里。它涵盖了流程,我们需要遵循相同的流程,几次!!!
文档中提到的过程如下
- 将您的应用程序打包成 Docker 映像
- 在您的机器上本地运行容器(可选)
- 将图像上传到注册表
- 创建一个容器集群
- 将您的应用部署到集群
- 通过服务向集群外部公开您的应用
- 扩展您的部署
回到我们的微服务
- 我们的第一个微服务使用 tensorflow-serving 和经过训练的保存模型运行 BERT,允许我们使用客户端执行推理
- 第二个微服务使用 gRPC 客户端通过“请求”BERT 来执行情感分析,并将其发布到 Redis 发布/订阅频道
如果你正在使用 GCP,我们假设你已经在你的机器上安装了 gcloud,kubectl 并连接到名为“kubernetes”的项目,更多信息请参见这里。对于其他设置,我们假设存在等效性。
我们首先通过命令行创建并连接到 GCP 的 kubernetes 集群
创建
**gcloud** beta container — project “kubernetes” clusters create “standard-cluster-1” — zone “us-central1-a” — no-enable-basic-auth — cluster-version “1.13.11-gke.14” — machine-type “n1-standard-1” — image-type “COS” — disk-type “pd-standard” — disk-size “100” — scopes “https://www.googleapis.com/auth/devstorage.read_only","https://www.googleapis.com/auth/logging.write","https://www.googleapis.com/auth/monitoring","https://www.googleapis.com/auth/servicecontrol","https://www.googleapis.com/auth/service.management.readonly","https://www.googleapis.com/auth/trace.append" — num-nodes “3” — enable-cloud-logging — enable-cloud-monitoring — enable-ip-alias — network “projects/kubernetes/global/networks/default” — subnetwork “projects/kubernetes/regions/us-central1/subnetworks/default” — default-max-pods-per-node “110” — addons HorizontalPodAutoscaling,HttpLoadBalancing — enable-autoupgrade — enable-autorepair
连接
**gcloud** container clusters get-credentials standard-cluster-1 — zone us-central1-a — project kubernetes
对于数据存储,我们使用谷歌云磁盘,模型是存储在一个单独的位置
**gcloud** beta compute disks create redis-disk-gce — project=kubernetes — type=pd-standard — size=100GB — zone=us-central1-a — physical-block-size=4096
我们在这个设置中使用 redis 在微服务之间进行通信。Redis 被用作发布/订阅消息传递。有必要在集群上运行健壮的 redis 微服务。我们可能面临的一个问题是万一 redis 崩溃。Kubernetes 能够检测崩溃并创建一个新的容器,即 redis 实例来维护服务。然而,当重新创建容器时,新容器可能具有不同的状态。因此,为了避免这种情况,我们使用了持久性磁盘(一个专用的存储磁盘),它通过使用持久性卷声明将这个存储链接到我们的 Redis 容器。这是一个非常简单的设置,在企业级别,要实现扩展,我们需要使用有状态集合。关于它的详细讨论可以在这里找到,而示例 redis 配置可以在这里找到。
在我们的设置中,有一个 redis 实例,我们使用 google 云盘通过 yaml 文件创建一个持久性卷和持久性卷声明。我们通过 redis 容器中的持久性卷声明的方式在 make use storage 中使用这些,如 ymal 文件中所概述的。我们还通过 kubernetes 服务向外部世界公开 redis。
服务张量流模型
通过使用 tensorflow 服务 API,在 kubernetes 中服务 tensorflow 模型非常简单。这些步骤如下
- 从张量流图中收集输入(“sinputs”)和输出(“soutput”)变量的列表
- 在保存模型之前创建预测签名
- 使用保存模型格式保存模型
我们将训练好的模型复制到 tensorflow 服务 docker 映像,使用我们的模型创建新的 docker 映像,并上传到容器注册表,使用此处列出的流程。我们的 docker 映像是 gcr.io/kubernetes-258108/bert.的我们通过 kubenetes 部署来部署这个映像。我们还创建了 kubernetes 服务。
注意:使用通过“kubectl”获得的服务 IP 地址,让我们的集群之外的客户端发出请求。为了避免使用 IP 地址,需要使用 kube-dns 发现服务,这是有据可查的,这里有一个 python 示例。因为我们已经为 bert 推断客户端配置了服务,并且可以使用服务名“bertservice:8500 ”,所以 8500 是端口,因为我们是在集群中发出请求的。
在客户端发出请求的关键代码组件如下,它们基于 google client 示例。
推理客户端可用的完整示例如下。它由 Tweepy 流监听器组成,用于订阅 tweets 主题和 redis sub/pub 消息服务
Bert 推理客户端使用 gRPC 请求客户端
我们使用一个docker 文件将这个客户端打包在 docker 容器中,并部署在我们的 kubernetes 集群上
要为 python 容器创建的 docker 文件
现在,我们可以通过连接到 redis pods 或使用 python 订阅者,通过 kubectl 来观察带有情感的流推文
***kubectl exec -it redis-pod-name redis-cli
127.0.0.1:6379> SUBSCRIBE STREAM***
注意:我们不使用 GPU 进行推理,因此标准 N1 计算资源上的 gRPC 请求需要大约 12 秒(对于 20 个批处理大小)
关闭思绪
我们能够在 GCP 集群上部署此设置 3 天,没有发生任何事件。这展示了 ML 的容器和简单应用程序的威力,并且可以很快部署。然而,在现实世界中,情况完全不同。例如,ETL 可能是一项非常复杂的任务,可能需要 rabbit-MQ、Kafka 或 Apache beam 等高级技术来集成来自其他来源的数据。我们可能需要重新培训和重新部署 ML 模型。这些在另一篇博文中有所涉及。结合起来,这些应该提供开发微服务的介绍,并强调对其他技术的需求,如 Kubeflow、Apache Airflow、Seldon、helm charts,用于使用 kubernetes 基础设施开发 ML 应用程序。我们还没有讨论如何使用 Kubernetes 扩展我们的微服务。一种方法是利用复制集,但根据我们需要的任务和规模,可能会有一些考虑。例如,OpenAI 在最近的博客帖子中记录了将 kubernetes 扩展到 2500 个节点的挑战。
git 回购:这项工作可以在这里找到
在 Heroku 上部署 Dash 或 Flask web 应用程序。简易 CI/CD。

在笔记本电脑上开发 python web 应用非常棒。让每个人都能接触到它更令人满意。今天,我们将了解如何在 GitHub 的 Heroku 平台上轻松部署 python web 应用程序。
首先,我们将把我上一篇文章中构建的动画散点图转换成一个基本的 Dash 应用程序,然后我们将评估 CI/CD 概念,最后,我们将从这个 GitHub repo 在 Heroku 上部署应用程序。

情节动画散点图
构建应用程序
Dash 是构建在 Flask 和 Plotly 之上的 Python 框架,旨在制作数据驱动的 web 应用。多亏了 plotly,它提供了一些基本的图表,如直方图和饼状图,它还附带了许多高度可参数化的控件,如下拉菜单、复选框、日期滑块等等。
让我们从创建一个只有一个标题的非常基本的应用程序并运行它开始。
Dash 的“Hello World”脚本
把标题改成“你好,世界!”,我们会在这里找到最基本的 dash 应用程序。对于了解 Flask 的人来说,直到现在看起来都很像。

基本 Dash 应用程序—渲染界面
让我们用散点图来填充空白页。由于本文的目的是 Heroku 部署,我们将假设数据准备已经完成,并使用pickle模块存储在dictionnary中。如果你对此感到好奇,这里有一些有用的资源:
App 的基本结构
现在我们有了一个漂亮的标题,关于疫情的指标,以及生动的散点图。

仪表板应用
注意:这个应用程序并不旨在展示 Dash 及其回调函数的强大功能。这是一个非常基本的应用程序,主要用于演示如何在 GitHub 的 Heroku 上进行部署。
既然我们已经准备好了应用程序,我们就可以部署它了。为了做到这一点,我们将使用 Heroku 平台,但是让我们从发现集成和持续部署的概念开始。
CI/CD
这是什么意思?您可能听说过 GitLab CI/CD、Circle CI、Travis CI 或任何其他包含这些字母的工具。但这意味着什么呢?
CI/CD ,或持续集成/交付和持续部署,专注于小增量变更的快速发布和整个开发过程中自动化的使用。在 DevOps 的核心,CI/CD 工具是其成功的关键。以下是这些概念的一些定义。

使用 Github 和 Heroku 的 CI 管道
持续集成:使用 CI,开发人员尽可能频繁地将他们的代码变更合并到回购的主分支中。一旦变更得到验证,就会运行自动化的构建和测试流程来验证变更的准确性。在开发周期中尽可能早地发现缺陷。测试自动化是持续集成的关键,以确保在集成到主分支时,新的提交不会破坏应用程序。
连续交付:它是 CI 的一个扩展,软件的设计、配置和参数化的方式使得它可以在任何时候自动投入生产。
持续部署:它比持续交付更进一步,通过每次变更自动协调应用程序向客户的部署。通过加速客户反馈循环,收益是巨大的——在软件质量、项目期限、结果和开发成本方面。
赫罗库
Heroku 是一个云平台即服务(PaaS),为 web 应用部署提供服务器。它支持 Python 中的几种技术,提供 CI/CD 服务,并有一个“免费和爱好”计划,这使它成为一个非常方便的工具,可以与客户和朋友分享您的 POCs 或其他个人项目。

Heroku 运行时:从你的代码到你的最终用户(来自 Heroku 网站)
如前所述,我们将使用 CI/CD: 我们将把我们的应用部署映射到 GitHub repo 主分支上的任何推送。这意味着小的修改应该在另一个分支上完成(例如develop分支)。当修改被批准后,我们将把develop分公司合并到master分公司。此操作将触发 Heroku,并根据您的新代码运行应用程序的新构建/部署。
先决条件
当 Heroku 检查您的回购协议时,它会自动检测使用的技术(在我们的例子中是 Python)。但是,要运行应用程序,需要遵循一些说明:
- 您需要从
app.py文件运行您的应用程序,并且该文件需要位于 repo 的根目录下。任何其他尝试都将导致以下消息和部署崩溃。

使用 index.py 而不是 app.py 作为主文件会导致崩溃
- 你需要使用 Procfile,它会被 Heroku 查找。它是一个单行文件,必须命名为
Procfile,包含启动网络服务器web: gunicorn app:server.的指令 - 如果您为您的项目使用了任何库,您应该在一个
requirements.txt文件中指定它们。Heroku 在每次构建开始时运行一个pip install -r requirements.txt。如果任何使用的包不在该文件中,部署将会崩溃。为了确保您不会忘记任何包,您可以在项目的根目录下使用 Linux 命令pip freeze > requirements.txt,它将生成包含所有需要信息的文件。 - 重要提示:除了你的库之外,你还必须在你的需求文件中添加
gunicorn包。 - 当然,应用程序的代码需要没有错误!
既然您已经为项目的部署做好了准备,让我们开始最终的部分部署吧!
首次部署
下面是实例化应用程序的持续部署并实现其首次发布的步骤。
- 注册并登录 Heroku 。当它完成后,你将登陆到你的个人仪表盘,现在是空的。
- 点击右上角的“新建”按钮和“创建新应用程序”

- 您现在可以输入您的应用程序名称。它会自动告诉你它是否可用。由于“covid”和各种“covid19”、“新冠肺炎”或“covid_19”已经被占用,我在这里选择“新冠肺炎-世界地图”。您还可以选择您的应用程序将托管的地区:美国或欧洲。通常的选择是从你的用户中选择最接近的;)!
- 点击“创建应用程序”进入下一个屏幕,并关联您的回购。
- 无需为单个应用程序添加管道
- 是时候选择部署方法了。Heroku 提供了一个 CLI(命令行界面)工具,用于从您的终端设置部署。但是我们想从界面配置它,然后选择“连接到 GitHub”

- 由于这是第一次,您需要登录您的 GitHub 帐户。
- 然后,您可以选择 repo to 并单击 connect。几秒钟后,您将能够选择与持续部署相关联的分支。最佳实践是选择
master分支。 - 选中“部署前等待配置项通过”选项,然后单击“启用自动部署”。

- 当更新您的分支时,它现在将运行新的构建和部署。您还可以选择要立即部署的分支。
神奇的事情发生了:几秒钟后,构建和部署就完成了。你可以连接你的应用!
附加说明
- 现在,每当您通过推送提交或合并请求来更新您的主分支时,应用程序都会重新构建!
- 有时部署过程会失败。这并不有趣,但它确实发生了。你有两个工具来帮助你:日志和控制台。你可以在 Heroku 的应用程序页面点击右上角的按钮“更多”来访问它们。通过日志,您可以了解失败的原因和原因,但如果您仍然不明白为什么您的应用程序不能正确运行,您可以通过控制台进入虚拟机来检查您的文件。****
- 现在,你已经订阅了 Heroku 免费计划。这足以满足我们的需求,但是有一个限制:几个小时不使用应用程序之后,服务器将关闭。这不是一个真正的问题,尽管这意味着下一个用户使用它时,他必须等待服务器启动,并且第一次加载可能会稍长一些。如果你知道你需要展示你的作品,提前几分钟查看网址是个好主意,这样可以避免这种延迟效应。
结论
您已经在 Heroku 上部署了您的第一个 dash 应用程序,现在只要您修改了代码,只需将您的代码推送到 GitHub,您就可以让全球的任何人都可以看到它。我希望你喜欢它!现在轮到您在 Heroku 上部署基本的(甚至复杂的)web 应用程序了!
下一次我们将探索如何使用 Docker-Compose 通过 Docker 部署 dash 应用程序!敬请期待:)
提醒一下,GitHub 上有完整的代码。此外,您可能已经注意到了 logzero 包在代码中的使用!我真的很喜欢这个软件包及其在控制台中彩色打印报表的能力。我建议你看看并阅读这篇文章,在这篇文章中我解释了为什么你应该在你的 DS 项目中使用它。
使用 AWS 为机器学习部署仪表板
包含 AWS CloudFormation 模板和代码示例。

我们都在努力开发有用的机器学习模型。在花费大量精力进行数据准备和模型开发之后,我们希望我们的模型能够对商业和更广阔的世界产生积极的影响。尽管成功取决于模型性能,但以清晰有效的方式传达模型预测同样重要。大多数机器学习应用程序都可以从拥有仪表板界面中受益。
拥有仪表板有什么好处?
仪表板是一个图形用户界面,显示与特定业务目标或流程相关的信息,这也可以包括机器学习模型预测。对于终端用户来说,使用可视内容通常要容易得多,而且根据定义,仪表板是可视的。与表格数据不同,肉眼可以快速识别出模型预测中的趋势、异常值和其他模式。一些机器学习任务本质上是可视的(例如物体检测),而其他任务可以用图表(例如时间序列预测)和地图(例如空间-时间预测)来显示。甚至可以为简单的分类任务创建引人注目的仪表板视觉效果,只需以不同的方式汇总预测即可。有了设计良好的仪表板,最终用户可以做出更明智、更快速的决策。
让用户能够通过仪表板与模型及其预测进行交互,通常会增加对模型的信任,并导致模型的更广泛采用。除此之外,仪表板是当今企业中非常常见的使用模式,这种熟悉感鼓励了进一步的采用。即使最终产品中没有使用仪表板,它们也是在开发周期早期收集反馈的宝贵工具。

图 1:使用该解决方案部署的示例仪表板。
应该使用什么仪表板服务或工具?
随着仪表板的流行,有大量的服务和工具可供选择也就不足为奇了。选择合适的工作将取决于你的具体要求,但有两大类。
- 托管仪表盘服务:如亚马逊 QuickSight 和 Kibana 。
- 自定义仪表盘工具:如流线型、面板和仪表盘。
一般来说,如果您需要数据库集成、用户管理和可扩展性,并且可视化选项足以满足您的特定使用情形,您应该选择托管仪表板服务。当您需要额外的定制级别(在视觉和用户界面上)时,您应该选择定制仪表板工具。
我们的例子使用了 Streamlit,因为它简单、灵活,并与各种各样的可视化工具集成,如牛郎星、散景和 Plotly 。不过,和往常一样,也有权衡。定制仪表板工具的部署可能比托管服务工具更复杂,因为您需要处理数据库集成、用户管理和可扩展性。
部署的解决方案是什么?
在这篇文章中,我们将对这个问题给出一个全面的回答,并深入探讨一些可能被忽略的重要细节。我们将首先考虑在 Amazon EC2 上部署我们的定制仪表板。添加一些额外的需求(比如安全性、身份验证和可伸缩性),然后我们讨论一个更全面的仪表板部署架构。
不仅仅是理论,我们还包括了一个用于仪表板开发和部署的可定制解决方案。一个 AWS CloudFormation 模板被共享,这样你只需点击几下鼠标就可以在你自己的 AWS 账户中创建所有需要的资源。您可以选择部署两个示例仪表板应用程序之一:“纽约市的优步皮卡”(一个独立的示例)和“ DistilGPT-2 文本生成”(一个与机器学习模型交互的示例)。所有代码都是可定制的。我们已经采用了集装箱化的方法(使用 Docker),因此您可以将该解决方案与一系列定制的仪表板工具一起使用。
🐙:点击这里查看 GitHub 上的代码
🚀:点击此处启动 AWS CloudFormation 堆栈
最小方法
简化 AWS 上的 it 部署的最简单的方法之一是使用亚马逊 EC2 。您可以在 Amazon EC2 实例(即 AWS 云中的虚拟服务器)上部署您的仪表板,并让仪表板用户连接到该实例。如果你需要为你的仪表板使用深度学习模型,你可以在 GPU 实例上使用 AWS 深度学习 AMI 。在 Amazon EC2 上部署时,您应该问自己以下问题:
谁可以访问应用程序,如何将访问权限限制在特定的个人?敏感通信是否被 HTTPS 加密了?如果服务器崩溃会发生什么?谁将在实例上安装错误修复和安全更新?如果用户数量随着时间的推移大幅上升和下降,会发生什么情况?该实例能处理高峰流量吗?模型和应用程序的更新呢?这样的例子不胜枚举。
因此,尽管这种方法在架构上很简单,但是根据您的用例,有许多因素会使事情变得更复杂。我们现在来看一种替代方法,它使用许多其他 AWS 服务来帮助我们实现全功能部署。
综合方案
在这种方法中,我们有 3 个中央 AWS 服务: Amazon SageMaker 、 Amazon ECS 和 Amazon Cognito 。Amazon SageMaker 是为无缝模型训练和部署而设计的,它也非常适合仪表板开发。亚马逊 ECR 和 ECS 是集装箱部署的完美补充。Amazon Cognito 专门从事简单安全的身份验证。结合这些 AWS 服务,我们最终得到了图 2 所示的架构。然后我们将直接进入细节。

图 2:使用的 AWS 组件的架构。其中一些是可选的。
使用亚马逊 SageMaker
当涉及到构建、训练和部署机器学习模型时,亚马逊 SageMaker 简化了体验。几分钟之内,您就可以旋转 Jupyter 笔记本电脑,并开始在专用和完全托管的基础架构上部署模型。开箱即用,您可以访问许多预构建的 Conda 环境和 Docker 容器。在“DistilGPT-2 文本生成”示例中,预构建的 PyTorch Docker 容器用于在 ml.c5.xlarge 实例上部署来自 transformers 的 DistilGPT-2 模型。Amazon SageMaker 然后提供了一个简单的 HTTP 端点来与部署的模型进行交互。我们的示例应用程序使用[invoke_endpoint](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/sagemaker-runtime.html?highlight=invoke_endpoint#SageMakerRuntime.Client.invoke_endpoint)方法(来自[boto3](https://boto3.amazonaws.com/v1/documentation/api/latest/index.html))来调用文本生成模型。
import boto3
import jsondata = {
'text': 'In a shocking finding',
'parameters': {
'min_length': 100,
'max_length': 200
}
}sagemaker_client = boto3.client('sagemaker-runtime')response = sagemaker_client.invoke_endpoint(
EndpointName='text-generation',
ContentType="application/json",
Accept="application/json",
Body=json.dumps(data)
)body_str = response['Body'].read().decode("utf-8")
body = json.loads(body_str)print(body['text'])
# In a shocking finding, scientist discovers a herd of unicorns...
Amazon SageMaker 也可以用于仪表板开发。部署模型后,可以直接在笔记本实例上构建和测试仪表板。为了简化应用程序部署,采用了容器化的方法,但是在编辑文件时,您仍然可以获得实时重新加载的所有好处(由于有了本地卷挂载)。当在 Amazon SageMaker 笔记本实例上运行 dashboard 容器时,您可以通过以下经过身份验证的 URL 上的 jupyter-server-proxy 来访问它:
[https://{NOTEBOOK_URL}/proxy/8501/](https://sagemaker-dashboards-for-ml2-notebook.notebook.us-west-2.sagemaker.aws/proxy/8501/)
当你在 Amazon SageMaker 上完成应用程序开发后,你可以将你的容器推送到Amazon Elastic Container Registry(ECR)。与 Docker Hub 类似,它为您的 Docker 图像提供了一个存储库,但它将图像保存在您的 AWS 帐户中,以获得额外的安全性和可靠性。
docker tag {IMAGE_NAME} {DASHBOARD_ECR_REPOSITORY_URL}:latest
docker push {DASHBOARD_ECR_REPOSITORY_URL}:latest
使用亚马逊 ECS
您的 dashboard Docker 图像现在在 Amazon ECR 上,但是应用程序实际上还没有运行。亚马逊弹性容器服务 (ECS)是运行 Docker 容器的全托管服务。您不需要供应或管理服务器,您只需定义需要运行的任务并指定任务所需的资源。我们的示例 任务定义声明 dashboard Docker 容器应该使用单个 vCPU 和 2GB 内存运行。我们的示例 服务同时运行并维护任务定义的指定数量的实例。因此,为了提高可用性,您可以使用 AWS CLI 将服务的期望任务计数设置为 2:
aws ecs update-service \
--cluster {DASHBOARD_ECS_CLUSTER} \
--service {DASHBOARD_ECR_SERVICE} \
--desired-count 2
使用 Amazon ECS 服务的一个主要优点是,它不断地监控任务的健康状况,并替换由于任何原因而失败或停止的任务。亚马逊 ECS 服务还可以自动扩展任务数量(即自动增加或减少),以应对高峰时期的高需求,并在低利用率期间降低成本。我们的示例解决方案还包括一个应用负载平衡器,它在任务间分配流量,与Amazon Certificate Manager(针对 HTTPS)集成,并通过 Amazon Cognito 认证流量。
使用亚马逊认知
当您的仪表板的内容是私有的时,Amazon Cognito 可用于限制某一组用户的访问。尽管该组件是可选的,但在解决方案中默认情况下是启用的。您可以与社交和企业身份提供商(如谷歌、脸书、亚马逊和微软 Active Directory)集成,但该解决方案会创建自己的用户池,其中包含特定于应用程序的帐户。您只需要在堆栈创建过程中提供一个电子邮件地址来接收临时登录凭证。

图 3: Amazon Cognito 登录
当 Amazon Cognito 身份验证启用时,您将在首次尝试访问应用程序时看到托管登录页面。使用临时登录凭据,然后输入该帐户的新密码。成功登录后,您将能够看到您的仪表板。
摘要
有时,机器学习的仪表板可以直接从您的开发机器上展示。但是,当您需要与世界其他地方(或您的公司内部)共享您的仪表板时,就需要一种健壮且安全的方法。
我们走过了一个可以帮助解决这个问题的解决方案:Amazon SageMaker 用于简化机器学习模型部署,Amazon ECR 和 ECS 用于运行和维护仪表板服务器,Amazon Cognito 用于控制仪表板访问。AWS CloudFormation 可用于在您自己的 AWS 帐户中自动创建解决方案的所有 AWS 资源,然后您可以根据需要定制解决方案。
🐙:点击这里查看 GitHub 上的代码
🚀:点击此处启动 AWS CloudFormation 堆栈
自动、可靠、安全地部署数据仪表板
新的开源软件,以所有语言和框架安全地自动部署数据科学家的交互式可视化
当今的数据项目需要交互式可视化,才能脱颖而出,给客户或组织中的决策者留下深刻印象。越来越多的开源仪表板框架允许数据科学家构建用户界面,而无需学习 Javascript 或 HTML。

来自 Pexels 的 ThisIsEngineering 摄影
例如,Volià以其最简单的形式显示了一个 Jupyter 笔记本,作为一个用户友好的网络应用程序——代码单元被隐藏,笔记本从上到下自动运行,用户不必在其中移动和输入。基于 Python 的小部件库提供了简单的用户控件,如滑块和下拉框。
数据科学家和分析师可以通过一个简短的教程开始使用这些框架。他们显然有技术能力找到一种方法来托管由此产生的 web 应用程序,也许是暂时在他们自己的笔记本电脑上,或者通过 AWS 帐户进行部署。
但是这个简单的部署步骤最终成为组织中采用仪表板框架最常见的障碍。
虽然这个过程可能很简单,但它本身是没有回报的——当数据科学家自豪地完成他们全新的分析时,需要运行一些乏味的命令。更糟糕的是,它容易出错,并可能暴露敏感数据。
正如自动化测试和持续集成使发布新功能变得有趣,而不是传统软件开发中的琐事一样,共享数据仪表板的任何障碍都会扼杀创新,阻碍新的迭代。
将部署选择留给您的数据科学家是不明智的,因为他们在技术上无疑是精明的。他们没有时间保护服务器,可能会选择最简单的认证系统。对于安全的定期部署,您确实需要一种统一的方法来托管您的数据团队,这种方法可以得到您的信息安全部门的全面批准。
这些仪表盘在技术上是网络应用。他们不需要 IT 部门花三个月的时间来审核他们的安全性,但需要有一种经过批准的方法来部署他们,这种方法不会像数据科学家在自己的设备上使用的临时方法那样让 IT 部门感到恐惧。
您需要知道您的所有仪表板在哪里运行,以及它们是如何被认证的。否则,可能会有过时和不安全的服务器在外面运行,暴露您的网络和敏感数据。当员工离开您的组织时,您需要能够终止他们对这些仪表板的访问。如果该员工碰巧在其个人 AWS 帐户上运行了一些仪表盘,您就不需要依靠他们来记住在哪里运行了什么,以便您可以关闭它们或转移所有权!
容器产品套件
免费的开源 ContainDS 软件产品可以为您的数据科学家提供一个统一的部署平台,允许他们以自动化、安全和可复制的方式共享基于开源框架的仪表板。
可以使用任何开源的仪表板框架。标配支持 Voilà、Streamlit、Plotly Dash、Bokeh、Panel 和 R Shiny。这些应该是您的数据科学团队可能面临的任何项目的良好起点!
ContainDS 是两个主要产品和相关开源技术的集合。

包含仪表板文档(图片由作者提供)
ContainDS Dashboards 是一个在互联网或内部网络上托管和共享仪表板的平台,拥有指定的认证用户——可能是特定的同事或客户。
有时,即使这样也太开放了,所以如果由于缺乏互联网或合同原因无法通过网络访问数据而需要离线共享仪表板, ContainDS Desktop 是一款适用于 Windows 或 Mac 电脑的应用程序,允许您在本地机器上运行仪表板,并将其作为单一平面文件与其他人共享。
在这里,我们将重点介绍在线仪表板软件。
通过 JupyterHub 的在线仪表板
ContainDS Dashboards 是流行的 JupyterHub 软件的扩展。如果你已经有一个正在使用的 JupyterHub,这使得安装特别容易,但是第一次安装一个并不太复杂,而且无论如何都是有用的。
JupyterHub 是为整个团队集中管理 Jupyter 笔记本环境的一种方式。标准安装允许每个用户启动他们自己的 Jupyter 笔记本,ContainDS Dashboards 扩展允许他们直接启动用户友好的仪表板,与其他经过身份验证的用户共享它们。
JupyterHub 的不同“发行版”提供了不同的维护和可伸缩性方法。有许多定制选项,但两个主要路径是运行在 Kubernetes 上的 Zero 2 JupyterHub ,允许为大量用户或项目在多台机器上无缝扩展资源;和最小的 JupyterHub 设置一个虚拟机来运行 JupyterHub(考虑到目前云提供商提供的虚拟机范围,这仍然可以支持惊人的大量使用!).
加载你的应用文件
选择用于部署仪表板的应用程序文件有两种主要方式:您的“文件源”可以来自您现有的 Jupyter 服务器树,也可以来自 Git repo(公共或私有)。

从 GitHub repo 创建 Voilà仪表板(图片由作者提供)
如果您已经是 Jupyter 笔记本的大量用户,并且可能只想将笔记本部署为 Voilà或 Panel 应用程序,那么使用第一个选项— Jupyter Tree 可能是有意义的。你可以像平常一样编辑你的笔记本,然后当你满意的时候,进入 JupyterHub 中的 Dashboards 菜单,输入你的笔记本的路径,看到它自动部署为一个新的仪表板。
更好的是,现在有一个配套的 Jupyter 扩展,所以你可以直接从 JupyterLab 或笔记本一键创建一个仪表板。
或者,如果您习惯于在本地机器上编辑 Streamlit、R Shiny、Plotly Dash 应用程序等,将您的代码签入 Git repo,然后指示 ContainDS Dashboards 直接从您的 repo 中提取并部署它,可能会更方便。你可以使用公共或私有 Git 回购,GitHub 集成意味着你可以通过 GitHub 帐户一键登录 JupyterHub,并在此过程中自动授予对你的回购的访问权限。
使用任何一种文件源方法,您也可以从多个 Conda 环境中进行选择,如果您已经为 JupyterHub 用户提供了这些环境的话。
从下拉列表中选择正确的“框架”也很重要,以确保使用正确的机制来服务仪表板。正如已经列出的,Voilà、Streamlit、Plotly Dash、Bokeh、Panel 和 R Shiny 目前都支持开箱即用,但很容易添加任何作为 web 应用程序工作的自定义框架。
一旦部署,仪表板实际上就像独立的 Jupyter 服务器,但它们不是运行 Jupyter notebook,而是直接运行您选择的框架的服务器软件。如果您曾经尝试过 Jupyter 笔记本中的 Voilà Preview 按钮,您会对最终结果很熟悉——但是在 ContainDS 仪表板的情况下,部署根本没有 Jupyter 前端。您的应用程序将被部署为纯 web 应用程序。这正是你要与他人分享的应用程序所需要的…最终用户不应该能够在你的服务器上运行任意代码。
与其他用户共享
添加到 JupyterHub 中的新仪表板菜单不仅用于注册新仪表板以进行部署,还用作与您共享的任何仪表板的内容列表。

仪表板主菜单屏幕(作者图片)
当您创建仪表板时,您可以选择是将其提供给 JupyterHub 中的所有用户,还是仅提供给选定的指定用户。JupyterHub 允许多种身份验证方法,例如,使用 LDAP 或 Google 单点登录,您的所有同事都可以通过自动为他们创建的帐户轻松访问您的仪表板。

为仪表板访问选择命名用户(按作者排序的图片)
授权用户可以点击任何与其共享的仪表板,点击确认 OAuth 同意屏幕,然后立即开始与仪表板交互。

在 ContainDS 仪表板内运行的仪表板可视化示例(图片由作者提供)
可扩展和可配置
关于 JupyterHub 的一切都是高度可配置的:从您托管它的位置(Kubernetes,在云 VM 上,或者在您的内部网络上)到用户登录时如何认证。
这同样适用于 ContainDS 仪表板——您可以完全控制它的行为方式,甚至可以通过编辑配置文件来插入您自己的仪表板可视化框架(例如,基于 Flask 的 web 应用程序)。
结论
这是对 ContainDS 仪表板的一个快速概述,解释了数据科学家部署一个新的交互式可视化来与客户或同事共享是多么容易。
您的数据科学家已经在试验新的可视化框架,这些框架在过去几年中出现在开源领域。他们的应用程序在他们的开发机器上运行得很好,但是当他们需要部署它时总是很痛苦。
通常,他们会转而导出 PDF 文件,或者只是将图表复制粘贴到电子邮件中。这是一个真正错过的机会,让决策者真正沉浸在数据模型中。
如果仪表板最终被部署,它通常不是以 it 批准的方式进行的,只有简单的身份验证步骤和托管在任意云服务器上。
对于大中型数据科学团队来说,不同的项目有不同的需求,数据科学家希望选择对他们自己的技能和项目需求有意义的开源框架。
为了克服这些问题,ContainDS Dashboards 提供了一个统一的部署和共享模型,无论数据科学团队使用何种技术来推动他们的分析,都可以由 IT 部门管理和轻松使用该模型。
有关安装详情,请参见包含仪表板文档。
丹·莱斯特是 Ideonate 的联合创始人,为数据科学家制作工具,包括ContainDS,这是一个为从事离散项目的团队提供的数据科学部署平台。
使用 TensorFlow 与 Docker 和 Flask 一起部署深度学习模型
通常,任何数据科学项目的生命周期都包括定义问题陈述、收集和预处理数据,然后是数据分析和预测建模,但任何数据科学项目最棘手的部分是模型部署,我们希望最终用户使用我们的模型。有许多部署机器学习模型的方法,但 TensorFlow serving 是一个高性能的模型部署系统,它使在生产环境中随着时间的推移维护和更新模型变得非常容易。

深度学习模型部署,TensorFlow 服务在 Docker 中运行,由 Flask App 使用
在本教程中,我们将借助 Docker 提供的 TensorFlow 部署一个预训练的 TensorFlow 模型,还将使用 Flask web framework 创建一个可视化 web 界面,该界面将用于从所提供的 TensorFlow 模型中获取预测,并使最终用户能够通过 API 调用进行消费。
TensorFlow serving 为开发人员提供了一个将人工智能融入软件系统的简单集成,并且已经被用于生产大量的谷歌产品。它可以同时服务于多个模型和同一模型的多个版本。Flask 是一个轻量级的 python web 框架,它让开发者可以轻松快速地创建 web 应用。Docker 是一个将软件组件隔离到容器中的工具,所有的软件依赖项都作为一个包安装和部署在容器中。
让我们把手弄脏吧!!
本教程将假设您运行的是 python 3.7 版的 Windows
让我们看一下目录结构,以便更好地理解模型结构和 Flask web app。

App.py—flask app 的主应用文件/控制器Model.py—将 TensorFlow 模型服务器连接到 flask web 应用程序pets—预训练保存的猫和狗分类 ML 模型Template—包含 flask 应用程序将提供的 html 文件static—包含应用程序的静态内容,例如图像
在本地主机上设置 TensorFlow 服务服务器
因为我们的 pets 文件夹中有一个预先训练好的模型,所以我们必须指定本地机器上的模型路径和模型将暴露到的端口,以便我们的 Flask 应用程序可以调用本地主机上的那个端口,并发送数据以获得预测。
Docker RUN 命令将安装 TensorFlow 服务的 Docker 映像,并将创建指向 pets 模型的 docker 实例。
先决条件:请启用 Hyper-V 功能并安装 docker
以管理员身份运行 CMD 并执行以下命令:
docker run -p 8501:8501 — name=pets -v “C:\pets:/models/pets/1” -e MODEL_NAME=pets tensorflow/serving
命令行参数的详细信息如下:
-p 8501:8501 —指定本地主机上 TensorFlow 服务器的端口 8501,docker 公开冒号后的端口用于服务
--name=pets —指定 docker 实例名称
-v “C:\pets:/models/pets/1” —指定本地主机上的模型路径和 docker 实例
内的模型路径注意:在模型路径“/models/pets/1”中,目录名“pets”应该与模型名环境变量相匹配,/1表示模型的版本,可以使用这个版本号升级模型。
-e MODEL_NAME=pets —指定模型名称环境变量
tensorflow/serving —指定要下载的 docker 图像名称
执行该命令后,您应该会得到以下输出:

现在,我们已经在localhost:8501上设置了模型服务器,让我们开发可视化 web 界面,它将使用 REST API 调用来使用模型。
使用引导程序对烧瓶 App 进行编码
现在,我们将遍历app.py文件,它将作为应用程序的控制器。这里,我们正在创建 flask app 的一个实例,并向接受 GET 和 POST 请求并将上传的图像保存在静态文件夹中的index.html 添加一个默认路由,然后静态文件夹调用 model.get_prediction 函数来获取预测并将其传递给result.html。
我们将简单地在 bootstrap 类中传递 app 实例,以便在 html 文件中使用 Bootstrap 功能。
我们可以在index.html 中编写一个完整的 html 代码,也可以使用 jinja 模板引擎将其分解成组件。现在,为了在我们的 html 文件中使用 bootstrap 和一些常见功能,我们将编写一个base.html ,它将从 Bootstrap 扩展base.html ,并设置应用程序的标题和定义内容块占位符。
接下来,我们编写一个index.html ,在其中我们扩展了 base.html,并进一步开发了上传图像的功能。
使用下面的代码在result.html中显示来自模型的预测和输入图像
到目前为止,TensorFlow 服务器已经启动,可视化 web 界面开发也接近完成,让我们通过在model.py 中编写一个小函数来连接这两个独立的实体,该函数将在 JSON 对象中加载、预处理和编码图像,并使用MODEL_URI向模型服务器发出 post 请求,并对模型预测执行后处理。
设置环境并运行应用
为避免现有安装出现问题,建议为此应用创建一个新的虚拟环境。
先决条件:请安装 anaconda 用于管理虚拟环境。
让我们创建一个虚拟环境并通过执行以下命令安装 flask 及其依赖项。
conda create –n flaskapp python=3.7
conda activate flaskapp
pip install tensorflow==2.1.0 flask flask-bootstrap requests pillow grpcio grpcio-tools
转到保存app.py 的目录,使用以下命令启动 flask 应用程序,但要确保 TensorFlow 服务的 docker 实例已经启动并正在运行。
python app.py
如果您获得以下输出,这意味着应用程序在本地主机上成功运行。

flask 的默认端口是 5000,因此通过键入localhost:5000 在浏览器中访问该应用程序,您应该会看到以下输出。

在上传猫图像并按下上传按钮后,应用程序将显示以下结果。

就是这样—模型部署从未如此简单。您刚刚学习了如何通过 docker 和 minimal flask web framework 利用 TensorFlow 服务的能力来构建一个简单的 AI 应用程序。
本教程是所有希望开发令人兴奋的人工智能应用程序的新手的快速入门。你可以在 Keras ( 这里)找到很多预先训练好的模型,在 Github 可以找到本教程的完整代码。
请在评论中留下您的疑问、反馈或建议。敬请关注更多内容!
在 Windows 上部署 Flask
一次悲伤痛苦的自我反省之旅。

塔达斯·萨尔在 Unsplash 上拍摄的照片
NB: 如果你会用 linux 请做!我不得不在我的公司使用 Windows,因为它不会给我们 linux 系统。因此,经过一番折腾之后,我不得不弄清楚如何部署 flask API。
对于这篇短文,我不会详细介绍 flask API 的实际创建,而是更多地介绍如何部署。这里是一个超级浓缩的一步一步让一个 flask API 运行。
安装:
pip install flask waitress
你会注意到我们正在安装女服务员,这是一个 Windows 兼容的服务器,我们可以使用它在多线程上部署我们的 flask 应用程序。这实际上是一个非常好的方法!下面是我们的 API 代码:
API 代码:
from flask import Flask
from waitress import serveapp = Flask(__name__)
[@app](http://twitter.com/app).route('/api/v1/')
def myendpoint():
return 'We are computering now'**serve(app, host='0.0.0.0', port=8080, threads=1) #WAITRESS!**
从上面可以看出,我们有一个超级复杂的 API,可以在运行时从浏览器调用:
python server.py
我们应该能够导航到http://myIP:8080/API/v1并得到预期的响应。
这一切都很好,但现在该怎么办呢?在 Windows 上,我们如何确保它在启动时运行?任务调度器是我如何做的。首先,确保你有管理员权限,然后打开任务调度。****

创建任务时,有一些非常重要的设置:
- 确保您选择了最高权限框

2.触发任务在启动时运行

3.确保你使用 pythonw 在后台运行(否则你将永远有一个命令提示)
4.使用 python 文件所在的起始目录。

嘣!这样,您应该能够点击 run 并测试您的端点。运气好的话,下次重新启动时,作业应该会触发并运行!
我真心希望这能在未来帮助一些可怜的灵魂。一路平安。
****参考文献:
很多这只是实验和快照是我自己的!
使用 FLASK 将 H2o 模型部署为 API 的初学者指南
模型训练、调优和创建简单 API 的端到端示例(没有技术术语)。

我保证,如果你一直关注这篇文章,它将会是(来源:makeameme.org)
作为一名数据科学家,我们大部分时间都花在数据预处理(或者说数据角力)、模型训练、超参数调优、模型验证等方面。然而,数据科学家戴的帽子越来越多,因此,许多行业现在开始寻找能够将他们的 ML 模型转化为 API 的人。
这到底是什么意思?意思是:
- 你建立了一个非常精确的 ML 模型。
- 您现在希望其他人能够利用您的模型进行预测(因为您很好,或者因为它有利可图,或者两者兼而有之),而不需要他们看到您的整个代码。这就是 API 的用武之地..
什么是 API?
API 允许我们建立一个连接,以便外部人员可以从服务器请求数据,向服务器发送新信息,更改服务器上的现有数据以及删除服务器上的现有数据。
用更简单的术语来解释(为了本文的目的),API 是一个接口,当用户从前端请求数据时,它允许您在后端访问和操作数据(来自数据库或其他数据源)。Flask 是在后端编写数据科学 API 的最流行的 python 框架之一。
为了测试您的 API,您可以在本地运行后端服务器,默认情况下它运行在 localhost URL (http://127.0.0.1)上。这个 URL 后跟一个端口,比如说 5000,这样整个 URL 看起来就像http://127.0.0.1:5000。端口可以在 Flask 设置中更改,这样如果你想运行多个本地服务器,你可以在http://127.0.0.1:5000、http://127.0.0.1:5001等等上运行它们。
在本文中…
我们将使用 H2o AutoML 建立一个机器学习模型(使用非常少的代码行,但生成高性能的模型)。我们的模型将能够根据某些特征来预测贷款申请是被批准还是被拒绝。接下来,我们将创建我们的第一个 API,我们将向它发送一个关于客户年龄、汽车类型、贷款金额等的查询,它将返回申请的状态——批准或拒绝。
注:我将使用 Jupyter 笔记本构建和测试 H2o 模型,使用 Spyder 编写烧瓶代码。最后,我也将从 Jupyter 内部访问我的 API。
一步步走向 APIs
在我们开始为模型编写简单的 API 之前,我想简单地体验一下编写更简单的 API(不需要用户输入)的感觉。让我们开始驾驶 Spyder …
下面是我们将要使用的一些样板代码(稍后会对其进行修改):
from flask import Flask
from flask_restful import Resource, Apiapp = Flask(__name__)
api = Api(app)class HelloWorld(Resource):
def get(self):
return {'hello': 'world'}api.add_resource(HelloWorld, '/')if __name__ == '__main__':
app.run(debug=True, port = 12345)
需要注意的几件事:
- 这里的返回属于类型
dict,即一个键-值对(键是hello;值为world。 debug = True支持代码重载和更好的错误消息。切勿在生产环境中使用调试模式!- 重要的是使用
api.add_resource将您创建的任何资源(比如HelloWorld)添加到 API 中。 - 端口被显式指定为
port = 12345,因为有时默认端口可能被其他应用程序使用,并可能抛出错误。
最后,将文件保存为 medium_tut.py ,并使用顶部的绿色运行按钮(或 Mac 上的 F5)运行它。右侧控制台窗格中的输出应该如下所示:

如您所见,API 正在本地服务器[http://127.0.0.1:12345/](http://127.0.0.1:12345/.)上运行。现在打开 Jupyter Notebook 并键入以下代码来访问我们刚刚编写的 API。
from requests import get
import requestsurl = '[http://127.0.0.1:12345/'](http://127.0.0.1:12345/')
get(url).json()

写你的第一个 API 值得称赞。😃
如果您仔细注意,我们在HelloWorld中的 get 函数的返回类型是dict,因此我们在上面的代码中使用.json()来解析该字典的输出。
编写接受一个输入参数的 API
我们将修改我们之前在medium_tut.py文件中的代码,从用户端接受一个参数(更具体地说是一个数字),并将它的平方返回给用户。
from flask import Flask
from flask_restful import Resource, Api, **reqparse**app = Flask(__name__)
api = Api(app)***# argument parsing*
parser = reqparse.RequestParser()
parser.add_argument('num1')**class HelloWorld(Resource):
def get(self):
return {'hello': 'world'}**class PrintSquare(Resource):
def get(self):
*# use parser and find the user's input*
args = parser.parse_args()
user_query = float(args['num1'])
return {'ans': user_query * user_query}**api.add_resource(HelloWorld, **'/hello'**)
**api.add_resource(PrintSquare, '/sq')**if __name__ == '__main__':
app.run(debug=True, port = 12345)
评估我们所做的修改:
- 我们已经使用
parser.add_argument()将用户输入(在我们的例子中是一个数字)添加到解析器中。 - 我们现在有了一个新的类
PrintSquare来返回数字的平方。 - 由于我们现在有多个类,并且我们不希望在用户发出请求时混淆 API 应该运行哪个函数,我们必须通过添加
'/hello'作为端点来更新HelloWorld的add_resource。所以现在,HelloWorld将运行在[http://127.0.0.1:12345/](http://127.0.0.1:12345/.)hello而不是[http://127.0.0.1:12345/](http://127.0.0.1:12345/.)上
让我们看看是否可以访问我们的 API,回到 Jupyter 笔记本:
*# note the URL has been updates, i.e. the 'sq' endpoint has been added to it*
url = '[http://127.0.0.1:12345/sq'](http://127.0.0.1:12345/sq')*# we have one input parameter 'num1'*
params = {'num1': '2'}*# outputting the response from API*
response = requests.get(url, params)
response.json()

编写采用多个输入参数的 API
更新 Spyder 上的medium_tut.py文件,以接受来自用户的两个数字作为输入,并返回其总和。
from flask import Flask
from flask_restful import Resource, Api, reqparseapp = Flask(__name__)
api = Api(app)*# argument parsing*
parser = reqparse.RequestParser()
parser.add_argument('num1')
**parser.add_argument('num2')**class HelloWorld(Resource):
def get(self):
return {'hello': 'world'}class PrintSquare(Resource):
def get(self):
*# use parser and find the user's input*
args = parser.parse_args()
user_query = float(args['num1'])
return {'ans': user_query * user_query}**class PrintSum(Resource):
def get(self):
# use parser and find the user's inputs
args = parser.parse_args()
num1 = float(args['num1'])
num2 = float(args['num2'])
return {'ans': num1 + num2}**api.add_resource(HelloWorld, '/hello')
api.add_resource(PrintSquare, '/sq')
**api.add_resource(PrintSum, '/sum')**if __name__ == '__main__':
app.run(debug=True, port = 12345)
最后检查 API 是否在 Jupyter Notebook 中工作:
url = '[http://127.0.0.1:12345/sum'](http://127.0.0.1:12345/sum')*# we have two input parameters - 'num1' & 'num2*
params = {'num1': '2', 'num2': '5'}response = requests.get(url, params)
response.json()

瞧,你已经准备好为自己的 ML 模型创建 API 了。
提示:继续在桌面上(或其他地方)创建一个新目录,命名为H2o_API。这是我们将保存 Jupyter 笔记本的地方,该笔记本包含训练我们的模型的代码。稍后,当我们创建 API 脚本(在 Spyder 中)时,它也将保存在同一个目录中。这样做的全部逻辑是,当我们在本地创建和下载模型时,我们的 Flask 脚本可以访问它。
让我们深入研究数据
我们的数据集有 5 个预测特征:
- 年龄组:(老年、青年、中年)
- 汽车类型:分类(敞篷车、轿车、SUV)
- 贷款金额:浮动
- 存款:浮动
- 地区:分类(农村、城市)
以及一个结果变量,即应用 _ 结果,它可以取两个值:批准或拒绝。
我们的数据看起来是这样的:

将训练集和测试集转换为 H2o 框架
#Categorical Columns - enum
#Numerical Columns - real
col_dict = {'age_group' : 'enum',
'car_type' : 'enum',
'loanamount' : 'real',
'deposit' : 'real',
'area' : 'enum',
'application_outcome': 'enum'}train_h2o = h2o.H2OFrame(train, column_types = col_dict)
test_h2o = h2o.H2OFrame(test, column_types = col_dict)
使用 H2o AutoML 进行培训
自动机器学习(AutoML)是将机器学习应用于现实世界问题的端到端过程自动化的过程。使用 H2o 的 AutoML 接口可以很容易地执行(我将在下一篇文章中深入讨论)。简而言之,它提供了一个由许多模型的自动训练和调整获得的顶级模型组成的排行榜。
现在,让我们把它载入我们的 Jupyter 笔记本:
from h2o.automl import H2OAutoML
aml = H2OAutoML(max_models = 5, max_runtime_secs=100, seed = 1)
设置预测值和响应特征:
*# setting predictor and response features*
x = ['age_group', 'car_type', 'loanamount', 'deposit', 'area']
y = 'application_outcome'
训练过程可以简单地使用 H2o 中的一行代码来实现。
*# Training*
aml.train(x=x, y='application_outcome', training_frame=train_h2o, validation_frame=test_h2o)
最佳模型(基于默认指标 AUC)存储在aml.leader中:
aml.leader

正如你所看到的,即使没有太多的修改,我们已经在验证集上获得了 AUC = 0.87 的模型(一点也不差)!还有,注意这个模型的名字是StackedEnsemble_AllModels_AutoML_20200619_172405。您的模型的名称将类似于此,减去最后一个下划线后的部分,即172405。
将最佳模型保存到本地机器上
*# download the model built above to your local machine*
my_local_model = h2o.download_model(aml.leader, path="/Users/UserName/Desktop/H2o_API")
如果您在您的目录中检查这个保存的模型的名称,它将看起来像StackedEnsemble_AllModels_AutoML_20200619_******。
为您的模型创建 API
创建新的 python 脚本pred_API.py来编写我们的 Flask 脚本。
导入库和加载模型
from flask import Flask
from flask_restful import Resource, Api, reqparseapp = Flask(__name__)
api = Api(app)import h2o
import pandas as pd
h2o.init()*## load trained model*
model_path = 'StackedEnsemble_AllModels_AutoML_20200619_******'
uploaded_model = h2o.load_model(model_path)
解析输入参数
*# argument parsing*
parser = reqparse.RequestParser(bundle_errors=True) *# if there are 2 errors, both of their msgs will be printed*parser.add_argument('age_group', choices = ('Young', 'Older', 'Middle-Aged'), help = 'Bad Choice: {error_msg}. Valid choices are Young, Older, Middle-Aged')parser.add_argument('car_type', choices = ('SUV', 'Saloon', 'Convertible'), help = 'Bad Choice: {error_msg}. Valid choices are SUV, Saloon, Convertible')parser.add_argument('loanamount')parser.add_argument('deposit')parser.add_argument('area', choices = ('urban', 'rural'), help = 'Bad Choice: {error_msg}. Valid choices are urban, rural')
在将分类特征的值添加到解析器中时(比如age_group和car_type,我们将choices设置为一个元组,其中包含该特征可以采用的所有可能值。如果遇到选项中未提及的值,它将抛出help中指定的错误消息。
最后,我们设置bundle_errors = True,这样在两个错误的情况下,两个错误消息都被打印出来。例如,在下面的示例中,我们故意将age_group的值设置为‘older ’,将car_type的值设置为‘SUVv ’:

定义预测类
*#Categorical Columns - enum
#Numerical Columns - real*
col_dict = {'age_group' : 'enum',
'car_type' : 'enum',
'loanamount' : 'real',
'deposit' : 'real',
'area' : 'enum',
'application_outcome': 'enum'}*# prepare empty test data frame to be fed to the model*
data = {}*# results dict*
item_dict = {}class LoanPred(Resource):
def get(self):
args = parser.parse_args()
age = args['age_group']
car_type = args['car_type']
loanamount = float(args['loanamount'])
deposit = float(args['deposit'])
area = args['area']
application_outcome = 'declined' *#setting as default to declined (can set it as 'approved' as well, doesn't matter)*
*# put key:value pairs in empty dict called data*
data['age_group'] = age
data['car_type'] = car_type
data['loanamount'] = [loanamount]
data['deposit'] = [deposit]
data['area'] = area
data['application_outcome'] = application_outcome
*# creating dataframe from dict*
testing = pd.DataFrame(data)
*# converting pandas to h2o dataframe*
test = h2o.H2OFrame(testing, column_types = col_dict)
*# making predictions*
pred_ans = uploaded_model.predict(test).as_data_frame()
*# put key:value pairs in empty dict called item_dict*
item_dict['Prediction'] = pred_ans.predict.values[0]
item_dict['Approved'] = pred_ans.approved.values[0]
item_dict['Declined'] = pred_ans.declined.values[0]
return{'ans': item_dict}
api.add_resource(LoanPred, '/')if __name__ == '__main__':
app.run(debug=True, port= 1234)
我们首先获取所有输入参数,并使用它们创建一个名为testing的 pandas 数据帧。该数据帧必须转换成名为test的 H2o 帧,然后才能提供给 H2o 模型进行预测。
需要注意的一点是,model.predict()的输出是一个 h2o 帧,目前,Spyder ipython 控制台无法正确显示 H2o 数据帧(您可以在 Github 上的这里跟踪问题)。因此,我们需要使用as_data_frame()将model.predict()的输出显式转换为 pandas 数据帧。输出pred_ans是包含三列的数据帧—
- 最终预测(批准或拒绝),
- 申请被批准的概率,
- 申请被拒绝的概率。
我们将这三个值作为键值对存储在item_dict中。
最后将 pred_API.py 中的所有代码放在一个地方:
from flask import Flask
from flask_restful import Resource, Api, reqparseapp = Flask(__name__)
api = Api(app)import h2o
import pandas as pd
h2o.init()## load saved model
model_path = 'StackedEnsemble_AllModels_AutoML_20200619_******'
uploaded_model = h2o.load_model(model_path)# argument parsing
parser = reqparse.RequestParser(bundle_errors=True) #if there are 2 errors, both's msg will be printed
parser.add_argument('age_group', choices = ('Young', 'Older', 'Middle-Aged'), help = 'Bad Choice: {error_msg}. Valid choices are Young, Older, Middle-Aged')
parser.add_argument('car_type', choices = ('SUV', 'Saloon', 'Convertible'), help = 'Bad Choice: {error_msg}. Valid choices are SUV, Saloon, Convertible')
parser.add_argument('loanamount')
parser.add_argument('deposit')
parser.add_argument('area', choices = ('urban', 'rural'), help = 'Bad Choice: {error_msg}. Valid choices are urban, rural')#Categorical Columns - enum
#Numerical Columns - real
col_dict = {'age_group' : 'enum',
'car_type' : 'enum',
'loanamount' : 'real',
'deposit' : 'real',
'area' : 'enum',
'application_outcome': 'enum'}#prepare empty test data frame to be fed to the model
data = {}# results dict
item_dict = {}class LoanPred(Resource):
def get(self):
args = parser.parse_args()
age = args['age_group']
car_type = args['car_type']
loanamount = float(args['loanamount'])
deposit = float(args['deposit'])
area = args['area']
application_outcome = 'declined'
# put key:value pairs in empty dict called data
data['age_group'] = age
data['car_type'] = car_type
data['loanamount'] = [loanamount]
data['deposit'] = [deposit]
data['area'] = area
data['application_outcome'] = application_outcome
# creating dataframe from dict
testing = pd.DataFrame(data)
# converting pandas to h2o dataframe
test = h2o.H2OFrame(testing, column_types = col_dict)
# making predictions
pred_ans = uploaded_model.predict(test).as_data_frame()
# put key:value pairs in empty dict called item_dict
item_dict['Prediction'] = pred_ans.predict.values[0]
item_dict['Approved'] = pred_ans.approved.values[0]
item_dict['Declined'] = pred_ans.declined.values[0]
return{'ans': item_dict}
api.add_resource(LoanPred, '/')if __name__ == '__main__':
app.run(debug=True, port= 1234)
访问 API 以获得预测
在朱庇特的笔记本上:
*# Normal API call with all inputs in correct format*url = '[http://127.0.0.1:1234/'](http://127.0.0.1:1234/')params = {'age_group': 'Young', 'car_type': 'SUV', 'loanamount': '12342', 'deposit': '2360', 'area': 'rural' }response = requests.get(url, params)
response.json()

我们走吧..我们已经成功地进行了 API 调用,并从 H2o 中训练的模型中检索预测。现在你所要做的就是找到一个朋友,他能把这个 API 输出变成一些漂亮的网络应用程序。
结论
这是对为 ML 模型创建 API 的概念的热情介绍。希望这不会太可怕,并且描述足够详细,可以帮助您理解相关的本质。所有代码都可以在 Github 上找到。
在下一部分中,我们将学习如何使用 Flask 和 Bigquery APIs 根据用户查询参数从 Bigquery 数据集中提取数据。
直到下一次:-)
在 Heroku.com 部署 Julia 项目

嗨!今天我将向你展示如何在云应用平台 Heroku 上用 Julia 编程语言部署项目。在本例中,我将部署一个 Dashboards.jl 文件进行演示。
这篇博客的所有内容都来自我的 GitHub 库,最终产品是这里的。请稍后查看示例:)
在我们开始之前,您将需要以下内容:您的 Dashboard 文件、一个 Heroku 帐户、一个 Julia 安装,以及安装的 Heroku 命令行界面 (CLI)。对于这个例子,我将在这里使用来自的仪表板文件。
现在,您可以创建一个新文件夹来存储部署应用程序所需的所有文件。这里,我将使用文件夹juliadash作为示例目录。之后输入julia进入茱莉亚。
mkdir juliadash
cd juliadash
julia
一旦你在 Julia 中,你将需要创建一个新的项目,包含Project.toml和Manifest.toml文件,包含你需要使用的软件包和注册表的版本信息。以下代码使用这两个文件激活您的新环境,并添加您的应用程序所需的包,然后将所有信息存储在这两个文件中。
using Pkg; Pkg.activate(".")
Pkg.add("Dashboards") #Do this as many times as you need to, changing the string (containing the package name) every time.
Pkg.add("HTTP")
⋮
完成后,您可以关闭 cmd/终端窗口。
接下来,我们将创建一个Procfile,这是一个空白文件,Heroku 使用它来指导您的文件的部署。您需要创建名为 Procfile 的文件,并将以下代码行复制并粘贴到该文件中。
web: julia --project app.jl $PORT
您需要用您的应用程序的启动文件的文件名替换app.jl。然后,您可以将文件保存到您的应用程序所在的目录中。
现在,您的目录应该有您的仪表板文件、Project.toml、Manifest.toml以及Procfile。
由于您通常将仪表板应用程序托管在本地主机的一个端口上,您将需要替换您的主机方法和编号,因为 Heroku 将应用程序部署在一个随机端口上。如果您使用的是 HTTP.jl,您需要用以下内容替换您的端口:
主持方式:用"0.0.0.0"代替HTTP.Sockets.localhost
主机端口:将8080替换为parse(Int,ARGS[1])
(如果你想知道,parse(Int,ARGS[1])对应的是Procfile中的$PORT。)
这是我的 HTTP serve 函数的样子:(更多细节,请看我在这个存储库中的代码。)
HTTP.serve(handler, "0.0.0.0", parse(Int,ARGS[1]))
完成后,您可以在 cmd 或终端上打开一个新窗口,并通过键入以下内容登录 Heroku CLI 帐户:
heroku login
它应该会打开一个浏览器窗口,让您输入凭据。完成登录并关闭浏览器窗口后,您会发现自己已经登录。现在,您可以再次进入您的目录并部署您的应用程序。
请在下面的代码中将my-app-name替换为您希望调用应用程序的名称!
cd juliadash
git init
HEROKU_APP_NAME=my-app-name
heroku create $HEROKU_APP_NAME --buildpack https://github.com/Optomatica/heroku-buildpack-julia.git
git heroku git:remote -a $HEROKU_APP_NAME
git add .
git commit -am "make it better"
git push heroku master
一旦该过程完成,应用程序将被部署并投入使用!
这可能需要一段时间,但一旦完成,您就可以运行以下命令在浏览器上打开您部署的应用程序!
heroku open -a $HEROKU_APP_NAME
希望这有助于你了解更多关于使用 Heroku 部署应用程序的知识。这种方法不仅限于仪表板应用程序。
如果你想看看我做的最终产品,点击https://juliadash.herokuapp.com/了解一下!
引用:该库中的dashex.jl文件来自这里的!
使用 Tkinter 部署机器学习项目
以可执行文件格式部署免费机器学习项目的完整指南。

介绍
由于各种各样的开源库,现在开始探索数据集并使用 Python 中简单的机器学习(ML)算法进行一些初步预测是相对容易的。虽然,为了使这些训练好的模型在现实世界中有用,有必要共享它们,并使它们在其他用户机器上容易访问以进行预测。只有这样,机器学习才能被用来造福社会。
在本文中,我将带您了解如何轻松地为您的机器学习项目创建图形用户界面(GUI ),然后将您的应用程序作为可执行文件共享,该文件可以在其他机器上运行(无需最终用户安装 Python 或任何库!).如果您有兴趣了解更多,本文使用的所有代码(以及更多!)可在我的 GitHub 档案上获得。
迁移学习图像分类
为了转移我们对图形界面开发和部署的关注,在本文中,我们将使用 Tensorflow 上提供的 VGG16 预训练模型来轻松构建一个便携式图像分类器。在视频 1 中,有一个演示我们应用程序最终工作流程的快速动画。

视频 1: GUI 演示
迁移学习是一个研究领域,专注于将机器学习模型获得的有用知识转移到另一个模型,我们计划将该模型用于不同的(但在某种程度上仍然相关的)主题。这在处理有限的数据时特别有用(图 1)。

图 1:迁移学习工作流(来源)
迁移学习最常见的应用之一是计算机视觉。例如,在本文中,我们将使用在 ImageNet 数据集上预先训练的 VGG16 模型,以便快速构建一个健壮的图像分类器。事实上,ImageNet 数据集包含大量图像(1400 万)和大约 21000 个类,因此对于这种类型的任务来说非常完整。
研究人员目前正致力于将迁移学习技术应用于其他领域,如音乐[1]和文本分类[2]。
图形用户界面(GUI)
首先,我们需要导入所有必需的依赖项。
现在,我们可以利用 Tkinter 库来创建我们的图形界面(如视频 1 所示)。我们首先创建窗口的基础( root ),然后在它上面添加不同的元素,例如程序标题( tit )、框架( 框架 )加载图像以在框架上显示的按钮(choose _ image)和启动图像分类器的按钮(class _ image最后,我们实例化我们的 VGG16 模型并启动我们的 GUI ( 使用 root.mainloop() )。**
为了关联当用户按下两个 GUI 按钮中的任何一个时要执行的动作,我们可以定义两个在单击时被激活的函数( load_img() 和 classify() )。
在 load_img() 函数中,我们首先清除框架以防有任何附加的小部件,然后我们让用户上传图像,最后我们重新缩放并在窗口框架上显示图像及其文件名。
在 classify() 函数中,我们改为预处理我们的图像(使用 Keras 指南用于这个预训练的模型)并最终在帧上打印我们的分类器的前 5 个预测及其百分比置信度。
一旦我们的程序在本地运行良好,我们就可以将其导出为可执行的格式。
部署
将 Python 文件转换成可执行文件的最简单方法之一(对于 Windows 或 Linux 平台)是使用 Pyinstaller (图 2)。

图 2: Pyinstaller [3]
对于只有一个文件且没有太多依赖项的项目,只需一条命令行语句即可完成:
pyinstaller my_script_name.py
虽然,对于更复杂的项目,为项目创建一个虚拟环境并使用一个 Spec 文件可能是一个更好的主意,以便给 Pyinstaller 关于如何创建可执行文件以及包含什么资产的明确指示。在此链接可获得该项目的规格文件示例。
最后,如果我们的可执行文件可能需要不同的资产(例如图像、视频等),那么使用 NSIS 将所有东西都包含在安装系统文件中可能是一个好主意(这样更容易在另一台机器上安装可执行文件和所有需要的依赖项)。
如果您有兴趣自己使用这个应用程序,可以在我的个人网站上找到下载链接。
此外,可以用来部署机器学习系统的一些替代技术正在使用:
这些技术现在被广泛使用,它们可以使机器学习模型很容易地在 Web 上获得,尽管它们很可能会产生托管费用(而不是使用可执行文件)。
希望您喜欢这篇文章,感谢您的阅读!
联系人
如果你想了解我最新的文章和项目,请在媒体上关注我,并订阅我的邮件列表。以下是我的一些联系人详细信息:
文献学
[1]音乐分类和回归任务的迁移学习,Keunwoo Choi,Gyö rgy Fazekas。访问地点:https://arxiv.org/abs/1703.09179
[2]使用卷积神经网络进行文本分类的迁移学习的实践者指南,Tushar Semwal,Gaurav Mathur。访问地点:https://arxiv.org/abs/1801.06480
[3] Pyinstaller。将 Python 程序冻结(打包)成独立的可执行文件 Github。访问地点:https://github.com/pyinstaller/pyinstaller
在分布式实时数据流应用中部署 ML 模型
探索在 Apache Flink/Spark 或其他实时数据流应用程序中部署 ML 模型的各种策略。

过去十年,机器学习从零到一。ML 的崛起可以被视为科技行业最具决定性的时刻之一。今天,ML 模型在几乎所有的服务中无处不在。
至今仍然存在的挑战之一是使用实时数据对模型进行训练和推断。让我们来看看在数据流生产作业中可以用来进行预测的各种策略。
沿着管道建模
对实时数据进行预测的自然方法是在处理数据的管道中运行 ML 模型。

在管道执行器中部署模型
这种方法有两个主要的复杂性-
- 管道代码和模型代码的集成。
- 优化集成管道以有效利用底层资源。
综合
大多数实时数据管道都是用 Java 或 Python 编写的。 Apache Spark 和 Apache Flink 都提供 Python API。这使得使用 Scikit-Learn 或 Tensorflow 编写的模型可以轻松集成。
您也可以使用 Spark MLlib 或 Flink ML 来创建模型。这些模型便于集成,您不必担心可伸缩性和容错性。
但是如果你有一个用 Java 或 Scala 编写的预先存在的数据管道呢?在这种情况下,使用 Tensorflow Java API 或第三方库(如 MLeap 或 JPMML )来导出您的 Scikit-learn 模型并在您的代码中使用它们更有意义。JPMML 支持很多模型,但是 MLeap 更快。
最佳化
Python 和 Java/Scala 之间的选择代表了通用性和性能之间的权衡。如果您根据用例、预期的数据量和预期的延迟做出决策,那将是最好的。对于大多数应用程序,我更喜欢 Scala,因为预期的输入记录是每秒数百万条。
另一个优化是您应该分配给模型的并行执行器的数量。如果是逻辑回归或小型随机森林等轻量级模型,您甚至可以运行模型的单个实例,并将数据重新分区到单个执行器(这在生产中从来都不是一个好主意)。对于大型随机森林或深度神经网络之类的大型模型,找到正确的执行者数量主要是一项反复试验的工作。
您可能还需要优化您的 ML 模型,以便它们能够适合内存。有几种工具可用于此目的。
TensorFlow Lite 是一个开源的深度学习框架,用于设备上的推理。
www.tensorflow.org](https://www.tensorflow.org/lite)
这种方法的另一个复杂之处是将模型更新到一个更新的版本。更新通常需要全新的部署。这也使得 A/B 测试相当重要。
作为 REST 服务的模型
这是最流行的推理方法之一。在 docker 容器中运行 python 代码,并提供一个 REST 接口来获得结果。Tensorflow 已经提供了开箱即用的 REST 模型。

将 ML 模型部署为服务
对于 Java,可以使用 MLeap 或者 DeepLearning4J。在这种方法中,您还可以根据吞吐量动态地增加/减少服务器的数量。
如果您的模型调用是异步的,这种方法在数据突发的情况下(比如在重启期间)无法触发背压。这可能会导致模型服务器中的 OOM 故障。必须采取额外的预防措施来防止这种情况。
延迟也很高,因为您需要一个网络调用来获取结果。通过使用 gRPC 代替 REST,可以稍微减少延迟。
实现自己的 http/2 服务。
codeburst.io](https://codeburst.io/heres-how-you-can-go-beyond-http-1-1-59e73f68bf75)
数据库作为模型存储
如果您有固定的模型架构,例如线性回归、随机森林或小型神经网络,权重可以存储在分布式数据库中,如 Cassandra。您可以在运行时使用权重创建模型,并对新模型进行预测。

将模型存储在数据库中
这种方法是第一种和第二种方法的混合。它允许您在运行时更新模型,而不需要新的部署,同时还提供了背压功能。这是以多功能性为代价的,因为您限制了模型的潜在选项的数量。
那么应该选择哪种方法呢?
好吧,如果你想做一个简单的 POC 或者你的模型非常轻量级,就用 REST 模型服务器。运行您的模型所需的易于集成和非常少的代码更改使它成为一个有吸引力的选择。A/B 测试也可以快速完成。
如果您需要在几十毫秒内进行预测,流水线方法是首选。
最后,模型存储方法应该只在有几个模型的情况下使用,例如,每个城市数据有一个 ML 模型,并且它们也是轻量级的。
在 Azure 上部署 ML 模型
在云上创建、构建和部署您自己的 ML 模型

凯文·Ku 在 Unsplash 上的照片
介绍
在我花了 3 年多的时间在 Jupyter Notebook 上开发机器学习模型之后,我从未能够将它部署到云上。您的线性回归模型有 90%的准确性,接近完美的 R 值,高 AUC(曲线下面积)是好的,但如果您的模型没有投入使用或部署,它还有什么用?
在本文中,我将逐步创建、训练一个模型,并将其部署到 Azure Machine Learning Studio 中。请注意,这篇文章大量引用了以下 Coursera 课程。当你完成一门在线课程时,一张证书并不能说明很多关于你的事情。因此,我借此机会复制我所学到的,并在 Azure 上部署我的模型。这是我参加的课程:
[## 在 Azure | Coursera 上开发 AI 应用
本课程介绍人工智能和机器学习的概念。我们将讨论机器学习…
www.coursera.org](https://www.coursera.org/learn/developing-ai-applications-azure/)
我使用了一个免费试用版,你将获得价值 200 美元的货币来创建你的工作空间和存储空间。下面是它的链接:
[## 立即创建您的 Azure 免费帐户| Microsoft Azure
开始享受 12 个月的免费服务和 200 美元的信用点数。立即使用 Microsoft Azure 创建您的免费帐户。
创建工作空间
首先,您必须创建一个工作空间来存储您为项目创建的所有实验、模型和结果。有三种方法可以做到。
- 工作区可以在 portal.azure.com创建。

2.可以使用 Azure CLI 创建工作区

3.可以使用 Azure Notebook 创建工作区

Azure 笔记本
我们将利用 Azure Notebook 在 Azure 上创建、训练和部署我们的模型。Azure 笔记本和 Jupyter 笔记本很像。如果您想在本地环境中使用 Jupyter Notebook,请随意。以下步骤仍然有效。
[## 微软 Azure 笔记本电脑
提供对运行在微软 Azure 云上的 Jupyter 笔记本的免费在线访问。
www.notebooks.azure.com](https://www.notebooks.azure.com/)
配置文件
您需要设置您的配置文件,以便可以在多种环境中引用您的工作区(例如,虚拟机、个人笔记本电脑、工作笔记本电脑等)。).更多信息请参考文档:https://docs . Microsoft . com/en-us/python/API/azure ml-core/azure ml . core . workspace . workspace?view=azure-ml-py
# Creating your configuration file
ws.write_config(path="./", file_name="ws_config.json")# View your configuration file
!cat .azureml/ws_config.json
模特培训
现在所有的“管理问题”都解决了,你终于可以开始训练你的模型了!
“哦不,在所有累人的步骤之后,我关闭了我所有的步骤和笔记本。我如何再次进入我的环境?”
别担心,这正是配置文件的目的。通过下面两行代码,您可以轻松地将工作区加载回笔记本
# Load your workspace in a brand new environment
from azureml.core import Workspace
ws = Workspace.from_config(path="./.azureml/ws_config.json")
现在,让我们用 Sklearn 提供的波士顿房价数据集创建一个非常简单的线性回归模型。我将不详细讨论这个模型,因为这不是本文的目的。
%%writefile my_sklearn_lr.py# Load the libraries
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import os
import sklearn# Load Boston data
from sklearn.datasets import load_boston
boston_dataset = load_boston()# Train test split data
from sklearn.model_selection import train_test_split
num_Rooms_Train, num_Rooms_Test, med_price_Train, med_Price_Test = train_test_split(boston_dataset.data[:,5].reshape(-1,1), boston_dataset.target.reshape(-1,1))# Create Linear Regression model
from sklearn.linear_model import LinearRegression
price_room = LinearRegression()
price_room.fit (num_Rooms_Train,med_price_Train)
现在您已经有了一个名为 price_room 的模型,让我们将这个模型保存为一个 pickle 文件:
# Save the model
from sklearn.externals import joblib
os.makedirs("outputs", exist_ok=True)
joblib.dump(value=price_room, filename="outputs/bh_lr.pkl")
将模型注册到工作空间
将模型保存为 pickle 文件后,您可以将其上传到您的工作空间:
from azureml.core.model import Modelmodel = Model.register(workspace=ws, model_path="./outputs/bh_lr.pkl", model_name="boston_housing_lr")

哒哒!您的模型现在在您的 Azure 工作区中可用
使用 Azure ML 训练模型
如果你的电脑只有 2GB 的 RAM 怎么办(我相信这种可能性极小…)?你可以用 Azure ML Services 提供的资源来训练你的模型,而不是使用你的本地资源。导入相关库后,您可以查看所有可用的虚拟机:
from azureml.core.runconfig import RunConfiguration
from azureml.core.compute import AmlCompute
list_vms = AmlCompute.supported_vmsizes(workspace=ws)
print(list_vms)

我们将简单地使用标准 DS1 v2:
compute_config = RunConfiguration()
compute_config.target = "amlcompute"
compute_config.amlcompute.vm_size = "Standard_DS1_v2"
属国
为了让您的模型在云中工作,您需要指定依赖关系。将依赖视为购物清单。你告诉程序你做饭/训练你的模型需要什么样的杂货店/图书馆。
from azureml.core.conda_dependencies import CondaDependenciesdependencies = CondaDependencies()
dependencies.set_python_version("3.6.6")
dependencies.add_pip_package("scikit-learn==0.20.3")
dependencies.add_pip_package("numpy==1.16.2")
dependencies.add_pip_package("pandas==0.23.4")
dependencies.add_pip_package("matplotlib==3.0.0")
compute_config.environment.python.conda_dependencies = dependencies
要找出依赖项的版本,只需键入:
<INSERT YOUR LIBRARY>.show_versions()
# e.g. pd.show_versions()
在云中训练您的模型
现在是时候运行具有依赖项的模型了,配置是您之前设置的。警告,这一部分可能需要相当长的时间,特别是如果您的模型很复杂,并且您使用的 VM 处理能力很低。
from azureml.core.experiment import Experiment
from azureml.core import ScriptRunConfig# The script you specify here is the one you wrote to train your linear model
script_run_config = ScriptRunConfig(source_directory=".",script="my_sklearn_lr.py", run_config=compute_config)
experiment = Experiment(workspace=ws, name="boston_lr_model")
run = experiment.submit(config=script_run_config)
run.wait_for_completion(show_output=True)
如果你觉得无聊,你可以在你的 Azure 门户中查看日志和输出:

部署您的模型
如果一个模型不用于预测,那么它有什么用呢?让我们检索您之前在云中训练的模型,并进行一些预测。
- 找出你的模型在哪里
run.get_file_names()
2.下载您的模型
run.download_file(name="outputs/bh_lr.pkl")
3.将模型加载到您的本地环境中
from sklearn.externals import joblib
import numpy as nprun_model = joblib.load('bh_lr.pkl')
4.用你的模型做一些预测
run_model.predict(np.array([7.354]).reshape(-1,1))
5.如果不满意,重新培训模型。否则,您可以将模型注册到您的工作空间中
from azureml.core.model import Model# There are 2 ways to register your model into Azure ML# First way, using your environment
model = Model.register(workspace=ws, model_path="bh_lr.pkl", model_name="cloud_boston_lr")# Second way, using local file
run.register_model(model_name="cloud_boston_lr", model_path="outputs/bh_lr.pkl")
我们可以验证我们的两个模型都已上传:

结论
恭喜你!现在,您已经成功地在云上训练和部署了您的模型!不要玩弄工作室,并尝试部署其他模式,如 LSTM,有线电视新闻网,决策树,SVM 或任何你知道的模式。请充分利用所提供的 200 美元。
使用 TensorFlow 模型服务器将模型部署到生产环境中

来源:tensorflow.org
模型创建无疑是人工智能应用的一个重要部分,但在训练后知道什么也是非常重要的。我将展示如何通过 HTTP 和 HTTPS 服务 TensorFlow 模型,并使用 TF Model Server 轻松完成模型版本控制或模型服务器维护等工作。您还将看到为此所需的步骤以及您应该遵循的流程。我们还将了解 Kubernetes 和 GKE,以自动调整您的部署。
这篇博文中演示所用的所有代码和一些额外的例子都可以在这个 GitHub repo-上找到
我在谷歌开发小组艾哈迈达巴德的会议是关于用 TensorFlow 模型服务器将模型部署到生产中,30…
github.com](https://github.com/Rishit-dagli/GDG-Ahmedabad-2020)
我也在 GDG(谷歌开发者组织)艾哈迈达巴德发表过关于这个的演讲,在这里找到录音版本-
我演讲的录音版本
这里有同样的幻灯片-【bit.ly/tf-server-deck
我希望你已经和一些深度学习模型合作过,并且自己也做了一些模型,也可以和 Keras 一起做。
部署过程背后的动机

来源:me.me
这是对理想场景的非常准确的描述,您的模型在测试或开发环境中工作良好,当您将其应用到现实世界或生产环境中时,问题就开始出现,事情就开始失败。您还需要确保您的模型一直在运行,并且您的用户有一个与模型交互的简单方法。它还应该在所有平台上运行良好,无论是 web、Android、IoS 还是嵌入式系统。您需要一个有弹性的管道来为您的模型服务,并且需要一个有效的方法来传递数据。这些只是生产和开发之间的一些差异。
需要处理哪些事情?
- 打包模型
因此,首先您需要获得模型,并以一种您可以在生产环境中使用的方式对其进行打包。理想情况下,您不会将相同格式的 Jupyter 笔记本投入生产,如果您愿意,您可以这样做,但通常不建议这样做。
- 在云托管服务器上发布模型
然后,您会希望将您的模型托管在某个云托管的服务器上,这样您就可以为您的用户提供服务,在他们需要模型的任何时候为他们提供模型。
- 维护服务器
既然您已经将模型发布到了云托管的服务器上,那么您还需要维护它。当我说你需要维护服务器的时候,我提到的主要事情之一是自动伸缩。如果你经历了用户数量的增加,你应该能够处理好你的用户,也许是通过增加你的资源。

显示自动缩放过程的图表
- 全球可用性
您现在想要确保的另一件事是您的模型具有全球可用性。这也意味着特定地区的用户不会面临大量的延迟。
- 应用程序接口
在此之后,您还需要为您的模型提供一种与您的设备交互的方式,很可能您会提供一个 API 来使用。然后你可以调用这个 API,或者有人可以调用你的模型并得到预测结果。你还有另外一件事要维护和保持运行,那就是 API。
- 模型版本控制
因此,明天当你或你的团队对模型进行更新时,你需要确保你的用户获得你的模型的最新版本,我们将在某个时候详细讨论这一点。例如,假设您提供一些影像分类服务,您必须不断更新您的模型,以便它能够以良好的准确性预测新的可用影像。
什么是 TF 模型服务器?
现在,您已经知道了将您的模型实际部署到云托管的服务器或为您的模型提供服务需要做些什么,让我们看看什么是 TF 模型服务器,更重要的是,它如何在您的用例中为您提供帮助。
TF Serving 是 TFX 或 TensorFlow Extended 的一部分,简单来说 TF Extended 是一个 API,旨在帮助您制作生产就绪的机器学习系统。我们将只讨论 TFX 的一个特定子部分,叫做 TF 服务。

演员表:劳伦斯·莫罗尼
这就是创建一个成熟的 ML 解决方案所要做的全部工作。我希望您了解的是,建模不是创建部署的唯一部分,事实上,也不是主要过程。TF 服务帮助您轻松完成服务基础架构部分。
因此,您可能希望在多种设备上运行您的模型,可能是在移动设备、低功耗嵌入式系统或网络上。也许您可以使用 TF Lite 将其部署在移动设备和嵌入式系统上,或者创建您的模型的 JavaScript 表示并直接在 web 上运行。很多时候,拥有一个集中的模型是一个更好的主意,在这个模型中,您的设备可以发送一个响应,然后服务器会执行它们,并将它们发送回发出调用的设备。

展示 TF 服务如何运作的图表
还记得我们讨论过的模型版本化吗?在这样的架构中,你只需要在服务器上更新模型的新版本,你的所有设备就可以立即访问它。然而,如果你使用传统的方法,如发送应用程序更新,一些用户有新的模式,一些用户有旧的模式,造成了不好的体验。在基于云的环境中,要做到这一点,可以根据用户数量动态分配资源。
TF 服务让你很容易做到这一点,这样你就不会遇到“哦,我刚刚更新了我的模型,我的服务器坏了!”诸如此类的事情。现在让我们在实践中看到这一点。
实践中的 TF 服务
- 安装 TF 服务
所以当然在开始之前你需要安装 TF 服务。repo 中这个博客的代码示例已经为您输入了安装命令。安装非常简单,在这里找到安装步骤。
- 转换模型
所以,你已经有了一个模型,你要做的第一件事就是简单地把它保存成一种 TF Serving 可用的格式。这里的第三行directory_path显示了保存模型的位置,另外两行只是传递输入和输出-
tf.saved_model.simple_save( keras.backend.get_session(), directory_path, inputs = {'input_image': model.input}, outputs = {i.name: i for i in model.outputs})
如果您导航到您保存此模型的路径,您将会看到一个类似这样的目录结构,我也创建了一个目录1,这是我的模型版本,我们将看到 TF server 如何帮助我们管理和部署这些版本。还要注意你的模型保存在一个.pb扩展名中。

保存的模型目录
- 保存的模型 CLI
还有一个很棒的界面叫做保存模型 CLI,我觉得它非常有用。这为您提供了许多关于已保存模型的有用信息,如操作签名和输入输出形状。
!saved_model_cli show --dir [DIR] --all
以下是显示该工具提供的信息的示例输出-

保存的模型 CLI 输出
- 启动模型服务器
这是你启动模型服务器的方法,让我们来分解一下
os.environ["MODEL_DIR"] = MODEL_DIR%%bash --bgnohup tensorflow_model_server \ --rest_api_port = 8501 \ --model_name = test \ --model_base_path="${MODEL_DIR}" >server.log 2>&1
因此,这里的第三行告诉它使用 tensorflow 模型服务器,当然,在实际实现它时,您不会包括 bash magic cell,即代码行%bash --bg,但是作为 Iassume,您可能会使用 Colab,我已经添加了这一点,因为 Colab 不为您提供直接终端。
这里的第四行指定了运行 TF 模型服务器的端口,这也非常简单。
需要注意的是,--model_name也会出现在你服务模型的 URL 中,所以如果你有多个模型在运行,管理你的服务模型 URL 也变得容易多了。
这里的最后一行指定您想要启用日志记录,有时日志在调试时非常有用。我个人经常使用它们来很容易地找出错误。
执行推理
现在让我们进入最有趣的部分,对模型进行推理。
- 传入数据
在模型上执行推理时要记住的一点是,在传递数据时,数据应该是列表的列表,而不仅仅是列表。事实上,这对开发者来说是一个额外的优势。让我们看看这意味着什么-
xs = np.array([[case_1], [case_2] ... [case_n]])
这里的case_1、case_2……case_n都有x1、x2……xi的所有特性值。
- 为数据创建一个 JSON 对象
data = json.dumps({"signature_name": [SIGNATURE], "instances": xs.tolist()})
如果你对保存的模型有所了解,你可能知道SignatureDef,对于那些不知道它定义了张量流图中支持的计算签名的人来说。所以你可以支持函数的 I/O。通过saved_model_cli你可以很容易的找到。在实例部分,我们将放入刚刚创建的xs。
- 提出推理请求
现在你可以简单地提出一个推理请求-
json_response = requests.post(
'[http://localhost:8501/v1/models/test:predict](http://localhost:8501/v1/models/helloworld:predict)',
data = data,
headers = headers)
记住我们谈论的是版本,而不是它包含的模型 URLv1,它允许我们容易地指定我们想要使用模型的版本 1。您还可以看到 URL 中反映的型号名称test。
你的头应该是这样的,因为你是以 JSON 的形式传入数据的
headers = {"content-type": "application/json"}
- 图像!
你们中的很多人可能会觉得,看看自己如何传递图像会很有趣。事实上,这样做很容易。代替我们在上面看到的case_1,您只需用一个值列表来替换它,这些值构成了您的图像。
一些额外的优势
现在你已经知道了 TF 服务器是如何工作的,以及如何使用它。了解了这一点,这里还有一些它提供的东西。现在,您可以理解,如果我们假设您部署了模型的版本 2,在出现任何问题的情况下,您的版本 1 将仍然是活动的和可用的。
此外,当您的新型号版本部署时,您没有停机时间,您的旧版本将继续正常工作,这些事情通常非常有用。TF 模型服务器可以帮助你很容易地做到这一点。
- 关注真实代码
TF Model Server 的一个非常棒的地方是让您专注于编写真正的代码,而不是担心基础架构和管理它,这是非常有用的,作为开发人员,您不会想花时间做这些基础架构方面的事情。这反过来允许您构建更好的 ML 应用程序,并让它们更快地启动和运行。
在云上服务模型
我们现在看到的东西可以很好地扩展到云,使其更加强大,您可以随时拥有自己的服务器。我们不会在这里讨论为什么是云或内部部署,也不会讨论负载平衡是如何发生的。我们将看到一个使用 Kubernetes 在云上部署模型的简短工作流。有了 TF 模型服务器,这就变得容易多了。
- 创建集群
首先,我假设您已经训练了一个模型,并为它构建了一个 docker 映像。做到这一点的步骤非常简单,我也在本次会议的 GitHub repo 中列出了它们。我们将从创建一个包含 5 个节点的 Kubernetes 集群开始,我将向您展示如何在云上部署一个简单的resnet模型。
gcloud container clusters create resnet-serving-cluster --num-nodes 5
- 推送 docker 图像
docker tag $USER/resnet_serving gcr.io/[PROJECT_ID]/resnetdocker push gcr.io/[PROJECT_ID]/resnet
然后,您可以将 docker 映像推送到容器注册表中
- 创建部署
现在,您已经准备好创建部署了,此处显示的 YAML 文件将为部署创建元数据,如您的映像和所需的复制副本数量,我在报告中为您提供了一个示例。
kubectl create -f [yaml]
另一件要记住的事情是,当使用云上托管的模型执行推理时,您现在将使用外部 IP 来进行推理请求,而不是我们之前使用的localhost。
我们从为什么部署过程是值得的开始。然后我们看到了部署您的模型所需要的东西,版本、可用性、全球性、基础设施等等。然后我们看到了 TF Model server 为我们提供了什么,以及为什么您应该选择 TF Model server 来进行部署。然后我们看到了与 TF 模型服务器相关的过程。您还看到了它如何允许您编写真正的代码,而不必担心基础设施、版本明智的 URL 以及对它们的简单管理。然后,我们开始研究如何在云上复制这一点,并了解 Kubernetes 如何让这一点变得简单。
我为你准备了几个笔记本,它们实现了你在这篇文章中看到的所有内容,你可以自己尝试一下。
关于我
大家好,我是里希特·达利
如果你想问我一些问题,报告任何错误,建议改进,给我反馈,你可以发邮件给我
使用 Heroku 容器注册中心部署 Panel (Holoviz)仪表板

交互式 Python 仪表盘
这篇文章旨在为使用 Heroku 部署面板应用程序提供一个简要的指南。当前的面板文档使用 Heroku 的默认应用程序构建,没有涵盖这里概述的大部分过程。
个人副业的福分之一就是选择和探索的能力。我最近开始了这样一个项目,主要是出于对全球变暖及其与我们宏观经济活动的联系的好奇。这让我经历了一个激动人心但有时也很痛苦的过程,我总结如下:
使用世界银行的 API 进行数据提取(高难度)→用于建模的数据准备(EDA)(高难度)→数据建模(低难度)
对我来说,最有趣的发现是,全国平均气温可能不一定是一个微不足道的概念。在某些情况下,我发现在同一气候带的国家之间,测量期间的温度变化很大;这是我们的宏观经济活动对气温产生重大影响的一个潜在迹象。不过,需要提醒的是,还需要更多的研究。对于任何有兴趣浏览研究结果或该项目的任何其他方面的人,这里有链接。
仪表板建筑
鉴于我已经经历了组织这个困难的数据集的过程,我不希望这个附带项目保持独立。我想建立一个仪表板,使我能够通过点击世界地图上的国家来查看每个国家的数据(我的数据是按国家排列的)。我还希望这张地图有一个显示每个国家温度变化(基于指数)的色标。最后,仪表板还必须在网上公开。
基于我对 Python 可视化/部署工具的了解,我期望花很多时间找到合适的库来实现这一点。令我惊讶的是,我发现 Anaconda 的 Holoviz 生态系统,由几个可视化、dashboarding 和部署工具组成,是我计划的一站式商店。

Holoviz 是所有这些多用途工具的集合
我不会进入代码或我如何建立仪表板的细节;有足够的材料可以带你经历这些。这些教程是一个很好的开始。
部署
现在这个帖子的关键来了。这是我旅程中在互联网上找不到太多直接帮助的部分。Panel 库(Holoviz 的一部分)为管理数据交互、设置管道、使用小部件和部署动态仪表板提供了一个优秀的工具包。部署就像用。servable()。这只有在部署在您的本地环境中时才成立。但是当涉及到像 Heroku(我将在这里讨论)这样的云服务器时,你很可能会遇到问题。然而,我希望这个简短的演练将有助于解决这些问题。
web 部署的问题
1.当我开始使用 Heroku 进行部署时,我遇到的第一个问题是我环境中的许多包无法通过 pip 获得;因此,应用程序构建阶段不断失败。
2.为了纠正上述问题,我尝试了几个定制的第三方构建包,它们应该能够处理基于 conda 的环境,但没有一个对我有效。
3.即使我很幸运地找到了一个 buildpack,我意识到我的环境超过了 3GB,而 Heroku 只允许最大 500 MB 用于这样的部署。
4.Panel library 文档中的另一个选项是使用 MyBinder 进行部署,我试过了,但还是无法构建我的环境。
解决办法
通过创建 docker 文件使用 Heroku 容器注册表进行部署解决了这个问题。这是 Heroku 提供的三个部署选项中的第三个。其次,我没有使用环境文件,而是在 docker 文件中使用单独的库安装命令(这提供了更多的稳定性;然而,如果使用环境文件是强制性的,这里有一个指南。
用近乎外行的语言快速浏览 Docker
3 个重要的 docker 概念:
-
Docker 容器:一个更简单/更快速的虚拟机替代品。因此,您可以在 Docker 容器中复制您的本地环境,该容器可能运行在提供商的平台上(在本例中为 Heroku ),并在其上运行您的应用程序。
-
Docker 镜像:构建和运行 Docker 容器的指令。
-
Dockerfile :包含 docker 图像蓝图的文本文件。
以下是我用来部署我的应用程序的 docker 文件:
# Starting from base miniconda image
FROM continuumio/miniconda3# Setting working directory in destination
WORKDIR /app# This is the complete set of libraries required
RUN conda install -c pyviz holoviz
RUN conda install -c pyviz geoviews-core
RUN conda install geopandas# Copy the relevant folder into the container
COPY ./dep-test/ .# Run panel serve to start the app
CMD panel serve --address="0.0.0.0" --port=$PORT main.py --allow-websocket-origin=worldbank-climate-dashboard.herokuapp.com
我的重点是最后一个 CMD 命令;但是为了理解这一点,有必要简要介绍一下 Panel 的部署系统:
本地部署使用。servable()
我提到过。servable()方法。什么时候。servable()附加到一个 panel 对象,该对象是使用 Tornado web 服务器部署的。因此,假设我有一个 python 文件或一个 jupyter 笔记本(在上面的例子中是它的 main.py ),其中包含一个带有可显示面板对象的仪表板的全部代码,我决定使用。servable()。要访问已部署的版本,我必须使用命令提示符浏览到我的项目文件夹(注意,提示符应该在适当的 conda 环境中),并输入以下命令:
panel servefilename . py或 filename.ipynb →这将在 Tornado web 服务器中打开应用程序,并为您提供使用浏览器访问它的链接。链接通常是: http://localhost:5006/ 文件名
Web 部署使用。servable()
使用 Heroku 的 Web 部署是类似的。使用上面的 Dockerfile 文件,我们已经设置了所需的环境。CMD 命令使您能够在 shell 中运行命令;因此,这就是我们使用面板服务的地方。以下是您将如何根据自己的应用程序自定义上述 docker 文件中的 panel serve 命令:
CMD panel serve --address="0.0.0.0" --port=$PORT ***main.py*** --allow-websocket-origin=***worldbank-climate-dashboard***.herokuapp.com
考虑上面粗体和斜体部分,您将执行以下操作:
- 用包含仪表板代码的文件替换 main.py
- 将world bank-climate-dashboard替换为您在 Heroku 中为应用程序选择的名称
如果你还没有帐户,下一步就是注册 Heroku(这是免费的)。他们的网络用户界面很棒,会引导你完成应用简介的创建过程。最后,在 Heroku 的 web UI 的应用程序部署部分,您将看到三种部署方法:
- Heroku Git(使用 Heroku CLI)
- Github(连接到应用程序的 Github Repo)
- 容器注册表(使用 Heroku CLI)
选择容器注册表,将显示必要的程序。只需记住 Heroku 提供的命令的以下附加内容:
$ heroku container:push web -a 'name of your app'
$ heroku container:release web -a 'name of your app'
我的朋友们。万事如意!
PS:这里有一个仪表盘回购的链接。
整理您的 Python 脚本并连接到外部 SQL Server
Docker、Python 和 SQL Server
查看了许多链接和教程后,我决定编写一个简单的指南,介绍如何将 Python 脚本部署到 Docker 容器,然后连接到外部 SQL Server 实例,并使用 pyodbc 执行简单的插入命令。

编写本指南时,假设您已经具备:
- Docker 安装完毕,转而使用 Linux 容器
- SQL Server 实例正在运行
您需要创建 3 个文件:
- Dockerfile 文件
- main.py(这是您的主要 Python 代码)
- requirements.txt
Dockerfile 文件
FROM python:3WORKDIR /appADD requirements.txt .
ADD main.py .#Optional
ENV https_proxy=[http://[](http://proxy1.uk.webscanningservice.com:3128)proxy]:[port]
ENV http_proxy=[http://[](http://proxy1.uk.webscanningservice.com:3128)proxy]:[port]# install FreeTDS and dependencies
RUN apt-get update \
&& apt-get install unixodbc -y \
&& apt-get install unixodbc-dev -y \
&& apt-get install freetds-dev -y \
&& apt-get install freetds-bin -y \
&& apt-get install tdsodbc -y \
&& apt-get install --reinstall build-essential -y# populate "ocbcinst.ini" as this is where ODBC driver config sits
RUN echo "[FreeTDS]\n\
Description = FreeTDS Driver\n\
Driver = /usr/lib/x86_64-linux-gnu/odbc/libtdsodbc.so\n\
Setup = /usr/lib/x86_64-linux-gnu/odbc/libtdsS.so" >> /etc/odbcinst.ini#Pip command without proxy setting
RUN pip install -r requirements.txt#Use this one if you have proxy setting
RUN pip --proxy [http://](http://proxy1.uk.webscanningservice.com:3128)[proxy:port] install -r requirements.txtCMD ["python","-i","main.py"]
main.py
main.py 可能的样子示例
requirements.txt
- 选项 1
创建一个文本文件并添加一行,如下所示:
pyodbc==4.0.28
- 选项 2
如果您使用 PyCharm 或任何终端并运行 pip freeze 命令,请使用 Python 终端:
pip freeze > requirements.txt
这将产生一个包含所有必需模块的文件。
构建并运行 Docker 映像
最后,我们希望构建并运行映像。
#Build the image
docker build -t my-app .
#Run it
docker run my-app
#Find container name
docker ps --last 1
#Check logs
docker logs <container name>
如果您想浏览容器并手动运行脚本,那么修改 Dockerfile 的最后一行,构建并再次运行:
*#CMD ["python","-i","main.py"]CMD tail -f /dev/null*
这将使容器长时间运行,使您能够使用以下命令打开 bash shell:
*docker exec -ti <container name> bash*
然后您将能够浏览容器并手动执行 main.py 。

打开 bash shell 后容器的屏幕截图
如果要停止或移除容器,请使用:
*#List all containers
docker ps -a#List all container id
docker ps -aq#Stop container
docker stop <container_name>#Will remove all your containers
docker rm -f $(docker ps -aq)*
使用 SAM 在 AWS Lambda 上部署 Sklearn 机器学习
在 API 背后的无服务器架构上生产机器学习

在笔记本电脑上构建机器学习模型非常简单。
部署模型以使它们在生产中可用并不容易。
生产 ML 很难。它不仅结合了 SDE,ML 和 DevOps。但是没有放之四海而皆准的方法。
一家公司的成立取决于业务需求、财务限制和技术技能的综合因素。
虽然大多数 ML 并不适合无服务器系统,但有时还是有意义的。一会儿有意义的时候我会解释的。
目录:
- 背景资料
- 在本地训练一个模型
- 将模式推向 S3
- 构建 SAM 应用程序
- 在本地测试应用程序
- 将应用程序部署到 AWS
- 测试 API
- 结论
背景
什么时候 ML 适合无服务器?
你的 ML 很适合 Lambda,如果…
- 你的型号小。 Lambda 会在每次请求时重新加载模型,因此大型模型会导致响应时间变慢。
- 数据向量很小。 Lambda 配备了 3GB 内存上限。所以如果你的输入数据是海量的,它就会崩溃。
- 您的模型将被零星地访问。 Lambda 向外扩展(不是向上扩展)到无限,并按请求收费。因此,它非常适合间歇性的“即时”需求。
- 低成本很重要。 Lambda 每百万次请求收费 0.2 美元。
否则…考虑在 EC2 或 Sagemaker 上部署(如果钱不是问题的话)。
山姆是什么?
SAM 代表“无服务器应用程序模型”。这是一个通过代码提供 AWS 服务的开源框架。
通常,在 AWS 控制台中,总是选择基础设施即代码,而不是设置基础设施。前者更易维护,可复制,并允许在 Github 中存储版本。
教程先决条件
你需要在你的机器上设置一些东西。
- AWS 外壳(下载并配置
- AWS SAM 客户端
- 码头工人
在本地训练一个模型
本教程的重点是部署。所以我们不会关心训练一个精确的模型。但是您可以很容易地用您自己的更复杂的模型来替换它。
在 Jupyter notebook 中,首先导入所需的库。
from sklearn.datasets import load_wine
import pandas as pd
import numpy as np
import pickle
导入数据并生成数据框架。
data = load_wine() # import dataset
df = pd.DataFrame(data['data'], columns=data['feature_names']) # build dataframe
df['target'] = data['target'] # add dependent variable
df = df.sample(frac=1) # randomize the data
df.head(3)

它看起来会像这样。
将数据分成测试集和训练集。
print("row count:",len(df))
train_df = df[:150]
test_df = df[150:]
#=> row count: 178
准备数据以训练模型。
def X_and_y_from_df(df, y_column, X_columns = []):
'''Extract data from the dataframe'''
X = {}
for feature in X_columns:
X[feature] = df[feature].tolist()
y = df[y_column].tolist()
return X, yX_train, y_train = X_and_y_from_df(train_df, 'target', ['alcohol'])
X_test, y_test = X_and_y_from_df(test_df, 'target', ['alcohol'])X_train = np.array(X_train['alcohol']).reshape(-1,1)
X_test = np.array(X_test['alcohol']).reshape(-1,1)
符合模型。
from sklearn.linear_model import LogisticRegression
model = LogisticRegression()
model.fit(X_train, y_train)
腌制模型。
import pickle
pickle.dump( model, open( "pickled_model.p", "wb" ) )
太好了!现在它的格式很容易在 S3 保存。
将模式推向 S3
在与上述笔记本相同的目录中打开命令行。
创建一个 S3 桶。
$ aws s3 mb s3://sam-sklearn-lambda-123
注意:您将需要自己的全球唯一的存储桶名称。
把你的腌模推到 S3 去。
$ aws s3 cp pickled_model.p s3://lambda-app-bucket-123
AWS 服务现在可以访问您的模型,并且无需重新部署任何其他代码就可以对其进行更新或更改。
构建 SAM 应用程序
在命令行上,初始化 SAM 应用程序。
$ sam init
这将询问您 4 个问题,这些问题将用于为我们的 SAM 应用程序构建一个起始模板。
回答下面的问题。
提示:
- 您想使用哪个模板源? 1 — AWS 快速入门模板
- 您想使用哪个运行时? 2 — python3.8
- 项目名称【Sam-app】:【按“回车”保留默认名称】
- AWS 快速入门应用程序模板: 1 — Hello World 示例
现在cd进入刚刚创建的目录,用你喜欢的文本编辑器打开它。我用的是 Atom。
目录结构应该如下所示。

接下来,让我们将 lambda 代码所在的子目录的名称从/hello_world改为code/。您可以使用以下命令来完成此操作。
$ mv hello_world/ code/
现在是时候更新文件了。
template.yaml
这个文件告诉 CloudFormation 应该提供哪些服务。
更新它,如下图所示。
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: 'Serverless wine classifier'
Globals:
Function:
Timeout: 10
Resources:
WineClassifierFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: WineClassifierFunction
Handler: app.lambda_handler
Runtime: python3.8
MemorySize: 1024
Role: arn:aws:iam::421242169512:role/LambdaCanReadS3
Environment:
Variables:
s3_bucket: lambda-app-bucket-123
model_name: pickled_model.p
Events:
WineClassifier:
Type: Api
Properties:
Path: /classify
Method: post
Outputs:
WineClassifierApi:
Description: API Gateway endpoint URL for Prod stage for WineClassifier function
Value:
Fn::Sub: [https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/classify/](https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/classify/)
注意:您需要在 AWS 中创建一个 IAM 角色,它允许 Lambda 读取 S3 的文件。我的名字叫做"arn:AWS:iam::421242169512:role/lambda can reads 3 "但是你需要用你的角色的名字替换它。
上面提供了 API 网关端点和 Lambda。
它还将运行在 lambda 上的语言指定为 Python3.8,设置一些可以在我们的 Lambda 代码中访问的变量,并配置 API 网关端点。
code/app.py
这是我们的 Lambda 代码所在的地方。
import json
import sklearn
import boto3
import os
import json
import pickles3 = boto3.client('s3')
s3_bucket = os.environ['s3_bucket']
model_name = os.environ['model_name']
temp_file_path = '/tmp/' + model_namefrom sklearn.linear_model import LogisticRegressiondef lambda_handler(event, context):
# Parse input
body = event['body']
input = json.loads(body)['data']
input = float(input ) # Download pickled model from S3 and unpickle
s3.download_file(s3_bucket, model_name, temp_file_path)
with open(temp_file_path, 'rb') as f:
model = pickle.load(f) # Predict class
prediction = model.predict([[input]])[0] return {
"statusCode": 200,
"body": json.dumps({
"prediction": str(prediction),
}),
}
简而言之,它导入库,从 S3 获取模型,解析输入请求,对其进行分类,并返回响应。
code/requirement . txt
这是我们指定应该在 Lambda 上安装什么库的地方。下面是我们所需要的。
requests
boto3
sklearn
现在在命令行上运行以下命令。
$ sam build
这将创建一个.aws-sam/build目录,其中包含将被部署到 AWS 的代码。
在本地测试应用程序
在部署之前,让我们确保应用程序在本地工作。在此处得到成功回复之前,请不要继续。
运行以下命令以在本地设置应用。
$ sam local start-api
现在用卷曲达到终点。
$ curl -XPOST http://127.0.0.1:3000/classify -H 'Content-Type: application/json' -d '{"data":".10"}'
响应应该如下所示。
{"prediction": "1"}
如果你的回答如上,请继续!
将应用程序部署到 AWS
cd进入.aws-sam/build/目录。
$ cd .aws-sam
$ cd build
现在在下面跑。这将创建一个 zip 文件,其中包含将要部署的依赖项(马上)。这需要一分钟。
注意:我使用我的 S3 桶的名字,但是你应该使用你的名字。
$ sam package --template-file template.yaml --s3-bucket lambda-app-bucket-123 --output-template-file packaged.yaml
然后运行以下命令来部署您的应用程序。
$ sam deploy --template-file packaged.yaml --stack-name SklearnLambdaStack --capabilities CAPABILITY_IAM
您应该得到一个应用程序已经部署的确认。
测试 API
在之前的部署响应中,您将获得一个 URL。
如果一切正常,向该 URL 发送请求应该会返回与向本地运行的应用程序发送请求相同的响应。
$ curl -XPOST https://6lsk6c6vw2.execute-api.us-east-1.amazonaws.com/Prod/classify/ -H 'Content-Type: application/json' -d '{"data":".10"}'
所以以上应该回归。
{"prediction": "1"}
恭喜你!您已经部署了您的第一个无服务器 ML 应用程序!
结论
如您所见,在无服务器架构上部署 ML 绝非易事。
我们所走过的例子非常简单;我们甚至跳过了 API 认证,因为我不想偏离核心课程。
关于生产无服务器 ML 的例子并不多,所以我希望这有助于加速你的学习过程。
我完全期待在未来我们会看到更多更好的生产 ML 的工具。但在此之前,基础设施将与模型部署紧密结合。
我希望你觉得这很有用。一如既往,如果你遇到困难,请告诉我,我会尽力帮助你!












浙公网安备 33010602011771号