使用 Python、PyMC3 和 ArviZ 实践贝叶斯统计
高斯推断、后验预测检查、分组比较、分级线性回归
如果你认为贝叶斯定理是反直觉的,而贝叶斯统计建立在贝叶斯定理的基础上,可能很难理解。我支持你。
有无数的理由让我们应该学习贝叶斯统计,特别是贝叶斯统计正在成为表达和理解下一代深度神经网络的强大框架。
我相信,对于我们在做之前必须学习的东西,我们通过做来学习。生活中没有什么事情是如此艰难,以至于我们不能通过我们对待它的方式来使它变得更容易。
因此,这是我使它变得更容易的方法:与其在开始时讲太多的理论或术语,不如让我们把重点放在贝叶斯分析的机制上,特别是,如何用pymc 3&ArviZ进行贝叶斯分析和可视化。在记忆无穷无尽的术语之前,我们将编码解决方案并可视化结果,并使用术语和理论来解释模型。
PyMC3 是一个用于概率编程的 Python 库,具有非常简单和直观的语法。 ArviZ ,一个与 PyMC3 携手工作的 Python 库,可以帮助我们解释和可视化后验分布。
我们将把贝叶斯方法应用到一个实际问题中,展示一个端到端的贝叶斯分析,从构建问题到建立模型,再到得出先验概率,最后用 Python 实现后验分布。
在我们开始之前,让我们先了解一些基本的直觉:
贝叶斯模型也被称为概率模型,因为它们是使用概率构建的。贝叶斯使用概率作为量化不确定性的工具。因此,我们得到的答案是分布而不是点估计。
贝叶斯方法步骤
步骤 1:建立关于数据的信念,包括先验和似然函数。
第二步,使用数据和概率,按照我们对数据的信念,来更新我们的模型,检查我们的模型是否与原始数据一致。
步骤 3,根据我们的模型更新我们的数据视图。
数据
由于我对使用机器学习进行价格优化感兴趣,我决定将贝叶斯方法应用于一个西班牙高铁票价数据集,可以在这里找到。感谢大师团队搜集数据集。
from scipy import stats
import arviz as az
import numpy as np
import matplotlib.pyplot as plt
import pymc3 as pm
import seaborn as sns
import pandas as pd
from theano import shared
from sklearn import preprocessingprint('Running on PyMC3 v{}'.format(pm.__version__))data = pd.read_csv('renfe.csv')
data.drop('Unnamed: 0', axis = 1, inplace=True)
data = data.sample(frac=0.01, random_state=99)
data.head(3)
Table 1
data.isnull().sum()/len(data)
Figure 1
价格列中有 12%的值缺失,我决定用相应票价类型的平均值来填充它们。还要用最常见的值填充其他两个分类列。
data['train_class'] = data['train_class'].fillna(data['train_class'].mode().iloc[0])
data['fare'] = data['fare'].fillna(data['fare'].mode().iloc[0])
data['price'] = data.groupby('fare').transform(lambda x: x.fillna(x.mean()))
高斯推论
az.plot_kde(data['price'].values, rug=True)
plt.yticks([0], alpha=0);
Figure 2
铁路票价的 KDE 图显示了高斯型分布,除了大约几十个数据点远离均值。
让我们假设高斯分布是对火车票价格的恰当描述。因为我们不知道平均值或标准差,我们必须为它们设定先验。因此,合理的模型如下。
模型
我们将对票价数据进行高斯推断。这里有一些模型的选择。
我们将像这样实例化 PyMC3 中的模型:
- PyMC3 中的模型规范包装在 with 语句中。
先验的选择:
- μ,总体的平均值。正态分布,很广。我不知道μ的可能值,我可以设置先验来反映我的无知。根据经验,我知道火车票价格不能低于 0 或高于 300,所以我将均匀分布的边界设置为 0 和 300。你可能有不同的经历,设定不同的界限。这完全没问题。如果你有比我更可靠的先验信息,请使用它!
- σ,总体的标准差。只能为正,因此使用半正态分布。同样,非常宽。
票价可能性函数的选择:
- y 是一个观察变量,代表来自参数为μ和σ的正态分布的数据。
- 使用坚果取样抽取 1000 个后验样本。
使用 PyMC3,我们可以将模型编写如下:
model_g.py
y 表示可能性。这就是我们告诉 PyMC3 我们想要在已知(数据)的基础上处理未知的方式。
我们绘制高斯模型轨迹。这在引擎盖下的 Theano 图上运行。
az.plot_trace(trace_g);
Figure 3
- 在左边,我们有一个 KDE 图,对于 x 轴上的每个参数值,我们在 y 轴上得到一个概率,它告诉我们该参数值的可能性有多大。
- 在右边,我们得到了采样过程中每一步的单个采样值。从迹线图中,我们可以直观地从后验得到似是而非的数值。
- 上图中每个参数都有一行。对于这个模型,后验概率是二维的,所以上图显示了每个参数的边际分布。
这里有几件事需要注意:
- 我们的单个参数的采样链(左)似乎很好地收敛和稳定(没有大的漂移或其他奇怪的模式)。
- 每个变量的最大后验估计(左侧分布中的峰值)非常接近真实参数。
我们可以画出参数的联合分布。
az.plot_joint(trace_g, kind='kde', fill_last=False);
Figure 4
我看不出这两个参数之间有任何关联。这意味着我们可能在模型中没有共线性。这很好。
我们还可以对每个参数的后验分布进行详细总结。
az.summary(trace_g)
Table 2
我们还可以通过用分布的平均值和最高后验密度(HPD) 生成一个图来直观地看到上面的总结,并解释和报告贝叶斯推断的结果。
az.plot_posterior(trace_g);
Figure 5
- 与频率主义推理不同,在贝叶斯推理中,我们得到值的整个分布。
- 每次 ArviZ 计算和报告 HPD 时,默认情况下,它将使用 94%的值。
- 请注意,HPD 区间不同于置信区间。
- 在这里,我们可以这样理解,有 94%的可能性相信平均票价在 63.8 欧元和 64.4 欧元之间。
我们可以使用 Gelman Rubin 测试来正式验证链的收敛性。接近 1.0 的值表示收敛。
pm.gelman_rubin(trace_g)
bfmi = pm.bfmi(trace_g)
max_gr = max(np.max(gr_stats) for gr_stats in pm.gelman_rubin(trace_g).values())
(pm.energyplot(trace_g, legend=False, figsize=(6, 4)).set_title("BFMI = {}\nGelman-Rubin = {}".format(bfmi, max_gr)));
Figure 6
我们的模型收敛得很好,盖尔曼-鲁宾统计看起来也不错。
后验预测检查
- 后验预测检验(PPC)是一种验证模型的好方法。这个想法是从模型中生成数据,使用从后面提取的参数。
- 既然我们已经计算了后验概率,我们将说明如何使用模拟结果来推导预测。
- 以下函数将从跟踪中随机抽取 1000 个参数样本。然后,对于每个样本,它将从由该样本中的μ和σ值指定的正态分布中抽取 25798 个随机数。
ppc = pm.sample_posterior_predictive(trace_g, samples=1000, model=model_g)np.asarray(ppc['y']).shape
现在,ppc 包含 1000 个生成的数据集(每个数据集包含 25798 个样本),每个数据集使用不同于后验的参数设置。
_, ax = plt.subplots(figsize=(10, 5))
ax.hist([y.mean() for y in ppc['y']], bins=19, alpha=0.5)
ax.axvline(data.price.mean())
ax.set(title='Posterior predictive of the mean', xlabel='mean(x)', ylabel='Frequency');
Figure 7
推断的平均值非常接近实际的铁路票价平均值。
分组比较
我们可能对不同票价类型下的价格比较感兴趣。我们将重点评估影响大小,即量化两种票价类别之间的差异。为了比较票价类别,我们将使用每种票价类型的平均值。因为我们是贝叶斯,我们将努力获得票价类别之间均值差异的后验分布。
我们创建三个变量:
- 价格变量,代表票价。
- idx 变量,用数字对票价类别进行编码的分类虚拟变量。
- 最后是分组变量,包括票价类别的数量(6)
price = data['price'].values
idx = pd.Categorical(data['fare'],
categories=['Flexible', 'Promo', 'Promo +', 'Adulto ida', 'Mesa', 'Individual-Flexible']).codes
groups = len(np.unique(idx))
组比较问题的模型与前面的模型几乎相同。唯一的区别是,μ和σ是向量,而不是标量变量。这意味着,对于先验,我们传递一个形状参数,对于可能性,我们使用 idx 变量正确地索引均值和 sd 变量:
comparing_groups.py
有 6 组(票价类别),为每组绘制μ和σ的轨迹图有点困难。因此,我们创建一个汇总表:
flat_fares = az.from_pymc3(trace=trace_groups)
fares_gaussian = az.summary(flat_fares)
fares_gaussian
Table 3
很明显,各组(即票价类别)之间的平均值存在显著差异。
为了更清楚,我们在不重复比较的情况下,绘制了每个票价类别之间的差异。
- Cohen 的 d 是比较两个均值的合适效应大小。Cohen 的 d 通过使用它们的标准偏差引入了每组的可变性。
- 优势概率(ps)定义为从一组中随机选取的数据点比从另一组中随机选取的数据点具有更大值的概率。
difference_plot.py
Figure 8
基本上,上面的图告诉我们,在 94% HPD 的上述比较情况中,没有一个包括零参考值。这意味着对于所有的例子,我们可以排除零的差异。6.1 欧元到 63.5 欧元的平均差额范围足够大,足以证明客户根据不同的票价类别购买机票是合理的。
贝叶斯分层线性回归
我们希望建立一个模型来估计每种火车类型的火车票价格,同时估计所有火车类型的价格。这种类型的模型被称为分层模型或多级模型。
- 编码分类变量。
- idx 变量,用数字对训练类型进行编码的分类哑变量。
- 最后是分组变量,包含列车类型的数量(16)
encode_cat.py
Table 4
我们将建模的数据的相关部分如上所示。我们感兴趣的是不同的火车类型是否会影响票价。
层次模型
hierarchical_model.py
Figure 9
左栏中的边际后验概率信息丰富,“α_μ_tmp”告诉我们组平均价格水平,“β_μ”告诉我们购买票价类别“Promo +”比票价类型“Adulto ida”显著提高价格,购买票价类别“Promo”比票价类型“Promo +”显著提高价格,以此类推(没有低于零的质量)。
pm.traceplot(hierarchical_trace, var_names=['α_tmp'], coords={'α_tmp_dim_0': range(5)});
Figure 10
在 16 种火车类型中,我们可能想看看 5 种火车类型在票价方面的比较。通过查看“α_tmp”的边际,我们可以看到不同列车类型之间的价格存在相当大的差异;不同的宽度与我们对每个参数估计的信心程度有关——每种列车类型的测量值越多,我们的信心就越高。
对我们的一些估计进行不确定性量化是贝叶斯建模的强大之处之一。我们得到了不同列车类型价格的贝叶斯可信区间。
az.plot_forest(hierarchical_trace, var_names=['α_tmp', 'β'], combined=True);
Figure 11
最后,我们可能想计算 r 的平方:
ppc = pm.sample_posterior_predictive(hierarchical_trace, samples=2000, model=hierarchical_model)
az.r2_score(data.price.values, ppc['fare_like'])
这篇文章的目的是学习、实践和解释贝叶斯理论,而不是从数据集中得出最好的结果。不然我们就直接用 XGBoost 了。
Jupyter 笔记本可以在 Github 上找到,好好享受这周剩下的时光吧。
参考资料:
Gelman 等人(2007)的 radon 数据集是分层建模的经典。在这个数据集中…
docs.pymc.io](https://docs.pymc.io/notebooks/GLM-hierarchical.html) [## 橄榄球预测的分层模型- PyMC3 3.6 文档
编辑描述
docs.pymc.io](https://docs.pymc.io/notebooks/rugby_analytics.html?highlight=sample_posterior_predictive)
这本书:用 Python 进行贝叶斯分析
实践大数据流,Apache 大规模爆发
photo credit: pexels
介绍
在一个数据以极快的速度生成的世界中,正确分析数据并在正确的时间提供有用且有意义的结果,可以为处理数据产品的许多领域提供有用的解决方案。这可以应用于医疗保健和金融,媒体,零售,旅游服务等。一些可靠的例子包括网飞实时提供个性化推荐,亚马逊跟踪您与其平台上不同产品的交互并立即提供相关产品,或者任何需要实时传输大量数据并对其实施不同分析的企业。
能够实时处理大数据并执行不同分析的令人惊叹的框架之一是 Apache Spark 。我认为有许多资源提供了关于 Spark 的不同功能以及它在大数据社区中有多受欢迎的信息,但简单提一下 Spark 的核心功能:它采用弹性分布式数据集(RDDs)、流和大规模实时机器学习来进行快速大数据处理。在本文中,我们将通过一个实践环节来使用 Spark Streaming 组件和 pySpark 解决一个业务问题。
动机
没有人能否认社交媒体在当今社会的重要性。许多企业通过 twitter 活动收集受众的洞察力、反馈和兴趣。许多企业已经意识到,对社交媒体活动的突出分析可以帮助他们更好地了解客户的行为模式。通常,来自社交媒体的反馈可能会迅速变化,对反馈的实时分析是企业成功的一个重要过程。因此,有不同的方法可以更好地了解人们对新的产品、品牌或事件的反应。一种方法是评估与特定主题相关的推文的情绪;这个话题可以是任何与产品、品牌或事件相关的话题。我以前在 这个项目 中实现过类似的想法。另一个聪明的方法是在特定时间段内提取与我们想要的主题相关的热门#标签,比如每隔几分钟,因为带有#标签的推文有更高的参与度。
实施
我们将与 pySpark 合作,利用 Spark Streaming 组件,并使用 python 中的 TCP 套接字通过 Tweepy 库连接到 Twitter 的流媒体 API。在 Spark 中流式传输推文并将其放在 RDDs 上之后,我们对推文应用一些操作来提取顶部标签。接下来,我们使用 Spark SQL 将 top hashtags 保存在一个临时 SQL 表上。最后,我们在 python 中应用了一些可视化技术来在图形中描绘结果。下图展示了我们程序的整体架构。
The overall Architecture
了解火花流的其他使用方式也很有好处:
Different Applications of Spark Streaming (DZone)
我们的计划将包含两个模块:
1- receive-Tweets,这个模块通过 Tweepy 库处理 Twitter 的流 API 的认证和连接。该模块只有在接收到 Spark 流模块的调用并通过 TCP 套接字将 tweets 发送到 Spark 引擎时才会被触发。
2- top#tags-streaming,这个模块在 pySpark 中启动 StreamingContext,通过 socketTextStream 接收数据。接下来,我们应用一些 lambda 函数来清除 tweets 并提取#标签。然后,我们将与我们搜索的主题(新产品、品牌或事件)相关的前 10 个标签可视化。
- 我们将简要介绍第一模块的步骤:
我们进口 Tweepy 及其所需的软件包。为了访问 Twitter 的 API,我们需要四个认证密钥,我们可以通过访问 developer.twitter.com 和注册一个新的应用程序来获得。如你所见,我把它们留为空白,因为与公众共享你的认证密钥是不安全的。接下来,我们创建从 Tweepy 中的 StreamListener 模块继承的 TweetsListener 类,并覆盖 on_data()方法,以便我们可以通过套接字发送 tweets。我们可以搜索单词“足球”作为我们想要的主题,因为它在 twitter 上非常受欢迎,我们可以非常快地获得推文,但我们总是可以根据我们的用例来改变搜索词。我们还不打算运行这个 python 文件(receive-Tweets.py ),因为我们需要首先设置 SparkStreamingContext。
有关 python 中的网络以及 Tweepy 流如何工作的更多信息,请参见以下链接:
send ex 的 Tweepy 上的 Youtube 系列。
[## 使用 Tweepy - tweepy 3.5.0 文档进行流式处理
在 tweepy 中,Tweepy 的实例。Stream 建立流会话并将消息路由到 StreamListener 实例…
docs.tweepy.org](http://docs.tweepy.org/en/v3.5.0/streaming_how_to.html)
- 对于第二个模块,我们将使用 findspark 库在本地机器上定位 spark,然后从 pyspark 导入必要的包。
import findspark
findspark.init('directory that contains Apache Spark')# import necessary packagesfrom pyspark import SparkContext
from pyspark.streaming import StreamingContext
from pyspark.sql import SQLContext
from pyspark.sql.functions import desc
接下来,我们初始化 SparkContext()。SparkContext 是任何 spark 功能的入口点。当我们运行任何 Spark 应用程序时,都会启动一个驱动程序,它具有主函数,并且您的 SparkContext 会在这里启动。SparkContext 表示到 Spark 集群的连接,可用于在该集群上创建 rdd、累加器和广播变量。SparkContext 在这里使用 Py4J 启动一个 JVM 并创建一个 JavaSparkContext ( 源)。需要注意的是,每个会话中只能运行一个 SparkContext。之后,我们以 10 秒的批处理间隔启动 StreamingContext(),这意味着在流式传输期间,输入流将每 10 秒被分成几批。
sc = SparkContext()# we initiate the StreamingContext with 10 second batch interval. #next we initiate our sqlcontext
ssc = StreamingContext(sc, 10)
sqlContext = SQLContext(sc)
下一步是分配流的输入源,然后将传入的数据放入行中:
# initiate streaming text from a TCP (socket) source:
socket_stream = ssc.socketTextStream("127.0.0.1", 5555)# lines of tweets with socket_stream window of size 60, or 60 #seconds windows of time
lines = socket_stream.window(60)
值得注意的是,我们使用了与第一个模块中相同的端口号(5555)来发送推文,并且 IP 地址也是相同的,因为我们是在本地机器上运行的。此外,我们使用 window()函数来确定我们每分钟(60 秒)都在分析推文,以查看在此期间排名前 10 的标签是什么。
下面是一个有用的图片,可以帮助您更好地理解 window()函数在 Spark 中的工作方式:
现在我们已经通过了所有的先决条件,让我们看看如何清理以#开头的 tweets,并将前 10 条保存在一个临时 SQL 表中:
# just a tuple to assign namesfrom collections import namedtuplefields = ("hashtag", "count" )
Tweet = namedtuple( 'Tweet', fields )# here we apply different operations on the tweets and save them to #a temporary sql table( lines.flatMap( lambda text: text.split( " " ) ) #Splits to a list
# Checks for hashtag calls
.filter( lambda word: word.lower().startswith("#") )
.map( lambda word: ( word.lower(), 1 ) ) # Lower cases the word
.reduceByKey( lambda a, b: a + b )
# Stores in a Tweet Object
.map( lambda rec: Tweet( rec[0], rec[1] ) )
# Sorts Them in a dataframe
.foreachRDD( lambda rdd: rdd.toDF().sort( desc("count") )
# Registers only top 10 hashtags to a table.
.limit(10).registerTempTable("tweets") ) )
我们创建了一个 namedtuple 对象来保存标签及其计数。接下来,我们使用 flatmap()创建一个标记化 tweets 的数组。我们正在使用函数,因为它们需要更少的内存并且运行更快。之后,我们过滤不以#开头的推文。foreachRDD()是 pySpark 中一个重要的输出函数,可以帮助在 RDD 上运行更快的操作。在这里,我们将它应用于每个 RDD,将其转换为数据帧,最后我们将它保存到一个名为“tweets”的临时表中。
**现在,我们可以运行 receive-Tweets.py,之后我们可以通过运行:**开始流式传输
# start streaming and wait couple of minutes to get enought tweets
ssc.start()
正如我们所看到的,我在 Linux 中打开了两个终端。其中一个运行我的 Jupiter 笔记本进行 pySpark 流传输,另一个运行 read-tweets.py 文件。
运行 receive-Tweets.py 后,我们必须等待几分钟,这样我们就有足够的 Tweets 来处理:
接下来,我们导入我们的可视化库,并为“足球”主题中的前 10 个标签绘制图表。在这里,我们运行我们的流,每分钟只检查前 10 个#标签几(5)次,这只是为了学习的目的,您可以看到#标签并不经常改变,但如果您想看到更好的结果,您可以让它运行一段时间:
# import libraries to visualize the resultsimport time
from IPython import display
import matplotlib.pyplot as plt
import seaborn as sns
import pandas
%matplotlib inlinecount = 0
while count < 5:
time.sleep(5)
top_10_tags = sqlContext.sql( 'Select hashtag, count from tweets' )
top_10_df = top_10_tags.toPandas()
display.clear_output(wait=True)
plt.figure( figsize = ( 10, 8 ) )
sns.barplot( x="count", y="hashtag", data=top_10_df)
plt.show()
count = count + 1
print(conut)
结果如下:
you can zoom in on the picture and see all those #tags
重要提示:
- 这是理解 Apache spark 的流组件如何工作的一个简单例子。总是有更复杂的方法来应用相同的方法来处理不同类型的输入流,如来自 youtube 或 Amazon(媒体、零售)等流行网站的用户交互数据。股票市场是另一个使用案例,实时传输大量数据并运行不同的分析对于股票经纪公司至关重要,Apache Spark 可能是首选工具。
Apache Spark 的另一个重要组件是 MLlib,它使用户能够大规模地训练和部署有用的机器学习模型。在我的 下一篇文章 中,我经历了一个有趣的项目,详细解释了如何在 Spark MLlib 中训练和构建模型。
像往常一样,代码和 jupyter 笔记本在我的 Github 上可用。
非常感谢您的提问和评论。
参考资料:
- https://spark . Apache . org/docs/2 . 2 . 0/streaming-programming-guide . html # discretized-streams-dstreams
- https://github.com/jleetutorial/python-spark-streaming
动手端到端自动化机器学习
使用 AutoML 库在 Python 环境中进行 AutoML 编码的实践经验。
我们从 Python 中的一个基本管道方法开始,它实际上没有 AutoML,然后快速传递到著名的 AutoML 库。我们还将 OptiWisdom 的趋势自动 SaaS 解决方案(如 OptiScorer)与经典方法进行了比较。
这是对端到端自动化机器学习过程的快速介绍,从不同的角度介绍了许多不同的库。此外,您将能够对 AutoML 库进行比较并做出战略决策。
如果你不知道什么是 AutoML 或者它的用途,你也可以开始阅读下面的文章。
Python 中机器学习的流水线和端到端解决方案介绍。
从这一点开始,我们将实现一个逐步编码的例子,其思想是用 sklearn 库实现 python 中最原语编码风格的分类。在这个例子中有两个重要的问题。首先,我们将讨论 sklearn 中的流水线,这是一种非常类似于 AutoML 流程的整体方法,其次,我们将使用网格搜索方法进行非常原始的超参数优化。
本文的步骤如下图所示:
在 Python 中,一种相对较新的称为流水线的方法是实现系统并将所有步骤结合在一起的经典方式。作为一种动手的编码实践,可以用 Python 编写如下的流水线方法:
- **加载数据集:**实际上,这一步是数据连接层,对于这个非常简单的原型,我们将保持它的简单性,就像从 sklearn 库加载数据集一样:
"""
@author: sadievrenseker
"""
import pandas as pd
import numpy as np
from sklearn import datasets
data = datasets.load_iris()
2。上面的代码是从 sklearn 数据集加载的一个非常简单的数据集。直到数据被加载到数据层对象中,加载数据集的问题才结束。在本例中,我们将使用 pandas 作为数据访问层,并通过以下代码将数据集加载到 pandas 对象中:
df = pd.DataFrame(data = np.column_stack((data.data, data.target)), columns=data.feature_names + ['Species'])
df.head()
上述代码将返回以下输出:
DataFrame output for the data loading
上图展示了加载的数据框是 sklearn 数据集的原始版本。在某些数据集中,物种列可能是物种的名称,如“鸢尾”、“鸢尾-杂色”和“鸢尾-海滨”。
3。探索性数据分析(EDA): 如果是这种情况,我们将在稍后的数据预处理中处理字符串类型,从这一点开始,如果数据科学家对数据集不熟悉,他/她可能会选择探索性数据分析(EDA),这在大多数现实生活问题中都会发生。因此,上述代码后面的代码可能是一些可视化或信息,如下所示:
import seaborn as sns
sns.pairplot(df, hue='Species', size=3)
上述代码将返回以下输出:
EDA Output for Iris Data Set
在 seaborn 矩阵图上,
保存所有可能的 2D 组合中的逐列匹配和数据分布的可视化。
对于流水线操作,整个系统被插入到单个流水线中,在常规的 AutoML 方法中,有数据预处理和机器学习过程,如本章第一节中已经解释的。
对于这种实践经验,我们将使用 K-NN 连同标准的定标器和标签编码器。
因此,标准缩放器和标签编码器是预处理阶段,而 K-NN 将是机器学习阶段。
**4。编码:**如果加载的数据集有带标签的物种列,那么标签编码器解决从字符串到数值的转换。在我们的数据集例子中,这不是问题,因为原始数据集在物种列中保存数值,如下面的代码所示:
df['Species'] = LabelEncoder().fit_transform(df['Species'])
上述代码将返回以下输出:
Encoded DataFrame
**5。标准化:**在标签编码之后,我们可以继续标准化。归一化将数据集要素转换到相同的范围内。我们将使用标准分布来转换所有功能:
df.iloc[:,:4] = StandardScaler().fit_transform(df.iloc[:,:4])
上述代码将返回以下输出:
Normalized version of DataFrame
上面显示了数据的缩放版本,现在数据已准备好进行分类。
**6。测试和训练集:**我们将使用 K-NN 算法进行分类,在常规编码中,我们可以将数据分为训练集和测试集,然后进行如下分类:
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(df.iloc[:,:-1].values,
df['Species'],
test_size = 0.4,
random_state = 123)
**7。机器学习:**将数据拆分成 0.6 比 0.4 的训练/测试集后,现在可以应用 K-NN 算法了。
from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors = 3)
knn.fit(X_train,y_train)
predictions = knn.predict(X_test)
您可以在上面的代码中很容易地注意到,在上面的示例中,n_neighbors 参数被设置为 3。
**8。超参数优化:**参数优化的一个解决方案是使用网格搜索,但是在进入网格搜索之前,我们将使用如下混淆矩阵和计分器显示算法的成功:
from sklearn.metrics import confusion_matrix
cm = confusion_matrix(y_test,predictions)
print(cm)
代码执行后,我们得到的混淆矩阵如下:
[[22 0 0]
[ 0 15 1]
[ 0 2 20]]
**9。评价:**对于已经熟悉混淆矩阵的读者来说,已经很清楚我们在 60 个数据点中只有 3 个错误。也是有经验的数据科学家,以前玩过 iris 数据集可以很容易地识别出第一类的清晰分类和第二类与第三类之间的问题。为了阐明数字上的成功,让我们计算准确性的分数,如下面的代码所示:
from sklearn.metrics import accuracy_score
score = accuracy_score(y_test,predictions)
print(score)
10。Score: 我们案例的分数是 0.95,现在我们可以通过使用网格搜索来优化精确度。
from sklearn.model_selection import GridSearchCV
k_range = list(range(1, 31))
print(k_range)
param_grid = dict(n_neighbors=k_range)
print(param_grid)
grid = GridSearchCV(knn, param_grid, scoring='accuracy')
grid.fit(X_train, y_train)
print(grid.best_params_)
上面的代码使用了 sklearn 库中的 GridSearchCV 类,它实际上使用了交叉验证来寻找最佳参数,我们给出了 k 从 1 到 31 的搜索空间。所以,这里的网格搜索基本上从 k= 1 开始,每次迭代增加 k 参数值 1。GridSearchCV 类也输出最佳参数,如下所示:
{'n_neighbors': 5}
因此,针对虹膜数据集的 K-NN 模型的精度的优化参数是 k=5。
**11。流水线:**现在,我们可以把上面所有的代码放到一个流水线中,如下所示:
from sklearn.pipeline import Pipeline
pipeline = Pipeline([
('normalizer', StandardScaler()), #Step1 - normalize data
('clf', KNeighborsClassifier()) #step2 - classifier
])
print(pipeline.steps)
流水线步骤的输出如下:
[('normalizer', StandardScaler(copy=True, with_mean=True, with_std=True)), ('clf', KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',
metric_params=None, n_jobs=None, n_neighbors=5, p=2,
weights='uniform'))]
12.现在,管道对任何设置都是开放的,并且在添加到管道时,规格化器或分类算法的参数也可以部署到构造函数中。
from sklearn.model_selection import cross_validate
scores = cross_validate(pipeline, X_train, y_train)
print(scores)
上面这段代码通过使用训练数据和标签来训练整个管道。在执行之后,scores 变量保存交叉验证的每一次得分的详细信息,如下所示。
{'fit_time': array([0.00163412, 0.0012331 , 0.00207829]), 'score_time': array([0.00192475, 0.00164199, 0.00256586]), 'test_score': array([0.96875 , 1\. , 0.93103448]), 'train_score': array([0.96551724, 0.98360656, 1\. ])}
摘要
我们实现了从数据源到机器学习算法评估分数的经典 python 机器学习过程,包括超参数优化,从上面的第一步开始,一直到步骤 11。在第 11 步和第 12 步,我们用 sklearn 下的流水线方法重新实现了整个过程,并立即执行。
请再次记住,我们的步骤可以演示如下:
Steps of operations in this article
请注意,我们的方法与 CRISP-DM 步骤非常相似:
CRISP-DM Steps
这篇文章是对 AutoML 过程的一个非常原始的介绍,我们实现流水线只是为了更好的理解。
动手全球模型解释
什么特性是重要的,为什么
Photo by Bram Naus on Unsplash
本文是我关于模型可解释性和可解释人工智能系列文章的延续。如果你还没有,我强烈推荐你阅读本系列的第一篇文章— “机器学习模型解释简介”,它涵盖了模型可解释性的基础知识,从什么是模型可解释性,为什么我们需要它到模型解释的潜在区别。
在本文中,我们将通过更深入地探究全局模型解释的来龙去脉来重拾我们离开的地方。首先,我们将快速回顾一下什么是全球模型解释及其重要性。然后我们将深入其中两种最流行的方法的理论——特征重要性和部分依赖图——并应用它们来获得关于心脏病数据集的特征的信息。
什么是全局模型解释?
全局模型解释是一套帮助我们回答问题的技术,比如一个模型通常是如何表现的?哪些功能驱动预测,哪些功能对你的事业完全没用。使用这些知识,您可以对数据收集过程做出决策,创建仪表板来解释您的模型,或者使用您的领域知识来修复明显的错误。
大多数全局解释方法都是通过研究完整数据集上因变量和自变量(特征)之间的条件交互作用来工作的。他们还创建和使用大量的可视化工具,这些工具很容易理解,但包含大量用于分析模型的有用信息。
特征重要性
特征的重要性是在我们置换了特征的值之后模型的预测误差的增加,这打破了特征和真实结果之间的关系。— 可解释的机器学习,一个让黑盒模型变得可解释的指南
Figure 2: Feature importance example
概念和理论
特性重要性的概念非常简单。使用特征重要性,我们通过计算在置换/混洗给定特征的特征值之后给定模型的误差的增加来测量特征的重要性。
如果置换会增加模型误差,则特征是“重要的”。这是因为在这种情况下,模型严重依赖这一特征来做出正确的预测。另一方面,如果置换不会对误差产生太大影响或者根本不会改变误差,那么特征就是“不重要”的。
Fisher,Rudin 和 Dominici 在他们 2018 年的论文中建议,“所有的模型都是错误的,但许多是有用的……”不是随机洗牌,而是应该将功能分成两半,并交换两半。
优势
特性重要性是了解特性重要性的最流行的技术之一。这是因为这是一种简单的技术,它为您提供了关于某个特性重要性的高度压缩的全局洞察力。此外,它不需要重新训练模型,这总是一个优势,因为节省了计算时间。
不足之处
尽管特征重要性是一种应该一直使用的解释技术,但是它仍然有一些缺点。例如,不清楚您是否应该使用训练或测试集来计算特性重要性。此外,由于置换过程,当重复计算时,结果可能变化很大。
另一个问题是,特征之间的相关性会通过产生不现实的实例或者通过在两个相关特征之间分割重要性来偏离特征的重要性。
要了解更多信息,我强烈推荐你去看看 Christoph Molnar 的电子书“可解释的机器学习”,这是一本学习更多解释模型的好书。
示例和解释
模型认为什么特征对于确定患者是否患有心脏病很重要?
这个问题可以用特征重要性来回答。
正如我在文章开头提到的,我们将研究心脏病数据集。你可以在我的 Github 上或者作为 Kaggle 内核找到本教程使用的所有代码。
大多数库,如 Scikit-Learn、 XGBoost 以及其他机器学习库,已经有了自己的特征重要性方法,但是如果您想在处理来自多个库的模型时获得准确的结果,使用相同的方法来计算每个模型的特征重要性是有利的。
为了确保这一点,我们将使用 ELI5 库。ELI5 允许用户可视化和调试各种机器学习模型。它提供的不仅仅是特性的重要性,还包括特定于库的特性以及一个文本解释器。
为了计算特征的重要性,我们可以使用*permutation_importance*
方法。在计算了给定模型的特征重要性之后,我们可以使用show_weights
方法来可视化它。
利用上述方法可以得到模型的特征重要度,并对它们进行比较。
Figure 3: Feature Importance of Logistic Regression
Figure 4: Feature Importance of XGBoost
您可以看到这两个模型对于一个特性有着非常不同的重要性分数。这会对你对结果的信任度产生负面影响。
尽管如此,我们可以看到,像 ca、性别和 thal 这样的特征对于获得正确的预测非常有用,而年龄和 cp 对于获得正确的预测并不重要。
部分相关图
部分相关图(简称 PDP 或 PD 图)显示了一个或两个特征对机器学习模型的预测结果的边际效应
Figure 5: Partial Dependence Plot Example
概念和理论
部分相关图为您提供了有关特征如何影响模型预测的信息。这可以帮助我们理解什么样的特征值会给我们更高或更低的输出。
对于分类特征,可以容易地计算部分相关性。我们通过强制所有数据实例具有相同的类别来获得每个类别的估计值。例如,如果我们对性别如何影响患心脏病的几率感兴趣,我们可以首先用值“男性”替换“性别”列中的所有值,并对预测进行平均,然后用值“女性”进行平均。
计算回归的部分相关性要困难得多,但是 Christoph Molnar 在他的电子书中很好地解释了这个问题。因此,如果你有兴趣深入了解模型解释,一定要去看看。
示例和解释
为了创建部分相关图,我们将使用 PDPbox 库。PDPbox 为我们提供了一些不同的精心设计的图,包括单个功能的部分依赖图以及多个功能的部分依赖图。
Figure 6: PDP’s for one and two features
要安装 PDPbox,我们可以键入:
pip install git+https://github.com/SauceCat/PDPbox.git
现在我们可以使用pdp_isolate
和pdp_plot
方法创建一个部分相关图来分析不同性别对患心脏病概率的影响。
Figure 7: PDP for Gender
当将性别从 sex_0 更改为 sex_1 时,黄黑线给出了预测的平均效果。只看这条线,我们就能看出性别为 0 的患者比性别为 1 的患者更有可能患心脏病。
为了创建一个部分依赖图,向我们展示目标上两个特征的交互作用,我们可以使用pdp_interact
和pdp_interact_plot
方法。
Figure 8: 2d partial dependence plot
这可以帮助我们找到两个特征之间的相互作用,甚至是单个特征值。例如,我们可以看到,无论性别栏的值如何,年龄在 55 岁至 63 岁之间的患者患心脏病的概率最低。
结论
全局模型解释是帮助我们回答一些问题的技术,比如一个模型通常是如何表现的?哪些功能驱动预测,哪些功能对你的事业完全没用。
两种最常用的全局模型解释技术是特征重要性和部分相关图。
我们可以使用特征重要性来了解模型认为特征对于进行预测有多重要。
部分相关图有助于我们理解特定特征值如何影响预测。这是非常有用的,因为它允许你对特定的特征值感兴趣,然后可以进一步分析或共享。
下一步是什么?
在本系列的第 3 部分中,我们将深入了解什么是局部模型解释,以及两种局部模型解释技术(石灰值和 Shapely 值)是如何工作的,从而更深入地了解个人预测。
这就是这篇文章的全部内容。如果你有任何问题或者只是想和我聊天,请在下面留下评论或者在社交媒体上联系我。如果你想获得我博客的持续更新,请确保在 Medium 上关注我,并加入我的简讯。
PyTorch 和 PyTorch 几何图形的手动图形神经网络
在我上一篇文章中,我介绍了图形神经网络(GNN)的概念以及它的一些最新进展。由于这个话题被大肆炒作,我决定制作这个教程,讲述如何在你的项目中轻松实现你的图形神经网络。您将学习如何使用 PyTorch Geometric 构建自己的 GNN,以及如何使用 GNN 解决现实世界中的问题(Recsys Challenge 2015)。
在这篇博文中,我们将使用 PyTorch 和 PyTorch Geometric (PyG),这是一个基于 PyTorch 构建的图形神经网络框架,运行速度快得惊人。它比最著名的 GNN 框架 DGL 快好几倍。
除了其非凡的速度,PyG 还提供了一系列实现良好的 GNN 模型,这些模型在各种论文中都有说明。因此,用 PyG 重现实验将会非常方便。
A Subset of The Implemented Models (https://github.com/rusty1s/pytorch_geometric)
鉴于其在速度和便利性方面的优势,毫无疑问,PyG 是最受欢迎和使用最广泛的 GNN 库之一。让我们进入主题,把我们的手弄脏!
要求
- PyTorch — 1.1.0
- PyTorch 几何图形— 1.2.0
PyTorch 几何基础
本节将带您了解 PyG 的基础知识。基本上会涵盖 torch_geometric.data 和 torch_geometric.nn 。您将学习如何将几何数据传递到您的 GNN,以及如何设计一个自定义的消息传递层,GNN 的核心。
数据
torch_geometric.data 模块包含一个数据类,允许您非常容易地从数据中创建图表。您只需指定:
- 与每个节点相关联的属性/特征
- 每个节点的连通性/邻接性(边索引)
让我们使用下图来演示如何创建数据对象
Example Graph
因此,图中有 4 个节点,v1 … v4,每个节点都与一个二维特征向量相关联,并且标签 y 指示其类别。这两个可以表示为浮动传感器:
图的连通性(边索引)应该用首席运营官格式限制,即第一个列表包含源节点的索引,而目标节点的索引在第二个列表中指定。
请注意,边索引的顺序与您创建的数据对象无关,因为此类信息仅用于计算邻接矩阵。因此,上面的 edge_index 表示与下面的相同的信息。
将它们放在一起,我们可以创建如下所示的数据对象:
资料组
数据集的创建过程不是很简单,但是对于那些使用过 torchvision 的人来说,它似乎很熟悉,因为 PyG 遵循它的惯例。PyG 提供了两种不同类型的数据集类,InMemorydataset 和 Dataset。顾名思义,前一个用于适合 RAM 的数据,而第二个用于更大的数据。由于它们的实现非常相似,所以我将只介绍 InMemoryDataset。
要创建 InMemoryDataset 对象,需要实现 4 个函数:
- raw_file_names()
它返回一个列表,显示原始的、未处理的文件名列表。如果你只有一个文件,那么返回的列表应该只包含一个元素。事实上,您可以简单地返回一个空列表,然后在*过程()*中指定您的文件。
- 已处理文件名()
与上一个函数类似,它也返回一个包含所有已处理数据的文件名的列表。调用 process()后,通常返回的列表应该只有一个元素,存储唯一处理过的数据文件名。
- 下载()
这个函数应该将您正在处理的数据下载到 self.raw_dir 中指定的目录中。如果你不需要下载数据,就直接来
pass
在函数中。
- 流程()
这是数据集最重要的方法。您需要将数据收集到一个数据对象列表中。然后,调用 self.collate() 来计算 DataLoader 对象将使用的切片。下面是一个来自 PyG 官网的自定义数据集的例子。
在本文后面,我将向您展示如何根据 RecSys 挑战赛中提供的数据创建自定义数据集。
数据加载器
DataLoader 类允许您轻松地将数据批量输入到模型中。要创建 DataLoader 对象,只需指定所需的数据集和批处理大小。
loader = DataLoader(dataset, batch_size=512, shuffle=True)
DataLoader 对象的每次迭代都会生成一个 batch 对象,该对象非常类似于数据对象,但带有一个属性“Batch”。它指示每个节点与哪个图相关联。由于数据加载器将来自不同样本/图形的 x 、 y 和 edge_index 聚集成批,因此 GNN 模型需要这种“批”信息来知道哪些节点属于一批中的同一个图形以执行计算。
**for** batch **in** loader:
batch
>>> Batch(x=[1024, 21], edge_index=[2, 1568], y=[512], batch=[1024])
信息传递
消息传递是 GNN 的本质,它描述了如何学习节点嵌入。我在上一篇文章中已经谈到了,所以我将简单地用符合 PyG 文档的术语来介绍一下。
Message Passing
x 表示节点嵌入, e 表示边特征,𝜙表示消息功能,□表示聚合功能,更新功能。如果图中的边除了连通性之外没有其他特征,则 e 本质上是图的边指数。上标代表层的索引。当 k=1 时, x 表示每个节点的输入特征。下面我将说明每个功能的工作原理:
- *propagate(edge_index,size=None,*kwargs):
它接受边索引和其他可选信息,如节点特征(嵌入)。调用此函数将会调用消息和更新。
- *消息(*kwargs):
您指定如何为每个节点对(x_i,x_j)构造“消息”。因为它跟随传播的调用,所以它可以接受传递给传播的任何参数。需要注意的一点是,可以用“_i”和“_j”定义从参数到特定节点的映射。因此,命名该函数的参数时必须非常小心。
- *更新(aggr_out,*kwargs)
它接收聚合的消息和传递到 propagate 的其他参数,为每个节点分配一个新的嵌入值。
例子
让我们从论文 “大型图的归纳表示学习” 来看看如何实现一个 SageConv 层。SageConv 的消息传递公式定义为:
https://arxiv.org/abs/1706.02216
这里,我们使用最大池作为聚合方法。因此,第一行的右边可以写成:
https://arxiv.org/abs/1706.02216
这说明了“消息”是如何构造的。每个嵌入的相邻节点乘以一个权重矩阵,加上一个偏差,并通过一个激活函数。这可以用 torch.nn.Linear 轻松做到。
class SAGEConv(MessagePassing):
def __init__(self, in_channels, out_channels):
super(SAGEConv, self).__init__(aggr='max')
self.lin = torch.nn.Linear(in_channels, out_channels)
self.act = torch.nn.ReLU()
def message(self, x_j):
# x_j has shape [E, in_channels]
x_j = self.lin(x_j)
x_j = self.act(x_j)
return x_j
至于更新部分,聚合消息和当前节点嵌入是聚合的。然后,将其乘以另一个权重矩阵,并应用另一个激活函数。
class SAGEConv(MessagePassing):
def __init__(self, in_channels, out_channels):
super(SAGEConv, self).__init__(aggr='max')
self.update_lin = torch.nn.Linear(in_channels + out_channels, in_channels, bias=False)
self.update_act = torch.nn.ReLU()
def update(self, aggr_out, x):
# aggr_out has shape [N, out_channels]
new_embedding = torch.cat([aggr_out, x], dim=1)
new_embedding = self.update_lin(new_embedding)
new_embedding = torch.update_act(new_embedding)
return new_embedding
放在一起,我们有下面的 SageConv 层。
一个真实的例子—2015 年 RecSys 挑战赛
RecSys 挑战赛 2015 向数据科学家发起挑战,要求他们构建一个基于会话的推荐系统。这项挑战要求参与者完成两项任务:
- 预测是否会有一个购买事件,随后是一系列的点击
- 预测哪件商品将被购买
首先我们从 RecSys Challenge 2015 官网下载数据,构建数据集。我们将从第一项任务开始,因为那项更容易。
该挑战提供了两组主要数据, yoochoose-clicks.dat 和 yoochoose-buys.dat ,分别包含点击事件和购买事件。让我们快速浏览一下数据:
yoochoose-click.dat
yoochoose-buys.dat
预处理
下载完数据后,我们对其进行预处理,以便将其输入到我们的模型中。item _ id 被分类编码以确保编码的 item _ id 从 0 开始,该编码的 item _ id 稍后将被映射到嵌入矩阵。
由于数据非常大,为了便于演示,我们对其进行了二次抽样。
Number of unique elements in the subsampled data
为了确定基本事实,即给定会话是否有任何购买事件,我们只需检查 yoochoose-clicks.dat 中的 session_id 是否也出现在 yoochoose-buys.dat 中。
数据集构建
在预处理步骤之后,数据就可以转换成 Dataset 对象了。这里,我们将会话中的每个项目视为一个节点,因此同一会话中的所有项目构成一个图。为了构建数据集,我们通过 session_id 对预处理后的数据进行分组,并迭代这些组。在每次迭代中,每个组中的 item_id 被再次分类编码,因为对于每个图,节点索引应该从 0 开始计数。因此,我们有以下内容:
在构建数据集之后,我们调用 shuffle() 来确保它已经被随机打乱,然后将它分成三组用于训练、验证和测试。
构建图形神经网络
下面的自定义 GNN 引用了 PyG 官方 Github 库中的一个例子。我用我们自己实现的 SAGEConv 层改变了 GraphConv 层,如上图所示。此外,还修改了输出图层以匹配二进制分类设置。
培养
训练我们的自定义 GNN 非常容易,我们只需迭代从训练集构建的数据加载器,并反向传播损失函数。这里,我们使用 Adam 作为优化器,学习率设置为 0.005,二进制交叉熵作为损失函数。
确认
这种标签是高度不平衡的,有大量的负面标签,因为大多数会议之后没有任何购买活动。换句话说,一个愚蠢的模型猜测所有的否定会给你 90%以上的准确率。因此,曲线下面积(AUC)是该任务的更好指标,而不是准确性,因为它只关心正面示例的得分是否高于负面示例。我们使用 Sklearn 现成的 AUC 计算功能。
结果
我对模型进行了 1 个时期的训练,并测量了训练、验证和测试的 AUC 分数:
仅用 100 万行训练数据(约占所有数据的 10%)和 1 个时期的训练,我们可以获得验证和测试集的 AUC 分数约为 0.73。如果使用更多的数据以更大的训练步长来训练模型,分数很可能会提高。
结论
您已经学习了 PyTorch Geometric 的基本用法,包括数据集构造、自定义图层以及用真实数据训练 gnn。这篇文章中的所有代码也可以在我的 Github repo 中找到,在那里你可以找到另一个 Jupyter 笔记本文件,我在其中解决了 RecSys Challenge 2015 的第二个任务。我希望你喜欢这篇文章。如果您有任何问题或意见,请在下面留下!确保在 twitter 上关注我,我会在那里分享我的博客帖子或有趣的机器学习/深度学习新闻!和 PyG 玩 GNN 玩得开心!
机器学习实践演示:
source: bawilabs
利用 YOLO·V2 进行实时物体检测
简介
这篇博客是为了一个具体的机器学习对象检测案例,与初学者分享我的经验而写的。
深度学习是人工智能(AI)和机器学习(ML)的一个高级子领域,长期以来一直是一个学术领域。随着数据的丰富和计算能力的指数级增长,我们已经看到跨学科应用深度学习商业案例的激增。也有很多聪明人选择研究 AI/ML,许多大型高科技公司(领先 云平台 ML 包括AWS SageMaker微软 Azure AI谷歌云平台 ML&tensor flow**
只要你在世界的任何一个角落都有互联网连接,每个人工智能/人工智能爱好者都可以获得大量的公共在线培训和资源。因此没有借口留下… (如果你是一个真正的 ML 爱好者,我认为最好的硬核开始是吴恩达的 Coursera specializations。)****
看我简单的 DIY 演示视频看看这件作品经过几个小时努力的成果: 视频 1 和 视频 2 。
卷积神经网络
Source: Wikipedia
卷积神经网络 (CNN)是深度人工神经网络,主要用于对图像进行分类(即标记所看到的),通过相似性对其进行聚类(即照片搜索),并在场景内执行对象识别。它们是可以识别人脸、个人、街道标志、汽车、动物、异常、肿瘤和视觉数据的许多其他方面的算法。
卷积层用于从输入训练样本中提取特征。每个卷积图层都有一组有助于要素提取的过滤器。一般来说,随着 CNN 模型的深度增加,通过卷积层学习的特征的复杂性增加。你可以在这里、这里或者这里了解更多关于 CNN 的信息。Andrej Karpathy在这个链接为他早期的斯坦福 CNN 课程写了一篇很棒的文章,如果你想在学术上更深入的话。
CNN 是一个如此迷人和具有颠覆性的领域,它为 人脸识别自动驾驶汽车光学字符识别疾病自动诊断图像到文本的转换神经艺术 等等开辟了可能性****
****还有许多进一步的创新机会,从帮助数百万有视觉障碍的人到进一步推进预防性医疗诊断、药物发现、 视频游戏 、全渠道零售商的货架/产品识别……天空是无限的:)这些框架也开始在边缘上工作。边缘可以是iphone,安卓小工具,亚马逊 DeepLens 等。你明白我的意思吗?
用 YOLO 进行实时物体检测
你只看一次(YOLO)——多酷的名字啊?这种目标检测算法是目前最先进的,优于 CNN 及其上述变体。也许创始人受到了人类眼睛/大脑的启发,因为 YOLO 在测试期间正在查看整个图像,所以它的预测是由图像中的全球背景提供的。它还通过单一网络评估进行预测,不像像 R-CNN 这样的系统需要数千个单一图像。YOLO V2 和 V3 可以实时检测各种对象类别。最新的 YOLO V3 甚至比 R-CNN 快 1000 倍以上,比快 R-CNN ( 参考 )快 100 倍。****
您可以向它提供任何主要的图像/视频类型或来自网络摄像头的实时视频。YOLO 也是一个卷积网络,但它以一种巧妙的方式运行。(掌声送给原文YOLO·V2 的文章这里 )
YOLO 有一种有效的方法,它首先预测图像的哪些部分包含所需的信息,然后只在这些部分上运行(CNN)分类器。简单地说,YOLO 把图像分成 13×13 的网格,网格又被分成 5 个“边界框”。边界框是包围对象的矩形。对于每个包围盒,它并行运行识别算法来识别它们属于哪个图像类别。YOLO 最终输出一个置信度(概率)分数,告诉我们预测的边界框实际上包围了一个对象(图像类)有多确定。每个输入图像都可以通过这个特殊的 CNN 快速获取,并产生一个(13 x 13 x 125)的矩阵,其中每个张量都携带独特的信息,如 x,y 参数,边界框矩形的宽度/长度,置信度得分和经过训练的图像类别的概率距离。
我们提供的参数忽略了得分低的那些,并从我们训练的图像类库中挑选出概率最高的特定对象。因此,我们最终很少看到有狗、人、花、汽车等的包围盒。因此,如果我可以过于简化,YOLO 过程在视觉上看起来像下面每个图像网格的闪烁速度。最右边的图片显示了识别出的具有最高盒子置信度得分的图像和标签组合。
The input image is divided into an 7 x 7 grid. Then bounding boxes are predicted and a class is predicted among classification over the most confident ones. Source: J. Redmon and al. (2016)
YOLO V2 is trained with the COCO (Common objects in Context) library that has 100k images of 80 common classes plus it is complemented with a subset of ImageNet. It has 80 image classes. As a reference ImageNet has 14 million images and 22k classes. You can leverage other data sets or leverage Amazon mechanical Turk like new crowd sourcing services for manual labeling work and come up with your own data set!!
所有代码和环境都是 开源 因此任何人都可以克隆和修改作品。我还做了一个小的 Python 代码修改,以便在制作我的测试 YouTube 视频时,能够使用外部网络摄像头进行实时记录(以便不随身携带我的笔记本电脑)。只要懂一点 Python,对理论有一定程度的理解,就可以做任何编辑…
网上的大多数例子通常基于 Linux 或 Mac,尽管我不得不在装有英特尔酷睿 7 的联想 Windows 10 机器上做这个演示。因此,以下所有个人经验和指导都适合在 Windows 环境下使用。
最初的 YOLO 作者使用 C 和 CUDA 在开源库中创建了 DarkNet。我选择使用 Darkflow,它基本上是 DarkNet 到方便的 Tensorflow 版本的翻译。因此,我们将下载并使用暗流版本进行演示。
好了,让我们开始吧…依赖关系
您需要在您的(笔记本电脑)环境中安装 Python 3.5 或 3.6、Tensorflow、numPY、openCV 才能开始。下面是一些在 Windows 上对我有用的指导。
第一步——安装 Windows 的依赖项
对于初学者,你可以安装以下软件,为你将来的 ML 实验准备一个干净的个人计算环境。
- 下载并安装 Anaconda 包 64 位版本,选择 Python 3.6 版本。( 链接 到视频教程)这个自动安装 Python 和很多流行的 data scientist/ML 库( NumPy、Scikit-Learn、Pandas、R、Matplotlib… )、工具( Jupyter Notebook、RStudio )和其他数百个开源包,供你未来的项目使用。当你开始时,它感觉像是最接近 ML 软件包的圣杯的东西…例如,我仍然使用 Anaconda Jupyter 笔记本进行几乎所有的 ML 实验,主要是出于方便。虽然 openCV 库不包括在内,但我们将单独安装它,因为实时计算机视觉任务需要它。(给蟒蛇乡亲们的提示!)
- 安装tensor flowT3和 Keras (可选)。TensorFlow 是最受欢迎的人工智能软件库,由谷歌创建/维护。 Keras 是另一个非常流行的&高级神经网络 API,用 Python 编写,能够在 TensorFlow 之上运行。它的开发重点是支持快速实验。当你在经历了 吴恩达的 这种很低级的素材后,想要“退出”的时候,Keras 感觉就像一块蛋糕!因为它是基于 Python 的高级语言。 别人 为你做了艰苦的工作!
在试图安装所有这些开源软件包时,出现问题是很常见的,尤其是在 Windows 机器上。让一切正常工作并解决所有版本或冲突问题需要一段时间。我的最佳实践是基本上谷歌这类问题,并在网上找到解决方案。像 stackoverflow 这样的网站非常有用,可以节省你的时间。
总的来说,我还发现创建一个单独的新的 conda 虚拟环境有助于缓解 Windows 安装问题。更多关于 这里 。
第二步——安装暗网/YOLA、暗流工具
**DarkNet**:最初,YOLO 算法是由 Joseph Redmon 在 DarkNet 框架中实现的。Darknet 是一个开源的自定义神经网络框架,用 C 和 CUDA 编写。它速度快,易于安装,并支持 CPU 和 GPU 计算。你可以在 GitHub 上找到开源。
Darkflow :是 YOLO 在 TensorFlow 上的一个实现的昵称。由于 Trinh Hoang Trieu,Darknet 模型被转换为 Tensorflow,并且可以安装在 Linux 和 Windows 环境中。让我们开始吧!
#打开 anaconda 提示符并克隆 darkflow github 存储库。(您可能需要安装Git BashWindows,Git 命令才能工作)
git clone [https://github.com/thtrieu/darkflow](https://github.com/thtrieu/darkflow)
#替代方法基本上是进入dark flow GitHub页面,将主库下载到您的本地(即 C:\ users \ user _ name \ dark flow)
#如果您尚未在步骤 1 中创建新的虚拟环境,则创建一个 conda 环境用于 darkflow 安装。
conda create -n your_env_name python=3.6
#使用 anaconda 提示符激活新环境。
activate your_env_name
#你可以用 conda-forge 库安装需要的 OpenCV。 conda-forge 是一个 github 组织,包含 conda 库的存储库。
conda config --add channels conda-forge
conda install opencv
#在适当的位置构建 Cython 扩展。这是一个广泛使用的 Python to C 编译器和包装器,它帮助我们从 Python 中调用 DarkNet C 代码。
python setup.py build_ext --inplace
或者尝试以下替代方法
pip install -e .
如果出现错误,首先尝试将工作目录更改为 darkflow (cd darkflow ),然后重新运行上述命令之一。
酷毙了。上述步骤将有望建立一个本地环境来运行 darkflow 并在图像或视频上执行对象检测任务。
最后,我们需要下载 CFG 和 WEIGHTS 文件。预训练的模型名称是 YOLOv2,其在包含 80 个类别(像汽车、狗、人、飞机等的图像类型)的 COCO 图像数据集上被训练。
权重文件:请从这里下载yolov2.weights
文件。请创建一个暗流/bin 目录来保存这些重量文件。
CFG 文件:在本地 darkflow 文件夹下现有的 darkflow/cfg 目录下创建一个对应型号的yolo.cfg
文本文件。勾选 这里的 为源文件。如果你愿意,你可以用记事本复制粘贴原始的 GitHub 内容。另外,不要忘记看看 Darkflow 的命令行帮助选项,以供将来参考。
python flow --h
PS:我发现这个 博客(Abhijeet Kumar)在我计算出需要的装置时非常有用。
我们都准备好了。
让我们运行暗流 YOLO 命令行来渲染一些视频!
我喜欢使用 Anaconda 命令提示符来执行以下命令。你可以通过搜索“Anaconda 提示符”在 Windows 开始菜单中找到它。在提示窗口中,通过“激活您的环境名称”命令激活您的新 Tensorflow 虚拟环境。然后执行“cd darkflow”命令,将当前工作目录更改为本地 darkflow 存储库。然后,您可以尝试以下命令开始运行 DarkFlow 来处理图像和视频。
- 要处理已有的图像,可以运行以下命令:
python flow --model cfg/yolo.cfg --load bin/yolov2.weights --imgdir sample_img
请注意 darkflow/sample_img 是一个包含样本照片的目录。
2.要处理视频文件,可以将待渲染的视频文件移动到 master darkflow 文件夹下,然后使用以下命令:
python flow --model cfg/yolo.cfg --load bin/yolov2.weights --demo samplename.mp4
提示:如果在末尾添加“— saveVideo”,也可以将处理后的视频保存在主文件夹下。
3.要通过您的笔记本电脑摄像头渲染实时流视频:
python flow --model cfg/yolo.cfg --load bin/yolov2.weights --demo camera
我的基本例子
因为 Medium 不允许直接流式播放,所以我在 YouTube 上上传了两个我用外部网络摄像头录制的示例视频。
使用个人设备还是云 ML 服务?
都是。如果你是初学者,建议你先设置一台个人私人笔记本电脑,里面有需要的 Anaconda、Python 和 Keras/Tensorflow 以及其他所有相关的流行包。在你的 ML 旅程中,这是学习、尝试 MVP 和快速失败/转向的关键。您还可以轻松地设置一个 AWS SageMaker 帐户/环境,它不需要 TerasFlow/Keras 的任何这些单独的安装。我不会详细介绍,但请查看此 链接 了解更多信息。你也可以尝试微软 Azure 或者谷歌云。随着您越来越先进,云将更适合帮助您获得更大的数据空间(即 AWS S3 桶)、计算能力(即更多的 CPU 或 GPU)和快速部署/扩展。因此,它们不是竞争而是互补。
结论
围绕 AI 和 ML 有很多议论。我试图展示,任何人都可以用可用的开源框架和库创建真正的产品,开始时风险自负。
例如,您可以进一步创建和培训自己的课程(图像或图像类型),并根据您的独特需求定制培训。YOLO 和暗流都是开源的,你可以克隆和修改它们。YOLO v3 也已经上市,这一视觉识别领域将继续迅猛发展。我很期待和它一起玩。
我绝不是人工智能或 CNN 的专家,但我希望这篇博客能对人工智能/人工智能爱好者在你未来的 DIY 项目中有所启发。随时欢迎评论和反馈。不要留下来!
学分
所有学分将授予以下人员。我所做的只是利用了他们的优秀作品。
- 关于 YOLO 的原始论文。继 YOLOv2 和 YOLO9000 之后的论文。如果你不喜欢阅读学术论文,你可以在这个链接查看开国元勋们的演讲摘要。
- 然后 DarkNet (Joseph Redmon)创建了 below 库,启发了许多人去实现 YOLO。他做了两次 TED 演讲。第一个主要谈论技术,第二个更多地谈论道德含义。
你只看一次(YOLO)是一个最先进的,实时对象检测系统。
pjreddie.com](https://pjreddie.com/darknet/yolo/)
3.然后 Trieu 先生已经将 Darknet-YOLO v2 翻译成 Tensorflow 框架。
将 darknet 转换为 tensorflow。加载训练过的重量,使用 tensorflow 进行重新训练/微调,将常量图形定义导出到…
github.com](https://github.com/thtrieu/darkflow)
延伸阅读和观看…
更多关于 YOLO 的信息,请点击 此处 , 此处 或 此处 获取更多见解和灵感。 马克杰伊 也有一个很棒的 8 部分 Youtube 系列,展示如何定制暗流。你可以在演职员表部分查看创始人的 YOLO 主页。(快捷键: 暗网 YOLO , 暗流 )。
更新
- 错误处理:如果你收到一个类似“ … AssertionError: labels.txt 和 cfg/yolov2.cfg 表示不一致的类编号…“
然后检查这个解决方案。您只能使用保留的 CFG 字后面的(只要您的命令提示符指示新的“bin”文件夹下下载的权重文件名,权重名称就可以了)。首先,你可以在这里 从 下载 yolov2,但将其重命名为 yolo.cfg ,因为它是由代码识别的。您还可以选择修改开放源代码。 - 如果你想使用外部网络摄像头,这里有一些调整开源代码的简单技巧。上帝保佑开源软件!
如何使用外部网络摄像头进行实时流媒体播放:
你必须对你克隆的开源暗流代码做一个小小的修改&下载。首先,你需要一个网络摄像头连接到 OpenCV 可以连接的计算机上,否则它将无法工作。如果您连接了多个网络摄像头,并且想要选择使用哪一个,您可以传递“file = 1”来选择(OpenCV 默认使用现有的网络摄像头作为 0)。请打开以下文件,并使用 Jupyter 或任何其他 Python 编辑器进行更改:http://localhost:8888/edit/dark flow/dark flow/net/help . py
或者你可以在下面的链接复制我的分叉代码。
将 darknet 转换为 tensorflow。加载训练过的重量,使用 tensorflow 进行重新训练/微调,将常量图形定义导出到…
github.com](https://github.com/Sailor74/darkflow/blob/Sailor74-patch-1/darkflow/net/help.py)
然后,您可以轻松地使用 Anaconda 提示符命令窗口通过外部网络摄像头进行流式传输。
# run darkflow with external webcam on windows
python flow --model cfg/yolo.cfg --load bin/yolov2.weights --demo webcamera
您可以使用 Anaconda prompt 命令通过网络摄像头进行流媒体播放,并将视频保存在 darkflow 根文件夹下:
# run darkflow with ext webcam and save to local folder
python flow --model cfg/yolo.cfg --load bin/yolov2.weights --demo webcamera --saveVideo
剧终
Happy “deep learning” in 2019!!******
记忆增强神经网络构建实践(第一部分)
记忆增强神经网络(MANN),可用于一次性学习,在这篇文章中,我将向您展示如何构建记忆增强神经网络。
在我们开始建立我们的曼恩之前,我想说明它的前身,神经图灵机(NTM)。在这一部分,我将向您展示 ntm 如何利用外部存储器来存储和检索信息。所以,让我们跳到 NTM。
神经图灵机架构和概念
神经图灵机是一种算法,具有从存储器中存储和检索信息的能力。NTM 的亮点是用外部存储器来增强神经网络,用于存储和检索信息,而通常一些神经网络使用隐藏状态作为存储器。这是 NTM 的建筑:
Fig 01 —The architecture of NTM
如您所见,通常 NTM 有三个核心组件:
- 控制器
- 记忆
- 读写头
控制器,基本上是一个前馈神经网络或递归神经网络,读取和写入存储器。存储器部分,你可以称之为存储体或存储矩阵,这里我们有一个二维矩阵,由 N 行 M 列的存储单元组成。控制器从外部环境接收输入,并通过与存储体或存储矩阵交互来发出响应。通常,读磁头和写磁头是包含存储器地址的指针,它必须从存储器中读取和写入。
在 NTM,我们使用特殊的读写操作来决定关注内存中的哪个位置。
神经图灵机读取操作
既然我们的记忆库或记忆矩阵中有很多记忆块,那么我们需要选择哪一个来从内存中读取呢?这是由权重向量决定的。可以由注意机制获取的权重向量指定了在存储器中哪个区域比其他区域更重要。首先,我们需要规范化权重向量,这意味着它的值范围从 0 到 1,其和等于 1。好了,让我们在这里做一些数学,不要担心下面这些长公式,我们会涵盖它。
Fig 02 — — Neural Turing Machine Read and Write operations math formula
假设归一化权重向量为 w_t,其中下标 t 表示时间,w_t(i)表示权重向量中索引为 I 且时间为 t 的元素。如公式 R1 所示,假设我们的记忆库或记忆矩阵包含 N 行和 M 列,我们使用 Mt 表示时间为 t 的记忆矩阵
Fig 03 — — M_t(i), Memory Matrix M_t given time t
然后我们可以以线性方式组合存储器矩阵 Mt、权重向量 Wt、读取向量 Rt。这可以表示为公式 R2(图 02)
Fig 04 — — r_t, read vector given time t
神经图灵机写操作
擦除和添加操作包含在 NTM 写入操作中。可以应用擦除操作来移除存储器中不需要的信息。为了擦除存储矩阵中特定单元的值,我们引入一个擦除向量 e_t,它的长度与权向量 w_t 相同,擦除向量包含 0 和 1 的值。
因此,为了擦除值并获得更新的内存矩阵,我们将(1- w_t x e_t)乘以上一步 M_{t-1}^(i 中的内存矩阵,如图 2 中的公式 E1 所示。
Fig 05 — — Erase operation
对于 NTM 写操作中的加法操作,我们使用权重向量 w_t(i)乘以加法向量 a_t,加法向量 a _ t 具有要添加到存储器的值,然后将它们添加到存储器矩阵,即图 02 中的公式 A1。
Fig 06 — — Add operation
神经图灵机中的寻址机制
我们可以使用注意机制和不同的寻址方案来计算权重向量。这里我们有两种类型的寻址机制来从存储器中访问信息:
- 基于内容的寻址
- 基于位置的寻址
对于基于内容的寻址,根据相似性从存储器中选择值。假设控制器返回一个关键向量 k_t,相似性是通过将该关键向量与存储矩阵 M_t 中的每一行进行比较而获得的。该相似性可以通过下图中的数学公式 CB1 来测量。
Fig 07 — — Addressing Mechanisms Math in Neural Turing Machine
接下来,我们引入一个参数β,它被称为关键强度,用于确定权重向量应该有多集中。基于β的值,我们可以根据关键强度的值将注意力调整到特定位置。也就是说,当β值较低时,我们平等地关注所有位置,当β值较高时,我们关注特定位置。因此,我们的权重向量变成了图 07 的公式 CB2。
我们可以对权重应用 softmax,而不是直接使用这个数学定义。也就是图 07 中的公式 CB3。
对于基于位置的寻址,我们仍然有三个步骤:
- 插入文字
- 卷积移位
- 磨刀
插值用于决定我们是否应该使用在先前时间步长 w_{t-1}获得的权重或者使用通过基于内容的寻址 w_t^c.获得的权重来解决该问题,我们引入新的参数 g_t 来确定我们应该使用哪些权重。g_t 的值可以是 0,也可以是 1。因此,我们的权重向量可以通过图 07 中的公式 CS1 来计算。
正如你所看到的,当 g_t 的值为 0 时,我们的权重向量是我们从上一个时间步获得的。而如果 g_t 的值是 1,那么我们的权重向量就是我们通过基于内容的寻址获得的权重向量。
然后,我们继续卷积移位,它用于移动头部位置。每个磁头发出一个参数,比如说移位权重 s_t,来给我们一个允许整数移位的分布。
假设我们的权重向量中有三个元素,如图 07 中的公式 CS2,我们的移位权重向量中有三个元素,假设 s_t = [-1,0,1]。移位-1 意味着我们将把 w_t^g 中的元素从左向右移位。移位 0 表示将元素保持在相同的位置,移位+1 表示将元素从右向左移位。那就是下图:
Fig 08 — — Shift Diagram
现在假设我们有移位权重 s_t = [1,0,0],我们将执行左移,因为在其他位置移位值为 0。
Fig 09 — — left shift
类似地,当 s_t = [0,0,1]时,我们执行如下右移
Fig 10 — — Right shift
当在权重矩阵中执行卷积移位时,假设我们有 0 到 N-1 个存储单元,卷积移位以图 7 的公式 CS3 的方式进行。
对于最后一步锐化,由于偏移,聚焦在单个位置的权重将分散到其他位置,为了减轻这种影响,执行了锐化。这里我们引入一个新的参数 gamma_t,应该大于等于 1 才能进行锐化。因此,权重向量可以表示为图 07 中的公式 S1。
广泛用于一次性学习任务的记忆增强神经网络(MANN)实际上是神经图灵机的变体。为了让 NTM 在一次性学习任务中表现得更好,曼恩不能使用基于位置的寻址。MANN 还使用了一种称为最近最少使用访问的新寻址模式。该场景背后的思想是最近最少使用的存储器位置由读取操作确定,并且读取操作由基于内容的寻址来执行。因此,我们基本上执行基于内容的寻址来读取和写入最近最少使用的位置。
记忆增强神经网络上的读操作
MANN 使用两个不同权重向量来执行读取和写入操作。MANN 中的读取操作与 NTM 相同。基于内容的相似性可以通过余弦相似性来测量,余弦相似性仍然可以表示为下面的第一个公式。权重向量可以表示为下面的第二个公式。与 NTM 不同,曼恩不使用密钥强度,所以 softmax 版本的加权向量成为下面的第三个公式。
Fig 11 — — Math in MANN read operations
以线性方式与权重向量和记忆矩阵结合的读取向量可以表示为上述第四个公式。
记忆增强神经网络上的写操作
为了找到最近最少使用的内存位置,我们可以计算一个新的向量,称为使用权重向量,比如 w_t^u,它将在每次读写步骤后更新。因此,使用加权向量成为读取加权向量和写入加权向量的总和,如图 12 中的公式 F1 所示。
Fig 12 — — Math in MANN Write Operations
然后,我们可以通过添加衰减的先前使用权重向量来更新我们的使用权重向量,它变成图 12 中的公式 F2,假设衰减参数γ用于确定先前使用权重必须如何衰减。
为了计算最近最少使用的位置,我们引入另一个权重向量,比如最少使用的权重向量 w_t^{lu}.从使用权重向量计算最少使用的权重向量非常简单。只需将使用权重向量中最低值的索引设置为 1,其余值设置为 0,因为使用权重向量中的最低值意味着它最近最少被使用。
然后,我们使用 sigmoid 门计算写入权重向量,该门用于计算之前的读取权重向量和之前最少使用的权重向量的凸组合。写权重向量变成图 12 中的公式 F3。在计算写入权重向量之后,我们最终更新存储器矩阵,即图 12 中的公式 F4。
这篇文章主要是关于记忆增强神经网络的概念和数学,你可以在这里找到代码实现部分:
在这篇文章中,我将向你展示一些构建记忆增强神经网络(简称 MANN)的代码。可以参考一下…
medium.com](https://medium.com/@xavier_lr/hands-on-memory-augmented-neural-networks-build-part-two-896b1ef50726)
实践:预测客户流失
长话短说——在这篇文章中,我们想亲自动手:建立一个模型,识别我们亲爱的客户在不久的将来离开我们的意图。我们通过在 python 的帮助下实现一个预测模型来做到这一点。不要期待一个完美的模型,而是期待一些你今天可以在自己的公司/项目中使用的东西!
在我们开始之前,让我们简要回顾一下什么是客户流失:客户流失量化了取消订阅或取消服务合同的客户数量。对于任何企业来说,顾客拒绝接受你的服务或产品都不是一件有趣的事情。一旦失去,赢回他们是非常昂贵的,甚至没有想到如果不满意,他们不会做最好的口碑营销。在我之前的一篇文章中,了解所有关于客户流失的基础知识。现在让我们开始吧!
我们将如何预测客户流失?
预测未来客户流失的基础层是来自过去的数据。我们关注已经流失的客户的数据(反应)以及他们在流失发生前的特征/行为(预测)。通过拟合一个将预测因素与响应联系起来的统计模型,我们将尝试预测现有客户的响应。这种方法属于监督学习的范畴,以防万一你需要一个更嗡嗡作响的表达。在实践中,我们执行以下步骤来进行这些精确的预测:
High Level Process
- 用例/业务用例
第一步实际上是理解具有期望结果的业务或用例。只有理解了最终目标,我们才能建立一个实际有用的模型。在我们的案例中,我们的目标是通过预先识别潜在的客户流失候选人来减少客户流失,并采取积极的行动来留住他们。 - 数据收集和清理
通过了解上下文,可以识别正确的数据源、清理数据集并为功能选择或工程设计做准备。这听起来很简单,但这可能是最难的部分。预测模型的好坏取决于数据源的好坏。尤其是初创公司或小公司往往很难找到足够的数据来充分训练模型。 - 特征选择和工程
第三步,我们决定在我们的模型中包含哪些特征,并准备好净化后的数据,用于机器学习算法来预测客户流失。 - 建模
有了准备好的数据,我们就可以开始构建模型了。但是为了做出好的预测,我们首先需要找到正确的模型(选择),其次需要评估算法是否真的有效。虽然这通常需要几次迭代,但我们会保持简单,一旦结果符合我们的需要就停止。 - 最后但同样重要的是,我们必须评估和解释结果。这意味着什么?我们能从结果中得出什么行动?因为预测客户流失只是其中的一半,许多人忘记了仅仅通过预测,他们仍然可以离开。在我们的案例中,我们实际上想让他们停止离开。
我们使用的工具
Tools to predict churn in python
为了预测客户是否会流失,我们正在使用 Python 和它令人惊叹的开源库。首先,我们使用 Jupyter Notebook,这是一个用于实时编码的开源应用程序,它允许我们用代码讲述一个故事。此外,我们导入了 Pandas ,这将我们的数据放在一个易于使用的结构中,用于数据分析和数据转换。为了让数据探索更容易理解,我们巧妙地使用来可视化我们的一些见解。最后,通过 scikit-learn 我们将分割数据集并训练我们的预测模型。
数据集
公司拥有的最有价值的资产之一是数据。由于数据很少公开共享,我们采用了一个可用的数据集,您可以在 IBMs 网站以及其他页面上找到,如 Kaggle :电信客户流失数据集。原始数据集包含 7000 多个条目。所有条目都有几个特征,当然还有一列说明客户是否搅拌过。
为了更好地理解数据,我们首先将它加载到 pandas 中,并在一些非常基本的命令的帮助下探索它。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.filterwarnings("ignore")from pylab import rcParams%matplotlib inline# Loading the CSV with pandas
data = pd.read_csv('..Customer Churn/Telco-Customer-Churn.csv')
探索和特征选择
本节非常简短,因为您可以在更好的教程中了解更多关于一般数据探索的内容。然而,为了获得初步的见解,并了解您可以用数据讲述什么故事,数据探索无疑是有意义的。通过使用 python 函数 data.head(5)和“data.shape ”,我们得到了数据集的总体概述。
Glimpse of the dataset — overall 7043 rows with 21 columns
具体来说,我们来看看目标特性,即实际的“客户流失”。因此,我们相应地绘制它,并看到客户流失总量的 26.5%。了解这一点很重要,因为在我们的培训数据中,流失客户与非流失客户的比例是相同的。
# Data to plot
sizes = data['Churn'].value_counts(sort = True)
colors = ["grey","purple"]
rcParams['figure.figsize'] = 5,5# Plot
plt.pie(sizes, explode=explode, labels=labels, colors=colors,
autopct='%1.1f%%', shadow=True, startangle=270,)plt.title('Percentage of Churn in Dataset')
plt.show()
数据准备和特征工程
要知道,我们为机器学习模型准备的数据越好,我们的预测就越好。我们可以有最先进的算法,但如果我们的训练数据很烂,我们的结果也会很烂。由于这个原因,数据科学家花费大量时间准备数据。由于数据预处理需要很多时间,但这不是本文的重点,我们将通过一些示例性的转换来完成。
- 丢弃不相关的数据
可能会包含一些不需要的数据来改进我们的结果。最好是通过逻辑思维或创建关联矩阵来识别。例如,在这个数据集中,我们有 customerID。因为它不影响我们的预测结果,所以我们用 pandas 的“drop()”函数删除该列。
data.drop(['customerID'], axis=1, inplace=True)
2.缺失值
此外,处理缺失数据也很重要。这些值可以用“.”来标识。isnull()"函数在熊猫中的应用。在识别空值之后,如果用平均值、中间值或众数来填充缺失值是有意义的,或者如果有足够的训练数据,则完全丢弃该条目,这取决于每种情况。在我们正在处理的数据集中,有一个非常不寻常的情况——没有空值。今天我们很幸运,但重要的是要知道通常我们必须处理这个问题。
3.从对象
转换数字特征从我们的数据探索(在本例中为“data.dtypes()”)中,我们可以看到 MonthlyCharges 和 TotalCharges 列是数字,但实际上是对象格式。为什么这样不好?我们的机器学习模型只能处理实际的数字数据。因此,通过“to_numeric”函数,我们可以更改格式,并为我们的机器学习模型准备数据。
data['TotalCharges'] = pd.to_numeric(data['TotalCharges'])
4.分类数据转换成数值数据
因为我们不能用字符串值计算任何东西,我们必须将这些值转换成数值。电信数据集中的一个简单例子是性别。通过使用 Pandas 函数“get_dummies()”,两列将用“gender_Female”和“gender_Male”替换性别列。
除此之外,我们可以对数据集中的所有分类变量使用“get_dummies()”函数。这是一个强大的功能,但是有这么多额外的列可能会令人不安。
5.分割数据集
首先我们的模型需要被训练,其次我们的模型需要被测试。因此,最好有两个不同的数据集。至于现在我们只有一个,相应拆分数据是很常见的。x 是自变量的数据,Y 是因变量的数据。测试大小变量决定了数据的分割比例。在 80 的培训/ 20 的测试比例中,这样做是很常见的。
data["Churn"] = data["Churn"].astype(int)Y = data["Churn"].values
X = data.drop(labels = ["Churn"],axis = 1)*# Create Train & Test Data*
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=101)
逻辑回归和模型测试
逻辑回归是最常用的机器学习算法之一,主要用于因变量(此处为流失 1 或流失 0)为分类变量的情况。相反,自变量可以是分类变量,也可以是数值变量。请注意,当然详细理解模型背后的理论是有意义的,但在这种情况下,我们的目标是利用预测,我们不会在本文中讨论这个。
第一步。让我们从 sci-kit learn
步骤 2 导入我们想要使用的模型。我们制作一个模型的实例
步骤 3。在训练数据集上训练模型并存储从数据中学习到的信息
from sklearn.linear_model import LogisticRegression
model = LogisticRegression()
result = model.fit(X_train, y_train)
有了训练好的模型,我们现在可以预测客户是否对我们的测试数据集产生了兴趣。结果保存在“prediction_test”中,然后测量并打印准确度分数。
from sklearn import metrics
prediction_test = model.predict(X_test)# Print the prediction accuracy
print (metrics.accuracy_score(y_test, prediction_test))
分数显示,在 80%的情况下,我们的模型预测了二元分类问题的正确结果。这在第一次运行中被认为是非常好的,特别是当我们查看每个变量的影响以及这是否有意义时。因此,为了减少流失并及时采取正确的预防措施,我们想知道哪些独立变量对我们的预测结果影响最大。因此,我们将模型中的系数设置为零,并查看每个变量的权重。
# To get the weights of all the variables
weights = pd.Series(model.coef_[0],
index=X.columns.values)
weights.sort_values(ascending = False)
可以观察到,一些变量与我们预测的变量成正相关,而一些变量则成负相关。正值对我们预测的变量有积极的影响。一个很好的例子是“逐月合同”:与客户流失的正相关意味着拥有这种类型的合同也增加了客户流失的可能性。另一方面,“两年合同”与预测变量高度负相关,这意味着这种类型合同的客户不太可能流失。但是我们也可以看到,有些变量在第一点没有意义。就对客户流失的积极影响而言,“光纤”居于首位。虽然我们预计这会让客户留下来,因为它为他提供了快速的互联网,但我们的模型却不这么认为。在这种情况下,深入挖掘并获得数据的一些背景信息是很重要的。
是的,我们做到了——下一步是什么?
Hug your customer and make him stay 😃
一——和你的团队谈谈。
我们不仅发现了哪些客户可能会流失,还发现了哪些特征对客户的流失影响最大。因此,强烈建议与您的客户成功团队分享这些见解,并调整他们的关注点。只有当团队知道重点放在哪里时,他们才能引导客户关注那些能让他/她停留更久的功能。开诚布公地说出来,讨论各种选择,并确保你了解整个背景。在许多情况下,客户成功或支持团队能够提供额外的定性见解,这些见解可能会强调您的发现或完全讲述与您的发现不同的故事。
二——与可能流失的客户接触。
是的,有一个故事说你不应该惹是非。但在潜在客户流失的情况下,这是扯淡。保持安静并希望你的客户不会离开,迟早会 100%地陷入客户流失。相反,不要害怕,走出去和你的客户接触。有很多选择,但最好的选择是最明显的:和他们谈谈。
查看他们的个人资料,确定特征,分析过去与你的产品的互动,然后简单地与他们交谈。寻求反馈,交流可能感兴趣的最新进展,或者向他们介绍新产品功能。接近可能会流失的客户,但要确保你提出了可能符合他们个人需求的相关内容。这将创造一种被理解的感觉,并将他们与你和你的企业捆绑在一起。
与此相关的文章:
动手操作:使用 Docker 设置您的数据环境
我写的大部分内容都让我忙于自己的创业。
期待听到你的经历:)
Python 数据可视化实践 Seaborn 计数图
A Seaborn Count Plot
在本教程中,我们将一步一步地展示如何使用 Python Seaborn 库 来创建计数图。基本上,Seaborn 计数图是一个图形显示,使用条形图显示每个分类数据的出现次数或频率。
数据来源
公共 Airbnb 数据集“ *AB_NYC_2019.csv”,*将用作样本数据来创建 Seaborn 计数图。数据集可以从 Kaggle 获取(https://www . ka ggle . com/dgomonov/new-York-city-Airbnb-open-data)。
先决条件 Python 库
- 熊猫(https://pandas.pydata.org/)
- 马特普利布(https://matplotlib.org/)
- 西博恩(https://seaborn.pydata.org/)
- 朱庇特笔记本/朱庇特实验室(https://jupyter.org/)
每个库的安装和设置细节都在它们的官方网站上给出。
它是如何工作的
步骤 0:创建一个 Jupyter 笔记本文档。
我们将编写 Python 脚本并在 Jupyter 笔记本环境中运行它。
第一步:导入库并读取数据。
一旦库准备就绪,我们就可以继续读取并可视化来自“ AB_NYC_2019.csv ”的前五行列表数据。
First five rows of data from “AB_NYC_2019.csv”
步骤 2:为单个分类变量" room_type " 创建一个简单的计数图
当我们观察数据集时,在“ room_type ”列中显示的基本上有三种类型的房间(“私人房间”、“整个家/apt”、“共享房间”)。直观显示每种房间类型的观察计数的一种简单方法是创建计数图。我们可以通过添加几行代码(第 13–16 行)轻松创建计数图,如下所示。
Create a count plot for a single categorical variable (room_type)
- 第 14 行——为我们的情节设置一个 Seaborn 主题“黑暗网格”。
- 第 15 行—将分类变量“ room_type ”(目标列)分配给参数“ x ”。参数“数据分配给绘图数据集 airbnb 。
快速生成一个简单的计数图。
A count plot for single categorical variables
**步骤 3:为两个分类变量“房间类型和“邻居组”**创建计数图
比方说,如果我们希望了解不同邻居组中每种房间类型的一般可用性,我们可以基于两个分类变量创建计数图,“房间类型和“邻居组”。
- 第 15 行—在 seaborn.countplot()中再添加一个参数“色调,并为其分配第二个分类变量“neighborhood _ group”。
A count plot for two categorical variables
从上面的计数图中,很明显“整个家庭/公寓”的房间类型在曼哈顿非常常见。该图还揭示了在数据集中的所有邻域组中“共享房间”的可用性非常有限。因此,我们得到合住房间的机会相对较低。
****步骤 4:为三个分类变量“房间类型”、“邻居组”和“价格组”创建计数图
我们也经常会遇到这样的情况:我们的旅行预算有限,希望计划一次住宿费用较低的旅行。一张显示不同地点中低价住宿信息的图表可能对我们的旅行计划有帮助。
为此,我们可以在现有的 Airbnb 数据集中添加一个新列“price _ group”。
Add new column “price_group” into table
- 第 9 行到第 15 行—创建一个函数 groupPrice() 将房间价格分为三个不同的组:低成本(低于 100 美元)、中等成本(100 美元到 200 美元)和高成本(高于 200 美元)。
- 第 17 行—将 groupPrice() 函数应用于数据集的现有 price 列。这将创建一个新列,其中包含三个不同的分类值(“低成本”、“中成本”和“高成本”)。
- 第 18 行—在数据集中的“价格”列旁边插入新列。
- 第 19 行—显示前五行记录。您将看到新列“价格 _ 组”被添加到表格中“价格”旁边的列中。
Added new column in the table
接下来,我们使用 catplot() 合并三个计数图。
- 第 22 行—组合三组计数图,这些计数图由第三个分类变量“ price_group ”分组。这是通过在 Seaborn 函数 catplot()中将“ price_group ”赋值给参数“ col ”来实现的。
Count plots based on three categorical variables
该图显示,布鲁克林可能是一个寻求低成本私人房间的个人旅行者的好选择。曼哈顿或布鲁克林可能是家庭/团体旅行的理想目的地,因为这相对更容易获得一个合理的中等价格范围的整个家庭/公寓单元,可供一群旅行者分享。
结论
当我们浏览上面的教程时,我们会发现使用 Seaborn 只需几行代码就可以生成一个吸引人的计数图,这并不困难。计数图可以揭示许多从原始数据集中无法直接发现的事实。
我希望你喜欢阅读这篇文章。非常欢迎您的评论或任何询问。
实践:使用 Docker 设置您的数据科学环境
每当你开始一个新的数据项目或有一个处理数据的好主意时,最初的概念验证可能是必要的。当然,您不希望,也可能没有时间花几个小时来建立一个全新的数据环境,甚至连数据本身都不看一眼。在下面的文章中,您将了解 Docker 如何帮助您建立一个可复制的数据环境,而不必一次又一次地浪费您的时间。
Docker 是什么,为什么要试一试?
Docker 是一种最简单、最灵活的方法,可以在特定的环境中创建、部署和运行您想要的应用程序,也就是所谓的容器。你当然会问自己什么是容器?
**非技术性的解释:**就像上图一样,想象一下,在我们的例子中,你的本地机器是一个你已经在生产东西的孤岛。为了改善这一点,你需要额外的工具,这些工具(就像 Docker 标志一样)装在小容器里。一旦您设置并运行它们,它们就可以运行了。
**技术解释:**容器是软件的一个标准单元,它封装了代码及其所有依赖关系,因此应用程序可以快速可靠地从一个计算环境运行到另一个计算环境。Docker 容器映像是一个轻量级的、独立的、可执行的软件包,包括运行应用程序所需的一切:代码、运行时、系统工具、系统库和设置。其他重要术语:
- 图片:只是你的容器的快照。
- Dockerfile:这是一个 yaml 文件,用来建立你的形象。在本课程结束时,您将拥有一个 yaml 文件模板,并将其用于您自己的容器规范。
- Docker hub: 在这里你可以推拉 Docker 图片,并根据自己的需要使用。基本上 GitHub 只是针对 Docker 的。
为什么要用 Docker?
让我向你概述一下我喜欢使用 Docker 的主要原因:
- 对于作为数据科学家或数据分析师的您来说,docker 意味着您可以专注于探索、转换和建模数据,而无需首先考虑数据环境所运行的系统。通过使用 Docker 容器中数以千计的应用程序中的一个,您不必担心单独安装和连接它们。Docker 允许您在几秒钟内部署您选择的工作环境——只要您需要。
- 让我们假设您不是项目中唯一的工作人员,但是您的团队成员也需要接触代码。现在唯一的选择是每个队友在他们自己的环境中运行代码,使用不同的架构、不同的库和不同版本的应用程序。docker 选项是每个成员都可以访问同一个容器映像,用 docker 启动映像并准备好。Docker 为团队中的每个人提供了可重复的数据环境,因此您可以立即开始协作。
Docker 肯定还有其他一些好处,尤其是如果您正在使用企业版的话。这绝对值得探索,不仅对作为数据科学家的你有好处。
安装和运行 Docker
您可以安装 Docker desktop,这是您需要立即开始的东西:访问 Docker Hub 这里,为您的 Mac 或 Windows 选择 Docker 版本并安装它。一旦在本地 machina 上启动 Docker,你就可以在顶部导航栏上看到这条可爱的小鲸鱼——干得好。
通过点击 Docker 的标志,你可以看到 Docker 是否正在运行。另一种方法是打开命令行并输入“docker info ”,这样你就可以看到正在运行的程序。以下是一些基本的 Docker 命令:
**docker login #Log in to Docker registry docker run <image> #create a new container and start it docker start <image> #start an existing container**
**docker stop <name|id> #stop a running container**
**docker ps [-a include stopped containers] #show all containers**
你可以从一个简单的例子开始,用 Jupyter 笔记本试试看。你所要做的就是在 Docker Hub 中寻找一个图像,打开你的终端,运行 Docker。在下面的例子中,您可以找到在 localhost:8888 上运行的 Jupyter 很容易!
docker run -p 8888:8888 jupyter/scipy-notebook:2c80cf3537ca
虽然我们现在可以在我们的容器中摆弄我们的应用程序,但它并不是高级数据科学家正在寻找的完整的数据环境。您可能希望使用更高级的工具,比如 Nifi 用于数据接收和处理,Kafka 用于数据流,SQL 或非 SQL 数据库用于存储中间的一些表。我们还能用 Docker 做所有这些吗?答案是:当然可以——Docker compose up 是为您管理这一切的。
Docker Compose:将所有内容整合在一起
为了设置您想要的数据环境,您可能希望在我们的本地机器上运行几个容器。这就是我们使用 Docker Compose 的原因。Compose 是一个定义和运行多容器 Docker 应用程序的工具。虽然单独连接每个容器可能很耗时,但 docker compose 允许多个容器的集合通过它们自己的网络以非常直接的方式进行交互。使用 compose,首先使用一个 yaml 文件来配置应用程序的服务,然后使用一个命令(docker compose up)就可以创建并启动先前定义的所有服务。 *
在下文中,您可以找到开始的主要步骤:
- 用一个
Dockerfile
来定义你的应用环境,以便于复制 - 在
docker-compose.yml
中指定组成您的数据环境的所有服务 - 在你保存 yaml 文件的文件夹中打开你的终端并运行
docker-compose up
一个docker-compose.yml
可能看起来像你在下面看到的一样。尽管您肯定可以使用以下内容作为模板,但您肯定应该为自己配置一次:
version: '3'
services:
zookeeper:
hostname: zookeeper
container_name: zookeeper_dataenv
image: 'bitnami/zookeeper:latest'
environment:
- ALLOW_ANONYMOUS_LOGIN=yes
nifi:
image: mkobit/nifi
container_name: nifi_dataenv
ports:
- 8080:8080
- 8081:8081
environment:
- NIFI_WEB_HTTP_PORT=8080
- NIFI_ZK_CONNECT_STRING=zookeeper:2181
minimal-jupyter-notebook:
image: jupyter/minimal-notebook:latest
ports:
- 8888:8888
mongodb:
image: mongo:latest
container_name: mongodb_dataenv
environment:
- MONGO_DATA_DIR=/data/db
- MONGO_LOG_DIR=/dev/null
ports:
- 27017:27017
grafana:
image: bitnami/grafana:latest
container_name: grafana_dataenv
ports:
- 3000:3000
db:
image: 'postgres:9.6.3-alpine'
container_name: psql_dataenv
ports:
- 5432:5432
environment:
POSTGRES_DB: psql_data_environment
POSTGRES_USER: psql_user
POSTGRES_PASSWORD: psql
PGDATA: /opt/psql_data
restart: "no"
就是这样!您刚刚学习了如何在几秒钟内随时随地部署您自己的数据环境的基础知识,这意味着在设置方面浪费更少的时间,而有更多的时间来提高工作效率。
您可能也喜欢阅读的文章:
请注意,还有很多其他的容器软件选项。我只是喜欢和 Docker 一起工作,并想和你分享我的经验
用于编写 Docker 的资源:
Compose 是一个定义和运行多容器 Docker 应用程序的工具。使用合成,您可以使用合成文件…
github.com](https://github.com/docker/compose)
TensorFlow 实践教程:使用 ImageNet 数据集从头开始训练 ResNet-50
在这篇博客中,我们给出了如何在 TensorFlow 中训练 ResNet 模型的快速指南。虽然官方的 TensorFlow 文档确实有您需要的基本信息,但它可能不会马上完全有意义,并且可能有点难以筛选。
我们在这里展示了一个循序渐进的培训过程,同时记录了最佳实践、技巧、诀窍,甚至是我们在开展培训过程中遇到并最终克服的一些挑战。
我们涵盖您需要做的一切,从启动 TensorFlow、下载和准备 ImageNet,一直到记录和报告培训。所有的实验和训练都是在 Exxact Valence 工作站上完成的,使用了 2 个英伟达 RTX 2080 Ti GPU。
有什么意义?我就不能用迁移学习吗?
是的,但是本教程是使用大型数据集(ImageNet)从头开始训练大型神经网络的好练习。虽然迁移学习是一件美妙的事情,并且您可以下载 ResNet-50 的预培训版本,但以下是您可能想要进行此培训练习的一些令人信服的原因:
- 如果你完成了本教程,你已经有效地训练了一个神经网络,可以作为一个通用的图像分类器。
- 有了合适的流程,您可以根据自己的数据训练网络。例如,假设您想要训练一个可以对医学图像进行分类的网络。如果图像经过适当的预处理,根据您的数据训练的网络应该能够对这些图像进行分类。
- 如果您有许多独特的训练数据,从头开始训练网络应该比一般的预训练网络具有更高的准确性。
- 您可以专门针对您的数据调整训练参数。
- 在预训练的模型上,检查点是脆弱的,并且不能保证与未来版本的代码一起工作。
虽然迁移学习是一种强大的知识共享技术,但知道如何从头开始训练仍然是深度学习工程师的必备技能。所以现在,让我们开始吧。
步骤 1)运行 TensorFlow Docker 容器。
首先,您需要启动 TensorFlow 环境。我们喜欢和 Docker 一起工作,因为它给了我们极大的灵活性和可复制的环境。打开一个终端窗口,让我们开始吧!
注意:一定要指定你的-v 标签,以便在容器内创建一个交互卷。
nvidia-docker run -it -v /data:/datasets tensorflow/tensorflow:nightly-gpu bash
或如果您计划在 docker 容器中启动 Tensorboard,请确保指定 -p 6006:6006 并使用以下命令。
nvidia-docker run -it -v /data:/datasets -p 6006:6006 tensorflow/tensorflow:nightly-gpu bash
步骤 2)下载并预处理 ImageNet 数据集。
我们决定包括这一步,因为它似乎会引起一点混乱。注意:当你做这一步时,你要确保你有 300+ GB 的存储空间(正如我们发现的),因为下载&预处理步骤需要这个!
2.1)对于第一个子步骤,如果您的环境中没有 git,您需要安装它。
apt-get install git
2.2)其次,您必须将 TPU 回购克隆到您的环境中(不,我们没有使用谷歌的 TPU,但是这里包含了基本的预处理脚本!)
git clone [https://github.com/tensorflow/tpu.git](https://github.com/tensorflow/tpu.git)
2.3)第三,您需要安装 GCS 依赖项(即使您没有使用 GCS,您仍然需要运行它!)
pip install gcloud google-cloud-storage
2.4)最后,您将需要运行 imagenet_to_gcs.py 脚本,该脚本从 Image-Net.org 下载文件,并将它们处理成 TFRecords,但不将它们上传到 gcs(因此有了**‘nogcs _ upload’**标志)。同样 ‘local_scratch_dir=’ 应该指向您想要保存数据集的位置。
python imagenet_to_gcs.py --local_scratch_dir=/data/imagenet --nogcs_upload
注意:ImageNet 非常大,根据您的连接情况,可能需要几个小时(可能是一夜)才能下载完整的数据集!
步骤 3)下载 TensorFlow 模型。
这一步是显而易见的,如果你没有模型,克隆回购使用:
git clone [https://github.com/tensorflow/models.git](https://github.com/tensorflow/models.git)
步骤 4)导出 PYTHONPATH。
将 PYTONPATH 导出到计算机上 models 文件夹所在的文件夹。下面的命令是模型在我的机器上的位置!确保用模型文件夹的数据路径替换 ‘/datasets/models’ 语法!
export PYTHONPATH="$PYTHONPATH:/datasets/models"
第 5 步)安装依赖项(您差不多准备好了!)
导航到 models 文件夹(如果您还不在那里)并运行以下命令
pip install --user -r official/requirements.txt
或如果你使用 Python3
pip3 install --user -r official/requirements.txt
重要提示:你已经准备好训练了!根据我们的经验,为了让训练脚本正确运行,您需要从验证文件夹中复制(或移动)数据,并将其移动到训练文件夹中!!!
步骤 6)设置训练参数,训练 ResNet,坐好,放松。
运行训练脚本 pythonimagenet _ main . py,设置训练参数。下面是我用来训练 ResNet-50 的,120 个训练历元对这个练习来说太多了,但我们只是想推动我们的 GPU。根据您的计算能力,在完整数据集上训练可能需要几天时间!
python imagenet_main.py --data_dir=/data/imagenet/train --num_gpus= 2 --batch_size=64 --resnet_size= 50 --model_dir=/data/imagenet/trained_model/Resnet50_bs64 --train_epochs=120
关于训练参数的注意事项:注意有许多不同的选项可以指定,包括:
上面提到的只是模型训练可用的一些选项。请参见resnet _ run _ loop . py查看选项的完整列表(您必须仔细阅读代码)。
你完了!现在让我们在 TensorBoard 中查看结果!
您也可以使用 TensorBoard 查看您的结果:
tensorboard --logdir=/data/imagenet/trained_model/Resnet50_bs64
张量板输出
如果您正确运行了上面的步骤(并使用了相似的参数),您应该会得到类似的结果。注意,这些结果与官方 TensorFlow 结果相当。让我们看看你能做什么!
精度
训练 _ 精度 _1
准确度 _ 最高 _5
train_accuracy_top_5_1
损失
L2 _ 损失
cross_entropy_1
learning_rate_1
秒
最后的想法
差不多就是这样!如果您在 ResNet 培训中有任何问题,请告诉我们。还有,你在 TensorFlow 中训练模型的时候用了哪些技巧和窍门?让我知道!
原载于 2019 年 3 月 26 日https://blog.exxactcorp.com。
Handtrack.js:使用 Tensorflow.js 和 3 行代码跟踪浏览器中的手交互。
js 库允许你用 3 行代码从任意方向的图像中跟踪用户的手(边界框)。
Here’s an example interface built using Handtrack.js to track hands from webcam feed. Try the demo here.
不久前,我真的被一个实验的结果震惊了,这个实验使用 TensorFlow 对象检测 api 来追踪图像中的手。我让训练过的模型和源代码可用,从那以后它就被用来原型化一些相当有趣的用例(一个帮助孩子拼写的工具,对预测手语的扩展,手打乒乓球等)。然而,虽然许多人想用训练好的模型进行实验,但许多人仍然有设置 Tensorflow 的问题(安装、TF 版本问题、导出图表等)。幸运的是,Tensorflow.js 解决了其中的几个安装/分发问题,因为它针对在浏览器的标准化环境中运行进行了优化。为此,我创建了 Handtrack.js 作为一个库,以允许开发人员 快速 通过训练有素的手部检测模型实现原型手部/手势交互。
运行时: 22 FPS 。在 Macbook Pro 2018 上,2.2 Ghz,Chrome 浏览器。Macbook Pro 2014 2.2GHz 上的 13 FPS
该库的目标是抽象出与加载模型文件相关的步骤,提供有用的功能,并允许用户在没有任何 ML 经验的情况下检测图像中的手。你不需要训练一个模特(你可以,如果你想的话)。您不需要导出任何冻结的图形或保存的模型。您可以通过在 web 应用程序中包含 handtrack.js(细节如下)并调用库方法来开始。
使用 Handtrack.js 搭建的互动演示在这里,GitHub 上的源代码在这里。喜欢在 Codepen 里修修补补?这里有一个 handtrack.js 示例笔可以修改。
一个用于直接在浏览器中原型化实时手部检测(边界框)的库。- victordibia/handtrack.js
github.com](https://github.com/victordibia/handtrack.js/)
我如何在 Web 应用程序中使用它?
您可以简单地通过在脚本标签中包含库 URL 或者通过使用构建工具从npm
导入它来使用handtrack.js
。
使用脚本标签
Handtrack.js minified js 文件目前使用 jsdelivr 托管,这是一个免费的开源 cdn,允许您在 web 应用程序中包含任何 npm 包。
<script src="https://cdn.jsdelivr.net/npm/handtrackjs/dist/handtrack.min.js"> </script>
一旦上面的脚本标签被添加到您的 html 页面中,您就可以使用handTrack
变量引用 handtrack.js,如下所示。
const img = document.getElementById('img');
handTrack.load().then(model => {
model.detect(img).then(predictions => {
console.log('Predictions: ', predictions) // bbox predictions
});
});
上面的代码片段打印出了通过 img 标签传入的图像的边界框预测。通过提交来自视频或摄像机的帧,您可以在每一帧中"跟踪"手(您需要随着帧的进展保持每只手的状态)。
Demo interface using handtrack.js to track hands in an image. You can use the renderPredictions()
method to draw detected bounding boxes and source image in a canvas object.
使用 NPM
您可以使用以下代码将handtrack.js
作为 npm 包安装
npm install --save **handtrackjs**
下面给出了一个如何在 React 应用程序中导入和使用它的示例。
import * as handTrack from 'handtrackjs';
const img = document.getElementById('img');
// Load the model.
handTrack.load().then(model => {
// detect objects in the image.
console.log("model loaded")
model.detect(img).then(predictions => {
console.log('Predictions: ', predictions);
});
});
You can vary the confidence threshold (predictions below this value are discarded). Note: The model tends to work best with well lighted image conditions. The reader is encouraged to experiment with confidence threshold to accommodate various lighting conditions. E.g. a low lit scene will work better with a lower confidence threshold.
什么时候应该使用 Handtrack.js
如果你对基于手势(身体作为输入)的交互体验感兴趣,Handtrack.js 会很有用。用户不需要附加任何额外的传感器或硬件,而是可以立即利用基于手势/身体作为输入的交互所带来的参与优势。
A simple body-as-input interaction prototyped using Handtrack.js where the user paints on a canvas using the tracked location of their hand. In this interaction the maxNumber of detections modelParameter value is set to 1 to ensure only one hand is tracked.
下面列出了一些(并非全部)相关场景:
- 当鼠标运动可以被映射到手的运动以进行控制时。
- 当手和其他物体的重叠可以表示有意义的交互信号(例如物体的触摸或选择事件)时。
- 人手运动可以代表活动识别的场景(例如,从视频或个人下棋的图像中自动跟踪运动活动,或者跟踪个人的高尔夫挥杆)。或者简单地计算图像或视频帧中有多少人。
- 互动艺术装置。可能是一套有趣的互动艺术装置控件。
- 教别人 ML/AI。handtrack.js 库提供了一个有价值的界面来演示模型参数(置信度阈值、IoU 阈值、图像大小等)的变化如何影响检测结果。
- 您需要一个易于使用的演示,任何人都可以通过最少的设置轻松运行或试用。
Body as input in the browser. Results from Handtrack.js (applied to webcam feed) controls of a pong game. Try it here. Modify it here on Codepen.
Body as input on a large display. Results from Handtrack.js (applied to webcam feed) can be mapped to the controls of a game.
Handtrack.js API
提供了几种方法。两个主要方法包括加载手检测模型的load()
和用于获得预测的detect()
方法。
load()
接受可选的模型参数,允许您控制模型的性能。该方法以 web 模型格式加载预训练的手检测模型(也通过 jsdelivr 托管)。
detect()
接受输入源参数(html img、视频或画布对象),并返回图像中手部位置的边界框预测。
const modelParams = {
flipHorizontal: true, // flip e.g for video
imageScaleFactor: 0.7, // reduce input image size .
maxNumBoxes: 20, // maximum number of boxes to detect
iouThreshold: 0.5, // ioU threshold for non-max suppression
scoreThreshold: 0.79, // confidence threshold for predictions.
}const img = document.getElementById('img');handTrack.**load**(modelParams).then(model => {
model.**detect**(img).then(predictions => {
console.log('Predictions: ', predictions);
});
});
预测结果的形式如下
[{
bbox: [x, y, width, height],
class: "hand",
score: 0.8380282521247864
}, {
bbox: [x, y, width, height],
class: "hand",
score: 0.74644153267145157
}]
还提供了其他辅助方法
model.getFPS()
:获取每秒检测次数计算的 FPS。model.renderPredictions(predictions, canvas, context, mediasource)
:在指定的画布上绘制边界框(以及输入的媒体源图像)。model.getModelParameters()
:返回模型参数。model.setModelParameters(modelParams)
:更新模型参数。dispose()
:删除模型实例startVideo(video)
:在给定的视频元素上开始摄像机视频流。返回一个承诺,可用于验证用户是否提供了视频权限。stopVideo(video)
:停止视频流。
库大小和模型大小
- 库大小— 810kb。主要是因为它与 tensorflow.js 库捆绑在一起(最近的版本中有一些公开的问题破坏了该库。)
- Models — 18.5mb。这是导致页面加载时初始等待的原因。TF.js webmodels 通常被分割成多个文件(在本例中是四个 4.2mb 的文件和一个 1.7 mb 的文件。)
它是如何工作的
在底层,Handtrack.js 使用了 Tensorflow.js 库,这是一个灵活而直观的 API,用于在浏览器中从头开始构建和训练模型。它提供了一个低级的 JavaScript 线性代数库和一个高级的 layers API。
Steps in creating a Tensorflow.js -based JavaScript Library.
数据汇编
本项目中使用的数据主要来自 Egohands 数据集。这是由 4800 张不同环境下(室内、室外)带有边框注释的人手图像组成,这些图像是使用谷歌眼镜设备拍摄的。
模特培训
使用 Tensorflow 对象检测 API 训练一个模型来检测手。对于这个项目,一个单次多盒探测器 (SSD)与 MobileNetV2 架构一起使用。然后,来自训练模型的结果被导出为savedmodel
。关于模型如何被训练的更多细节可以在这里和 Tensorflow 对象检测 API github repo 上找到。
模型转换
Tensorflow.js 提供了一个模型转换工具,允许您将 Tensorflow python 中训练的savedmodel
转换为可以在浏览器中加载的 Tensorflow.js webmodel
格式。这个过程主要是将 Tensorflow python 中的操作映射到 Tensorflow.js 中的等价实现。有必要检查保存的模型图以了解正在导出的内容。最后,我按照 Tensorflow coco-ssd 示例的作者的建议 T17 在转换期间删除了对象检测模型图的后处理部分。这种优化有效地将浏览器中检测/预测操作的运行时间增加了一倍。
库包装和托管
该库是在 tensorflowjs coco-ssd 示例之后建模的(但不是用 typescript 编写的)。它由一个主类和一组其他有用的函数组成,主类包含加载模型、检测图像中的手的方法,例如 startVideo、stopVideo、getFPS()、renderPredictions()、getModelParameters()、setModelParameters()等。Github 上有关于方法的完整描述。
然后使用 rollup.js 捆绑源文件,并在 npm 上发布(带有 webmodel 文件)。这尤其有价值,因为 jsdelivr 自动为 npm 包提供 cdn。(在其他 cdn 上托管文件可能会更快*,并鼓励读者尝试其他方法)*。目前,handtrackjs 与 tensorflowjs (v0.13.5)捆绑在一起,主要是因为在编写这个库时,存在版本问题,tfjs (v0.15)在将图像/视频标签作为张量加载时出现数据类型错误。随着新版本修复此问题,它将被更新。
限制
- 浏览器是单线程的:这意味着必须小心确保预测操作不会阻塞 UI 线程。每次预测可能需要 50 到 150 毫秒,这对于用户来说是显而易见的。例如,当将 Handtrack.js 集成到一个每秒多次渲染整个屏幕(例如在游戏中)的应用程序中时,我发现它有助于减少每秒请求的预测数量。在这个场景中, Webworkers ,一个允许在后台线程中运行脚本的新兴标准,将有助于防止 UI 阻塞。
Web Workers 是 Web 内容在后台线程中运行脚本的简单手段。工作线程可以在不干扰用户界面的情况下执行任务。此外,它们可以使用
[XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest)
执行 I/O(尽管responseXML
和channel
属性总是空的)。创建后,工作线程可以向创建它的 JavaScript 代码发送消息,方法是向该代码指定的事件处理程序发送消息(反之亦然)。本文提供了使用 web workers 的详细介绍。
- 逐帧跟踪手:如果有兴趣跨帧识别手,您需要编写额外的代码来推断检测到的手进入、移动和离开连续帧的 id。提示:在每帧中保持每个预测位置的状态(和欧几里德距离)可以帮助。
- 错误预测:偶尔会有错误预测(有时人脸被检测为手)。我发现每个相机和照明条件需要不同的模型参数设置(尤其是置信度阈值)来获得良好的检测。更重要的是,这可以通过额外的数据来改善。
我真的很期待使用或扩展这个项目的其他人如何解决其中的一些限制。
接下来是什么?
Handtrack.js 代表了真正的 早期步骤 关于实现人工智能人机交互新形式的整体潜力。在浏览器中。已经有一些很好的想法,比如浏览器中用于人体姿势检测的posenet和用于面部表情检测的handseys . js。
最重要的是,请读者想象。想象一下有趣的用例,知道用户手的位置可以产生更吸引人的交互。
与此同时,我将在以下方面花更多时间
- 更好的手模型:创建一个健壮的基准来评估基本的手模型。收集额外的数据,提高准确性和稳健性指标。
- 附加词汇:在我构建示例的过程中,有一点变得很明显,那就是这种交互方法的词汇有限。显然需要支持至少一个州。也许是一只拳头和一只张开的手。这将意味着重新标记数据集(或一些半监督方法)。
- 额外的模型量化:目前,我们正在使用最快的模型 wrt 架构大小和准确性——MobilenetV2,SSD。有没有优化可以让事情变得更快?欢迎任何想法或贡献。
如果你想更详细地讨论这个问题,请随时联系 Twitter、T2、Github 或 T4 的 Linkedin。非常感谢 Kesa Oluwafunmilola 帮助校对这篇文章。
参考
- [1]桑德勒,马克等,“移动互联网 2:反向残差和线性瓶颈。”IEEE 计算机视觉和模式识别会议录。2018.https://arxiv.org/abs/1801.04381
- [2] Tensorflow.js Coco-ssd 示例。
该库使用来自 Tensorflow.js coco-ssd 示例的代码和指导,该示例提供了一个用于在 MSCOCO 数据集上训练的对象检测的库。repo 中建议的优化(去掉一个后处理层)真的很有帮助(2 倍加速)。
使用 PyTorch 的手写数字识别——神经网络介绍
对吗?——弄清楚上面的图片代表数字四,对你来说没什么。你甚至没有为图像的分辨率差而烦恼,多神奇啊。我们都应该花点时间感谢我们的大脑!我想知道我们的大脑对图像进行处理、分类和反馈是多么自然。我们是天才!
模仿人脑会有多难?深度学习,简单来说,是机器学习研究的领域,它允许计算机学习执行大脑自然的任务,如手写数字识别。从技术上来说,它涉及更多的层(我们后面会讲到)和更多的数据。
在本文中,我们将讨论神经网络,并从头开始开发一个手写数字分类器。我们将使用 PyTorch 因为它很酷!
本文的唯一先决条件是 Python 语法的基础知识。坐下来,喝杯咖啡,跟着我走。
Only Good Coffee Please!
步骤 1 —了解数据集
作为数据科学家,最重要的任务是收集完美的数据集,并彻底理解它。相信我,剩下的就简单多了。对于这个项目,我们将使用流行的 MNIST 数据库。它是 70000 个手写数字的集合,分为分别由 60000 个和 10000 个图像组成的训练集和测试集。
Source: Wikimedia
该数据集最初可在 Yann Lecun 的网站上获得。清理数据是最大的任务之一。别忘了— “垃圾进,垃圾出!” 。幸运的是,对我们来说,PyTorch 提供了一个简单的实现,使用几行代码就可以下载干净的和已经准备好的数据。在开始之前,我们需要做所有必要的进口。
import numpy as np
import torch
import torchvision
import matplotlib.pyplot as plt
from time import time
from torchvision import datasets, transforms
from torch import nn, optim
在下载数据之前,让我们定义在将数据输入管道之前,我们希望对数据执行哪些转换。换句话说,您可以将它视为对图像执行的某种自定义编辑,以便所有图像都具有相同的尺寸和属性。我们使用 torchvision.transforms 来实现。
transform = transforms.Compose([transforms.ToTensor(),
transforms.Normalize((0.5,), (0.5,)),
])
- 摇身一变。ToTensor() —将图像转换成系统可理解的数字。它将图像分成三个颜色通道(单独的图像):红色、绿色&蓝色。然后,它将每个图像的像素转换为其颜色在 0 到 255 之间的亮度。然后将这些值缩小到 0 到 1 之间的范围。图像现在是一个火炬张量。
- 变换变换。Normalize()
现在,我们终于下载了数据集,对它们进行了洗牌和转换。我们下载数据集并将它们加载到 DataLoader ,它将数据集和采样器结合在一起,并在数据集上提供单进程或多进程迭代器。
trainset = datasets.MNIST('PATH_TO_STORE_TRAINSET', download=**True**, train=**True**, transform=transform)valset = datasets.MNIST('PATH_TO_STORE_TESTSET', download=**True**, train=**False**, transform=transform)trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=**True**)valloader = torch.utils.data.DataLoader(valset, batch_size=64, shuffle=**True**)
在一行中,批量大小是我们想要一次读取的图像数量。
步骤 2-更好地了解数据集
在这个阶段,我们将对我们的图像和张量进行一些探索性的数据分析。让我们检查一下图像和标签的形状。
dataiter = iter(trainloader)
images, labels = dataiter.next()
print(images.shape)
print(labels.shape)
您将发现图像的形状是,torch.Size([64,1,28,28])
,这表明每批中有 64 个图像,每个图像的尺寸为 28 x 28 像素。类似地,标签的形状为torch.Size([64])
。猜猜为什么?—是的,你说得对!64 张图片应该分别有 64 个标签。就是这样。轻松点。
让我们显示训练集中的一幅图像,例如第一幅。
plt.imshow(images[0].numpy().squeeze(), cmap='gray_r');
酷吧!让我们展示更多的图像,这将让我们感受一下数据集的样子。
figure = plt.figure()
num_of_images = 60
**for** index **in** range(1, num_of_images + 1):
plt.subplot(6, 10, index)
plt.axis('off')
plt.imshow(images[index].numpy().squeeze(), cmap='gray_r')
这将生成一个随机排列的图像网格。现在,是时候开始定义我们将要使用的神经网络了。
步骤 3——建立神经网络
我们将构建下面的网络,正如你所看到的,它包含一个输入层(第一层),一个由十个神经元(或单元,圆圈)组成的输出层,以及中间的两个隐藏层。
PyTorch 的torch.nn
模块允许我们非常简单地构建上述网络。这也非常容易理解。看看下面的代码。
input_size = 784
hidden_sizes = [128, 64]
output_size = 10
model = nn.Sequential(nn.Linear(input_size, hidden_sizes[0]),
nn.ReLU(),
nn.Linear(hidden_sizes[0], hidden_sizes[1]),
nn.ReLU(),
nn.Linear(hidden_sizes[1], output_size),
nn.LogSoftmax(dim=1))
print(model)
nn.Sequential
包裹网络中的层。有三个带 ReLU 激活的线性层(一个允许正值通过的简单函数,而负值被修改为零)。输出图层是激活了 LogSoftmax 的线性图层,因为这是一个分类问题。
从技术上来说,一个 LogSoftmax 函数是一个 Softmax 函数的对数,顾名思义,它看起来像这样,如下所示。
接下来,我们定义 负对数似然损失 。用 C 类训练一个分类问题很有用。 LogSoftmax() 和 NLLLoss() 一起充当交叉熵损失,如上面的网络架构图所示。
另外,你一定想知道为什么我们在第一层有 784 个单元。很好!这是因为我们在将每幅图像发送到神经网络之前将其展平。 (28 x 28 = 784)
criterion = nn.NLLLoss()
images, labels = next(iter(trainloader))
images = images.view(images.shape[0], -1)
logps = model(images) #log probabilities
loss = criterion(logps, labels) #calculate the NLL loss
我们将在以后的文章中讨论更多的神经网络,激活函数,优化算法等。
步骤 4 —调整重量
神经网络通过对可用数据进行多次迭代来学习。 学习 是指调整网络的权值,使损耗最小。让我们想象一下它是如何工作的。
print('Before backward pass: **\n**', model[0].weight.grad)
loss.backward()
print('After backward pass: **\n**', model[0].weight.grad)
在向后传递之前,模型权重被设置为默认的无值。一次,我们调用 backward() 函数来更新权重。
Before backward pass:
None
After backward pass:
tensor([[-0.0003, -0.0003, -0.0003, ..., -0.0003, -0.0003, -0.0003],
[ 0.0008, 0.0008, 0.0008, ..., 0.0008, 0.0008, 0.0008],
[-0.0037, -0.0037, -0.0037, ..., -0.0037, -0.0037, -0.0037],
...,
[-0.0005, -0.0005, -0.0005, ..., -0.0005, -0.0005, -0.0005],
[ 0.0043, 0.0043, 0.0043, ..., 0.0043, 0.0043, 0.0043],
[-0.0006, -0.0006, -0.0006, ..., -0.0006, -0.0006, -0.0006]])
步骤 5 —核心培训流程
这是真正的奇迹发生的地方。您的神经网络迭代训练集并更新权重。我们使用 PyTorch 提供的模块torch.optim
来优化模型,执行梯度下降,并通过反向传播来更新权重。因此,在每个时期(我们迭代训练集的次数),我们将看到训练损失逐渐减少。
optimizer = optim.SGD(model.parameters(), lr=0.003, momentum=0.9)
time0 = time()
epochs = 15
**for** e **in** range(epochs):
running_loss = 0
**for** images, labels **in** trainloader:
*# Flatten MNIST images into a 784 long vector*
images = images.view(images.shape[0], -1)
*# Training pass*
optimizer.zero_grad()
output = model(images)
loss = criterion(output, labels)
*#This is where the model learns by backpropagating*
loss.backward()
*#And optimizes its weights here*
optimizer.step()
running_loss += loss.item()
**else**:
print("Epoch **{}** - Training loss: **{}**".format(e, running_loss/len(trainloader)))print("**\n**Training Time (in minutes) =",(time()-time0)/60)
这可能需要一些时间来执行,并且会因系统而异。我在云笔记本上花了 2.5 分钟。
步骤 6 —测试和评估
我们的工作快完成了。模型做好了,但我们要先评估一下。我创建了一个实用函数 view_classify() 来显示预测的图像和类别概率。代码可以在 GitHub 上找到。(下面参考资料部分的链接)。
我将我们之前创建的验证集中的一个图像传递给训练好的模型,以查看模型是如何工作的。
images, labels = next(iter(valloader))
img = images[0].view(1, 784)**with** torch.no_grad():
logps = model(img)
ps = torch.exp(logps)
probab = list(ps.numpy()[0])
print("Predicted Digit =", probab.index(max(probab)))
**view_classify**(img.view(1, 28, 28), ps)
Prediction Result. Perfect Prediction!
现在,我们使用 for 循环遍历验证集,并计算正确预测的总数。这是我们计算精确度的方法。
correct_count, all_count = 0, 0
**for** images,labels **in** valloader:
**for** i **in** range(len(labels)):
img = images[i].view(1, 784)
**with** torch.no_grad():
logps = model(img)
ps = torch.exp(logps)
probab = list(ps.numpy()[0])
pred_label = probab.index(max(probab))
true_label = labels.numpy()[i]
**if**(true_label == pred_label):
correct_count += 1
all_count += 1
print("Number Of Images Tested =", all_count)
print("**\n**Model Accuracy =", (correct_count/all_count))
现在来看看结果。这是最有趣的部分!
Number Of Images Tested = 10000
Model Accuracy = 0.9751
哇!我们有超过 97.5%的准确率。这是值得庆祝的事情。我们获得如此高精度的原因是,我们的数据集是干净的,有各种各样经过良好洗牌的图像,而且数量很大。这使得我们的模型能够很好地识别大量看不见的数字。
步骤 7 —保存模型
现在我们已经完成了所有的工作,我们不想失去训练好的模型。我们不想每次用的时候都训练它。为此,我们将保存模型。以后需要的时候,可以直接加载使用,不需要进一步的训练。
torch**.save**(model, './my_mnist_model.pt')
第一个参数是模型对象,第二个参数是路径。PyTorch 型号一般用.pt
或.pth
扩展名保存。查阅文件。
结论
我希望你喜欢建立一个神经网络,训练它,测试它,最后保存它的过程。在构建一个很酷的项目的同时,你肯定已经掌握了一些概念,学到了一些新东西。我很想知道它是如何为你工作的。 并且,如果你喜欢请鼓掌,这对我是一种鼓励。 😃 更多炫酷文章一字排开。即将推出!
如果你有心情请我喝啤酒🤩> >https://www.buymeacoffee.com/amitrajit
哦!并且, 整个笔记本在这里 都有。笔记本电脑的 GPU 版本不同于 CPU 版本。你可以根据你的需要参考。
参考文献
[1] PyTorch 官方 Docs 【2】MNIST 维基百科【3】Cool GIFs 来自GIPHY
【4】GitHub 上的全部代码