您的仪表板对组织有影响吗?
Photo by Julien-Pier Belanger on Unsplash
怎么会?就用“那又怎样?”试验
我的第一个数字仪表板并没有得到管理层的好评。经过数周的计划和准备,在一个下雨的周五下午,我和我的同事向总经理展示了最终产品。
会议期间,我们向她详细介绍了我们的杰作——我敢肯定,我们脸上挂着大大的傻笑。
她最后说了什么…“ 那又怎样?”
那一年,带有向下钻取功能的网页非常流行
在网络报道的早期,能够深入了解更多信息是非常棒的(或者对我们来说是这样)!我们为我们的仪表板感到骄傲。我们设想赢得世界最佳仪表板奖,并获得一个镶满钻石的皇冠,戴在我们聪明的小脑袋上。
我们花哨的仪表板是为客户支持部门设计的。它展示了有关故障单计数和代理回复率的数据。经理可以根据过去 30 天的回复率,选择计数以深入查看 traffic-lite 客户问题列表。
我们有技术,但没有可操作的分析
总经理继续说,“那又怎样?那又怎样?”看完之后耸了耸肩。我们面面相觑,然后看向我们的经理,因为我们不知道如何回答。总经理是一个令人印象深刻的人物,我们想给她留下深刻的印象,仿效她。
我的经理从军队退休了。在他的职业生涯中,他见过更糟糕的情况,但对我们来说这就像是一场战争。我们的经理不好意思地问总经理,“你是什么意思?”
“如果有 72 张严重性为中等的罚单,响应率为 76%,那又如何。它应该是什么?应该少票吗?更多?回复率好吗?不好?你希望我用这些信息做什么?”,她一边举起双手一边继续说道。她变得不耐烦了。
“目标是 85%。他表示:“未来几周,到达的门票数量将会下降——这是一个积极的趋势。”。
“团队没有达到目标,工作票也少了,这是这份报告想要表达的意思吗?她问。“我是不是应该先看看这份报告,然后打电话给你问清楚?”
“我明白了。这个仪表板需要说明这一点。”我们的经理回答道。
“他们为什么会错过目标?对此正在做些什么?”她继续说道。这是真正的标题和数据的真正要点。
结论,而不是建议
好消息是仪表板开始工作了。我们已经将数据提炼为几个简单的关键绩效指标(KPI),她已经准备好应对这种情况。
坏消息是我们的仪表板没有回答“那又怎样”的问题——它只呈现了一些事实。
管理层在寻找一个结论,这是仪表板的一个关键元素。那天,我戴上最好的仪表板头饰的梦想就像放了一天的结婚蛋糕一样被抛到了一边。总经理证实,我们已经建立了一个花哨的网络报告,而不是一个有用的工具。
将报表更改为仪表板
报表不同于仪表盘,有些人没有意识到这一点。这两个术语经常互换使用——对我来说,仪表板可以帮助您了解性能。
报告提供了您可以查看的事实,例如,故障单的数量或响应率。在下图中,我使用 SAS Visual Analytics 重新创建了一个简单的示例,展示了我们的仪表板的外观。
应用“那又怎样”测试
如果你试图确定你正在看的是一份报告还是一个仪表板,使用通用汽车公司的“那又怎样?”测试。你可以很容易地问“如果上周有 156 张低优先级票,那又怎么样?”你不知道这是一个好的还是坏的事实——它只是一个事实。页面上没有支持信息来帮助您确定“什么”
你需要帮助来下结论
没有任何支持信息——上表没有通过测试,所以没有通过测试。我们需要一种方法来知道事实是好是坏。为了测量到达的票计数,我们采用前一周的计数或过去六周的平均值来确定趋势。然后我们可以分配一个显示规则,如下所示:
- 如果本周的票数高于上周,将该事实标记为红色
- 如果低于前一周,则显示为绿色
- 如果是一样的,那就把它变成黄色或者什么都没有
回应率基于服务水平协议。如果客户期望特定的回复率,则使用该回复率作为衡量标准。对于高优先级票证,他们希望 99%的票证在 24 小时内关闭,中等优先级票证在五天内关闭 85%。在这种情况下,条形不是红色就是绿色。团队是否达到了目标。如果他们有一个大问题,顾客很少关心他们的票是否几乎准时关闭。
如果您将“那又怎样”测试应用于该仪表板,它将不起作用。本周有 156 张低优先级票,比上周低,这很好。当有结论时,经理可以查看仪表板,看看他们下一步需要确定什么。
推动组织向前发展
在上面的仪表板中,经理需要知道为什么团队没有达到服务级别。也许团队人手不足?可能安装了一个热补丁,破坏了许多客户系统,所以它让每个人都很忙。
我并不是说仪表板从来没有任何事实,但是事实应该是支持信息,而不是表演的明星。例如,在上图中,查看 12 周或 6 个月的票证关闭率会有所帮助,这样我们就可以知道这种情况是异常还是持续存在。
你的外卖
- 什么时候需要事实,什么时候结论更有用?
- 你如何提供数据来帮助管理者理解需要采取的行动?
最初在 www.zencos.com 出版。
以光速构建和部署数据科学项目
“starry night” by Quentin Kemmel on Unsplash
(或其左右)。
使用 Repl.it 的云环境在几分钟内分析和共享陨石降落数据
当今数据科学发展的最大挑战之一是快速共享、开发和部署代码。
除非你在一个数据科学和分析深深嵌入公司文化和生态系统(以及 Github)的企业中工作,否则你很可能已经体验过包含 SQL 行的电子邮件链的乐趣,无穷无尽。Slack 上的 txt 代码片段和足够多的类似命名的 R 环境引起了真正的头痛。
在这些环境中,与其他数据科学家、分析师和工程师共享代码可能是一项挑战。在某些情况下,数据仍然与传统的工程部门过于分离,这意味着这是一种乞求、借用和窃取代码模式和最佳实践的情况。
在阅读了威廉·科赫森的回复后,我很想尝试一下这个新平台。它允许你在云环境中快速构建、测试和共享代码。对数据人员来说,好消息是 repl.it 支持多种语言,包括 R 和 Python。
“silhouette photo of mountain during night time” by Vincentiu Solomon on Unsplash
我一直在使用 NASA 的陨石着陆数据作为一个项目的样本数据,该项目围绕群体分析以及何时利用参数与非参数分析方法。这似乎是一个绝佳的机会,可以看看 repl.it 导入外部数据集并提供快速分析的能力如何。
虽然在这种情况下,我可以访问群体(已知的降落在地球上的陨石),但为了项目的目的,我想对这些数据进行采样,以了解坠落和发现的陨石的质量是否不同,并分析样本是否来自正态分布的群体。
下面,你可以看到来自 repl.it 的嵌入,它导入了美国宇航局的数据集,采集了样本,提供了一个用于正态性的夏皮罗-维尔克测试和一个箱线图可视化,以了解质量数据的分布,按坠落和发现的陨石进行划分,进一步:
如您所见,repl.it 环境可以轻松处理外部数据导入和可视化运行,即使是在介质中。我确实发现,目前 repl.it 似乎还不能处理 install.packages()和 library()功能,所以使用 ggplot 等工具进行分析目前是不允许的。然而,对于基本功能,repl.it 提供了一种简单快捷的方法来与您的团队和更广泛的数据社区共享 R 代码。而且是免费的!
有用的资源
https://data . NASA . gov/Space-Science/陨石降落/gh4g-9sfh
了解如何在 R 中为单个变量或按组为变量创建箱线图。
www.statmethods.net](https://www.statmethods.net/graphs/boxplot.html) [## 如何把完全交互式的、可运行的代码放到一篇中等的文章中
代码应该是交互式的。
towardsdatascience.com](/how-to-put-fully-interactive-runnable-code-in-a-medium-post-3dce6bdf4895)
建立、开发和部署一个机器学习模型,使用梯度推进来预测汽车价格。
介绍
在这篇博文中,我将介绍一个数据科学过程,通过以下步骤来构建和部署一个可以预测汽车价格的机器学习模型:
- 设定研究目标
- 检索数据
- 数据预处理和清理
- 数据探索和可视化
- 数据建模
- 模型部署
设定研究目标
这项工作的目的是通过构建和部署一个机器学习模型来熟悉如上所述的数据科学过程,该模型可以根据汽车的特征来预测汽车价格,方法是尝试 4 个回归模型,并选择具有最高 R 分数和最低均方根误差的模型。
Demo of the Web App
检索数据
检索数据是设定研究目标后的重要步骤,为此,我使用了专门从事这类任务的著名 python 库“BeautifulSoup”
。该任务的过程非常简单,首先我们循环遍历广告页面,通过增加基本 URL 中名为o
的页码参数来收集广告 URL,如下所示:
basic_url = "[https://www.avito.ma/fr/maroc/voitures-](https://www.avito.ma/fr/maroc/voitures-)à_vendre&o="
一旦 URL 被收集,我将它们设置在一个名为“ads_urls.csv”的csv
文件中,如下所示:
[https://www.avito.ma/fr/temara/voitures/peugeot_508_26753561.htm](https://www.avito.ma/fr/temara/voitures/peugeot_508_26753561.htm)
[https://www.avito.ma/fr/safi/voitures/renualt_kasket_26753552.htm](https://www.avito.ma/fr/safi/voitures/renualt_kasket_26753552.htm)
[https://www.avito.ma/fr/oued_fes/voitures/Citroen_C3_Diesel_26753551.htm](https://www.avito.ma/fr/oued_fes/voitures/Citroen_C3_Diesel_26753551.htm)
.
...
上面这些链接中的每个链接都包含广告中发布的汽车的相关数据,例如:“车型年”、“里程”、“燃料类型”、“价格”…,看起来就像这样:
Car features published on the Ad page
然后,我读取这个包含要在广告页面上抓取的 URL 列表的文件,并提取必要的数据,所以这里有一个关于它如何工作的简短代码快照。
Extracting ad data procedure
最后我得到以下数据模式:
price, year_model, mileage, fuel_type, mark, model, fiscal_power, sector, type, city
135 000 DH,Année-Modèle:2013,Kilométrage:160 000–169 999,Type de carburant:Diesel,Marque:Peugeot,Modèle:508,Puissance fiscale:-,-,”Type:Voitures, Offre”, Temara
60 000 DH,Année-Modèle:2009,Kilométrage:130 000 - 139 999,Type de carburant:Essence,Marque:Ford,Modèle:Fiesta,Puissance fiscale:7 CV,Secteur:saies,"Type:Voitures, Offre", Fès
.
...
下一步是每个数据科学流程中最耗时的步骤,即数据预处理和清理。
数据预处理和清理
数据清理
数据预处理的原因是将我们的原始数据转换成有用的数据,并减少数据大小,以便于分析,在这种情况下,我们需要:
price
:去掉price
中的“DH”(迪拉姆货币)字符和空格,然后转换成整数。year_model
:从year_model
列中删除不需要的字符串,如:“Anne-modèle:”或“ou plus ancien”,然后将其转换为整数。mileage
:对于这个字段来说,事情完全不同,我们有一个里程范围,例如在每次观察中,我们的里程在 160000 - 169999 公里之间,所以在删除“公里”和“-”字符后,我必须呈现这个列,以便只保留一个值而不是一个范围,我们可以使用最小值或最大值,对我来说,我选择使用平均值,以便我们保持在该范围的中间。fuel_type
:从fuel_type
栏中移除不需要的字符串,如“de 型增碳剂:”。mark
:从mark
栏中移除“品牌:”字符串。fiscal_power
:对于这个字段,我必须处理两种情况:删除不需要的字符串,如“Puissance fiscale: CV ”,并处理缺失值,因此处理缺失值的技巧之一是用所有fiscal_power
列的平均值填充它们。
删除不需要的列
对于数据探索和分析,我们不需要一些列,如“sector”和“type ”,所以我们最终将它们从数据框中删除。
数据探索和可视化
在数据提取和数据预处理步骤之后,我现在应该可视化我的数据集,这样我就可以更深入地了解幕后发生了什么,以及我的数据是如何分布的。
在接下来的部分中,我将运行一个问答会话,以回答许多基于直方图和图的问题。
问:价格在年度模型中是如何分布的?
Price distribution over the year of released model
**答:**从上面的图中我们可以看出,汽车价格逐年上涨,更明确地说,我们可以说,最近发布的汽车越多,价格上涨越多,而另一方面,最老的汽车仍然价格低廉,这是完全符合逻辑的,因为每当汽车从发布之日起变得有点旧,价格就开始下降。
问:价格如何在财权上分配?
Price distribution over fiscal power
**答:**从上面的图中我们可以清楚地注意到,在[2800 DH,800000 DH]和[3 CV,13 CV]范围内存在着巨大的积分集中度,这可以解释为:首先,中型财政动力汽车在市场上占据着巨大的主导地位,价格是正确的;其次,财政动力越大,价格也越高。
问:燃料类型的价格如何按年分配?
Simple linear regression between price and year model grouped by fuel type
**答:**虽然疲软,但似乎在year_model
和price
之间存在正相关关系。让我们看看价格和其他数据点之间的实际相关性。我们将通过查看热图关联矩阵来确认。
Correlation matrix with Heatmap visualization
正如我们所看到的,在price
和 year_model
特性之间有很强的相关性,相关性分数为 0.47,这验证了price
和year_model
列之间的强关系。
数据建模
现在,我们来到了整个过程中的主要任务,即数据建模,为此,我将使用 4 个专门用于回归问题的机器学习模型,最后我将制作一个基准表来比较每个模型r2_score
,并选择最佳模型。使用的模型有:K 近邻回归、多元线性回归、决策树回归和梯度推进回归。
数据转换
我有意让这一部分一直进行到数据建模,而不是为了一些可视化的目的对数据进行预处理。
目前,我仍然有两个分类特征,它们是fuel_type
和mark
,这一部分的目的是预处理这些特征,以便将它们数字化,使它们适合我们的模型。在文献中,有两种著名的分类变量转换方法,第一种是标签编码,第二种是 one hot 编码,对于这个用例,我们将使用 one hot position,我选择这种数据标签的原因是因为我以后不需要任何类型的数据标准化,这样做的好处是不会对值进行不正确的加权,但也有向数据集添加更多列的缺点。
Features engineering and Data Transformation
Result of one hot encoding on the data frame
如上图所示,使用 one hot 编码将分类特征转换为数字特征后,我们得到了一个宽数据框。
数据拆分
通常我们将数据分成三部分:训练、验证和测试集,但为了简单起见,我们将只使用 20%的测试规模进行训练和测试,其余的用于训练。
梯度推进回归
Boosting 是另一种用于创建强大预测器集合的集成技术,而梯度 Boosting 是一种用于生成由回归变量集合组成的回归模型的技术。
集合是预测者的集合,其预测通常通过某种加权平均或投票进行组合,以提供从集合本身获得指导的总体预测。因此,boosting 是一种集成技术,在这种技术中,学习者按顺序学习,早期的学习者将简单的模型拟合到数据中,然后分析数据中的错误,这些错误识别出困难或难以拟合的问题或数据的特定实例,因此,后来的模型主要关注那些试图使它们正确的例子。
最后,所有模型贡献权重,集合被组合成一些整体预测器,因此 boosting 是一种将弱学习器序列转换成非常复杂的预测器的方法,它是一种增加特定模型复杂性的方法。最初的学习器往往非常简单,然后随着学习器的增加,加权组合会变得越来越复杂。
渐变增强背后的数学原理
这个算法是梯度推进的一个例子,它被称为梯度推进,因为它与梯度下降过程有关。
- 首先,我们为每个数据点做一组预测
ŷ(i)
。 - 我们可以计算出我们预测的误差,姑且称之为
J(y, ŷ)
,j 只是把ŷ的精度和 y 联系起来 - 对于均方差 MSE :
J(y, ŷ) = **Σ** ( y(i) **-**ŷ(i) **)²**
。 - 所以现在我们可以试着考虑调整我们的预测
ŷ
来试着减少上面的误差:ŷ(i)= ŷ(i) + α *∇J(y, ŷ)
,用:∇J(y, ŷ) = y(i)- ŷ(i)
- 每个学习者都在估计损失函数的梯度。
- 梯度下降:采取一系列步骤降低
J
。 - 预测值之和,按步长α加权。
梯度推进回归器—代码快照
Snapshot from the used code in the GBR model
解释残差与预测值
建立 GBR 模型后,主要建议绘制误差分布图,以验证以下假设:
- 正态分布
- 同方差(每个 X 处的方差相同)
- 自主的
这在我们的案例中已经得到了验证,您可以在笔记本上查看更多细节,但是我们需要观察残差图,以确保它不遵循非线性或异方差分布。
Residual VS Predicted values
正如我们从上面的图中看到的,残差在 0 线周围大致形成一个“水平带”,这表明误差项的方差相等,此外,没有一个残差从残差的基本随机模式中“脱颖而出”,这涉及到没有异常值。
车型基准测试
因此,在尝试了许多回归模型来拟合我们的数据集之后,是时候绘制一个基准表来总结我们得到的所有结果了。
╔═══════════════════╦════════════════════╦═══════════════╗
║ Model ║ R^2 score ║ RMSE ║
╠═══════════════════╬════════════════════╬═══════════════╣
║ KNN ║ 0.56 ║ 37709.67 ║
║ Linear Regression ║ 0.62 ║ 34865.07 ║
║ **Gradient Boosting** ║ 0.**80** ║ **25176.16** ║
║ Decision Tree ║ 0.63 ║ 34551.17 ║
╚═══════════════════╩════════════════════╩═══════════════╝
看起来梯度推进模型以最低的 RMSE 值和最高的 R 值赢得了这场战斗,正如它所预期的那样。
Heroku 模型部署
- 创建 Flask web 应用程序
Flask 是 Python 的一个“微”框架。之所以称之为微框架,是因为他们希望保持核心简单但可扩展。虽然一开始会有些困惑,但使用 Jinja2 模板在 Flask 上建立一个网站还是相对容易的。
flask 应用程序由两个主要组件组成:python 应用程序(app.py
)和 HTML 模板,对于app.py
它看起来是这样的:
Web App Controller
因此,一旦构建了app.py
,我们就可以从终端运行它,如果一切顺利,我们将得到在“/”路径上运行的index.html
页面,如:http://localhost:8080/
,然后我们可以用正确的值填充给定的表单,并得到一个甜蜜的警告弹出窗口。
2。将应用程序部署到 Heroku
对于这一部分,我将需要一个 Heroku 帐户(免费)和 HerokuCLI,我也可以使用 GitHub 来完成这项任务,但让事情变得简单。
- 设置 Procfile:Procfile 是一种机制,用于声明 Heroku 平台上应用程序的 dynos 运行哪些命令。创建一个名为“Procfile”的文件,并将以下内容放入其中:
web: gunicorn app:app --log-file -
- 通过在您的终端中运行以下命令,在 Flask 应用程序的根目录下创建 python 需求文件:
$ pipreqs ./
如果您在 python 虚拟环境中工作,这将是高效的:
$ pip3 freeze > requirements.txt
- 登录您的帐户,在 Heroku 网站上创建一个新的应用程序。
Form to create a new app with Heroku
创建好应用程序后,我们将被重定向到一个页面,该页面显示了成功部署的说明。在成功连接到 HerokuCLI 后,我需要将目录更改为我们的 flask 应用程序,并运行以下命令:
$ heroku git:clone -a cars-price-prediction
$ git add .
$ git commit -am "make it better"
$ git push heroku master
该应用程序现在应该在 my-app-name.herokuapp.com 现场直播!点击查看应用程序的工作版本。
结论
在这篇博客文章中,我试图通过构建一个可以根据汽车特征预测汽车价格的模型来介绍数据科学的过程,从数据收集开始,到数据建模和内置模型之间的比较,最后以模型部署为 web 应用程序结束。
有用的链接
完整笔记本:https://github . com/PaacMaan/cars-price-predictor/blob/master/cars _ price _ predictor . ipynb
GitHub 资源库:
这个项目一步一步的展示了如何建立一个模型来预测汽车的价格
github.com](https://github.com/PaacMaan/cars-price-predictor)
网页申请链接:https://cars-price-prediction.herokuapp.com
与❤.共享
使用神经网络从零开始构建手势识别-机器学习简单而有趣
从自拍图像到学习神经网络模型
Photo by Perry Grone on Unsplash
介绍
这种算法应该适用于所有不同的肤色,只要确保你的手放在中间。
对于这个解决方案,我使用了 GNU Octave 和 Visual Studio 代码。
数据和代码可以在我的 Github 库中找到。
[## gago 993/HandGestureRecognitionNeuralNetwork
使用神经网络的手势识别软件-gago 993/handsgeturerecognitionneuralnetwork
github.com](https://github.com/Gago993/HandGestureRecognitionNeuralNetwork)
我们需要做的所有工作可以分为 5 个步骤:
- 生成和准备数据
- 生成要素
- 生成 ML 模型
- 测试 ML 模型
- 用 ML 模型预测
那么让我们开始…
生成和准备数据
因为我们是从底层构建这个项目。我们需要做的第一件事是创建用于训练神经网络模型的数据。
对于这一步,我使用我的电脑内置摄像头。我从手上抓拍了 78 张图片,展示了 4 种不同的手势,它们被分成 4 个文件夹。我裁剪了一些图像,使它们更适合稍后训练我们的模型。所有训练(准备)图像都存储在 数据集 文件夹中。
- 左—包含 27 个向左指的手的图像
- 右-包含 24 个向右指的手的图像
- 手掌—包含 11 个手掌图像
- 和平—包含 14 个和平之手的图像(V 形符号)
Image 1: Dataset Example (Peace V Sign)
生成要素
训练图像准备就绪后,我们可以继续下一步,即处理所有图像并创建特征。从图像中分离手的主要算法通过几个简单的步骤完成:
- 加载图像
- 将图像大小调整为 50x50
- 将图像从 RGB 转换为 YCbCr 颜色
- 选择中心点颜色(期望手放在图像的中间)
- 根据步骤 3 中定义的肤色范围分割手部。
- 用白色标记所选像素,用黑色标记其他像素
这个算法放在processskinimage . m文件中。我记下了代码中的每一步。
该图像皮肤处理由create _ image _ dataset . m文件使用,该文件遍历所有图像,使用上述代码处理它们,并将它们分别写入左、右、手掌、和平文件夹中名为dataset _ resized的单独文件夹中。
最后,我们需要准备我们的图像,以便它们可以用于生成和测试我们的神经网络模型。因为我们得到了 78 幅图像,它们是 50x50 像素,所以我们将它们保存为 78x2500 大小的矩阵,其中每一列代表我们图像中的像素。我们也将随机地把矩阵分成两组。训练矩阵将被保存在 x_features_train 矩阵中,并将包含 80%的图像和 x_features_test 中的测试矩阵以及其他 20%的图像。标签将分别保存在 y_labels_train 和y _ labels _ test中。
创建特征矩阵的代码如下所示
...
% Generate random number from 1 to 10
randNum = ceil(rand() * 10);% Split the images in 80%-20% train-test set
if randNum > 2
% Create the features for the image
X_train = [X_train; image_out(:)'];
y_train = [y_train; label];
else
X_test = [X_test; image_out(:)'];
y_test = [y_test; label];
endif
...
有四种类型的标签:
- [1 0 0 0] —左指手形图像
- [0 1 0 0] —右手图像
- [0 0 1 0] —手掌图像
- [0 0 0 1] —和平标志手形图像
这个标签是在create _ image _ dataset . m中创建的,如下面的代码所示。其中 文件夹 是包含图像的文件夹名称, 是成员 从上面的列表中返回 4 个选项中的一个。
...
label_keys = { 'left', 'right', 'palm', 'peace'};
...
label = ismember(label_keys, folder);
...
这个脚本完成后,我们可以在dataset _ resized文件夹中检查已处理的图像,我们应该会看到类似这样的内容
Image 2: Processed Image (Peace V Sign)
还应该有x _ features _ train和y _ labels _ train文件,我们将在下一步中使用它们来训练我们的模型,还有x _ features _ test和y _ labels _ test用于稍后测试我们的模型。
在继续之前,在这篇博客中,我假设你已经熟悉神经网络,这就是为什么我不打算深入神经网络的解释。
为了充分理解概念和公式,我建议阅读我的帖子,以便更深入地理解神经网络。
[## 你需要知道的关于神经网络和反向传播的一切-机器学习变得容易…
神经网络的基础解释,包括理解背后的数学
towardsdatascience.com](/everything-you-need-to-know-about-neural-networks-and-backpropagation-machine-learning-made-easy-e5285bc2be3a)
生成 ML 模型
让我们从定义我们的神经网络结构开始。我们将在网络中使用一个隐藏层。输入层的大小将是 2500 个节点,因为我们的图像是 50x50 像素。隐藏层大小将是 25 个节点,输出将是 4 个节点(4 种类型的符号)。
定义隐藏层大小没有严格的公式,但通常取决于“它与数据的拟合程度如何?”
Image 3: Andrew Ng on Neural Network Size
这里我们将使用 main.m 文件,我们将:
- 加载要素和标注
- 随机初始化θ值(NN 节点权重)
- 创建成本函数并向前传播
- 为 NN 成本函数创建梯度(反向传播
- 使用 fmincg 最小化器最小化成本函数
加载特征和标签
让我们开始第一步,加载要素和标签。我们通过使用 dlmread 函数来实现。
...
X = dlmread('x_features_train');
% Labels for each processed training image
%[1 0 0 0] - left, [0 1 0 0] - right, [0 0 1 0] - palm, [0 0 0 1] - peace
y = dlmread('y_labels_train');
...
随机初始化θ值(NN 节点权重)
接下来我们需要使用randinitializeweights . m函数初始化 Theta 值。它由下面的代码表示
epsilon = sqrt(6) / (L_in + L_out);
W = zeros(L_out, 1 + L_in);
W = (rand(L_out, 1 + L_in) * 2 * epsilon) - epsilon;
其中生成的值在[-ε,ε]之间。该代码与“均匀分布方差”的统计公式相关。如果你对这个公式更感兴趣,我会在这个博客的末尾留下链接,或者你可以提出问题。
创建成本函数并向前传播
我们的下一个目标是实现下面等式定义的成本函数。
Image 4: Regularized Cost Function
其中 g 是激活函数(在这种情况下是 Sigmoid 函数)
为了计算成本,我们需要使用前馈计算。代码在***nncostfunction . m .***中实现。我们将在示例中使用 for 循环来计算成本,我们还需要将 1 的列添加到 X 矩阵中,表示“偏差”值。θ₁(θ1)和θ₂(θ2)值是神经网络中每个单元的参数,θ₁的第一行对应于第二层中的第一个隐藏单元。
为 NN 成本函数创建梯度(反向传播 )
为了能够最小化成本函数,我们需要计算 NN 成本函数的梯度。为此,我们将使用反向传播算法*,是“误差反向传播”的缩写,用于最小化我们的成本函数,这意味着最小化我们的 NN 的误差和最小化每个输出神经元的误差。这个计算是在nncostfunction . m*中实现的代码的一部分
使用 fmincg minimizer 最小化成本函数
一旦我们计算出梯度,我们可以通过使用高级优化器(如 *fmincg)最小化成本函数 J(θ)来训练神经网络。*这个函数不是 Octave 的一部分,所以我是从吴恩达的机器学习课程中得到的。据我所知,这个函数比 Octave 中实现的函数更快,它使用了共轭梯度法。
fmincg 接受 3 个参数,如下面的代码示例所示。它采用成本函数、连接成单个向量的初始θ (Theta)参数和选项参数。
在我们的测试例子上运行 fmincg 之后,我们得到了一个向量中的θ值,我们需要在矩阵中对它们进行整形,以简化矩阵乘法。
测试 ML 模型
现在,我们成功地从神经网络中生成了我们的 Theta(权重)值。接下来要做的是检查我们的模型与训练的吻合程度,以及它在测试数据上的表现。
为了预测我们将使用 预测 函数位于 预测. m 文件中。
该函数采用参数和特征矩阵。然后,它将表示“偏差”值的 1 列添加到特征矩阵中。只需将两个 NN 层的特征乘以θ值。然后,它获得大小为(number_of_images x 4)的向量 h2,其中每列(4)表示该图像在该类别中的可能性(左、右、手掌、和平)。最后 if 返回概率最高的一个。
让我们执行训练集准确性和测试集准确性。
...
pred = predict(Theta1, Theta2, X_train);
% Compare the prediction with the actual values
[val idx] = max(y_train, [], 2);
fprintf('\nTraining Set Accuracy: %f\n', mean(double(pred == idx)) * 100);...
pred = predict(Theta1, Theta2, X_test);
% Compare the prediction with the actual values
[val idx] = max(y_test, [], 2);
fprintf('\nTest Set Accuracy: %f\n', mean(double(pred == idx)) * 100);
我们得到的是
Training Set Accuracy: 100.000000%
Test Set Accuracy: 90.909091%
用 ML 模型预测
我还制作了一些额外的图片,并将它们放在 测试 文件夹中。它们代表完整的图像(未编辑),所以我可以测试神经网络模型的性能。我得到的是对他们四个人的预测。
pred = 2
Type: rightpred = 1
Type: leftpred = 3
Type: palmpred = 4
Type: peace
您可以用您的图像甚至您自己的训练图像来尝试这一点。只需将您的训练图像放在 数据集 文件夹下,并调用create _ image _ dataset . m文件来创建训练和测试矩阵。同样所有的 测试 图片都在 测试 文件夹下,你就可以调用 main.m 脚本了。
结论
恭喜你从零开始构建你的机器学习神经网络模型。希望这将有助于理解使用神经网络时的总体情况以及如何迈出第一步。如有任何问题或建议,请发表评论或联系我。
希望你喜欢它!
有用的链接
[## 统计/分布/制服- Wikibooks,开放世界的开放书籍
顾名思义,(连续)均匀分布是一种概率密度为……
en.wikibooks.org](https://en.wikibooks.org/wiki/Statistics/Distributions/Uniform#Variance) [## 神经网络中什么是好的初始权重?
我刚刚听说,从范围$(\frac{-1}中选择神经网络的初始权重是一个好主意…
stats.stackexchange.com](https://stats.stackexchange.com/questions/47590/what-are-good-initial-weights-in-a-neural-network#answer-297777) [## 一个逐步反向传播的例子
背景技术反向传播是训练神经网络的常用方法。网上不缺论文说…
mattmazur.com](https://mattmazur.com/2015/03/17/a-step-by-step-backpropagation-example/)
使用 Apache Spark 构建日志分析应用程序
使用 Apache Spark 开发真实世界应用程序的一步一步的过程,主要重点是解释 Spark 的体系结构。
如果我们有 Hadoop,为什么还要 Apache Spark 架构?
Hadoop 分布式文件系统(HDFS ),它以 Hadoop 原生格式存储文件,并在集群中并行化这些文件,同时应用 MapReduce 算法来实际并行处理数据。这里的问题是数据节点存储在磁盘上,处理必须在内存中进行。因此,我们需要进行大量的 I/O 操作来进行处理,而且网络传输操作会跨数据节点传输数据。这些操作总的来说可能会阻碍数据的快速处理。
Hadoop Map Reduce Algorithm (Left Image Source : researchgate.net)
如上图所述,数据块存储在磁盘上的数据记录中,地图操作或其他处理必须在 RAM 中进行。这需要来回的 I/O 操作,从而导致整体结果的延迟。
Apache Spark :官网描述为:“Apache Spark 是一个快速和通用集群计算系统”。
快 : Apache spark 很快,因为计算是在内存中进行并存储的。因此,没有 Hadoop 架构中讨论的 I/O 操作。
**通用:**是一个支持通用执行图的优化引擎。它还支持丰富的 SQL 和结构化数据处理, MLlib 用于机器学习, GraphX 用于图形处理,以及 Spark Streaming 用于实时数据处理。
Spark Architecture. Eg : Detect prime numbers
Spark 的入口点是 Spark 上下文,它处理执行者节点。Spark 的主要抽象数据结构是弹性分布式数据集(RDD),它代表了一个可以并行操作的不可变元素集合。
让我们讨论上面的例子来更好地理解:一个文件由数字组成,任务是从这个巨大的数字块中找到质数。如果我们把它们分成三块 B1,B2,B3。这些块是不可变的,由 spark 存储在内存中。这里,复制因子=2,因此我们可以看到,其他节点的副本存储在相应的其他分区中。这使得它具有容错体系结构。
步骤 1:使用 Spark 上下文创建 RDD
第二步:变换:当对这些 RDD 应用 map() 操作时,新的块,即 B4、B5、B6 被创建为新的 RDD,它们又是不可变的。这一切操作都发生在内存中。注:B1,B2,B3 仍然作为原来的存在。
第三步:动作:当 **collect(),**这个时候实际的结果被收集并返回。
懒评估 : Spark 不会马上评估每个转换,而是将它们批量放在一起,一次性评估全部。在其核心,它通过规划计算顺序和跳过潜在的不必要步骤来优化查询执行。主要优点:增加可管理性**,**节省计算并提高速度,降低复杂性,优化。
它是如何工作的?我们执行代码来创建 Spark 上下文,然后使用 sc 创建 RDD,然后使用 map 执行转换来创建新的 RDD。实际上,这些操作并不在后端执行,而是创建一个有向无环图(DAG)谱系。仅当执行动作时,即获取结果,例如: collect() 操作被调用,然后它引用 DAG 并向上爬以获取结果,参考该图,当向上爬时,它看到过滤器 RDD 尚未创建,它向上爬以获取上部结果,最后反向计算以获取精确结果。
RDD — **弹性:**即借助 RDD 谱系图容错。RDD 是其输入的确定性函数。这加上不变性也意味着 RDD 的部分可以在任何时候被重新创建。这使得缓存、共享和复制变得容易。
分布式:数据驻留在多个节点上。
**数据集:**代表你所处理的数据的记录。用户可以通过 JDBC 从外部加载数据集,数据集可以是 JSON 文件、CSV 文件、文本文件或数据库,没有特定的数据结构。
在文章的一部分,我们将使用 Apache Spark 的 pyspark 和 SQL 功能从头开始创建一个 Apache 访问日志分析应用程序。Python3 和 pyspark 的最新版本。数据来源:Apache access log
必备库
pip install pyspark
pip install matplotlib
pip install numpy
步骤 1:由于日志数据是非结构化的,我们从每一行解析并创建一个结构,在分析时,每一行又会变成每一行。
步骤 2:创建 Spark Context、SQL Context、DataFrame(是组织到命名列中的数据的分布式集合。它在概念上相当于关系数据库中的表)
步骤 3:分析以 MB 为单位传输最多内容的前 10 个端点
Top End Points with Maximum Content Flow
Response Code Analysis
Visitors(IP Address) which access the system most frequently
Traffic Analysis for Past One Week
Hour Level Traffic Analysis on Particular Day
Day Level Traffic Analysis
通过分析峰值以及哪些端点被哪些 IP 地址击中,可以清楚地检测出异常值。
Week Level Each Day Traffic Analysis
在这里,我们可以看到 3 月 8 日的一个不寻常的峰值,可以对其进行进一步分析,以确定差异。
地块分析代码:
End Points which are most Frequenty Hit
获取完整的应用代码:【https://github.com/ahujaraman/live_log_analyzer_spark
从头开始构建神经网络—第 2 部分
神经网络系列简介(GINNS)——第二部分
简介
在这篇文章中,我们将为 And 逻辑门构建一个感知机,这个模型我们将使用 python 和 numpy 从头开始构建。在这里,我假设你已经阅读了神经网络入门系列—第 1 部分,并且你已经熟悉了神经网络的基本概念。如果您不熟悉这个主题,我强烈建议您从第 1 部分开始。你还在吗?太好了,这篇文章将是我迄今为止写得最短的文章之一,我想在你建立良好的直觉和对神经网络的理解的同时保持事情的简单,所以让我们开始吧,但是首先,让我解释一下为什么从零开始建立一个超级虚拟神经网络为什么从零开始实现一个神经网络?
但是为什么要从头开始实现一个神经网络呢?我相信你真正想要的是创建强大的神经网络,可以预测你照片中的人是乔治·卢卡斯还是卢克·天行者?不要!,哦好吧,我不怪你。
现在,玩笑归玩笑。即使你计划在未来使用 Tensorflow、Keras 或另一个神经网络库,从头实现一个网络至少一次也是非常有价值的练习。它帮助你理解神经网络是如何工作的,这对设计有效的模型是必不可少的。所以,我希望我说服你留在这里。
单层神经网络(感知机)
感知器算法是最简单的人工神经网络类型,它的灵感来自于称为神经元的单个神经细胞的信息处理。
Perceptron
在感知器中,为了计算输出,我们将输入乘以各自的权重并与阈值进行比较,概括来说,输入的加权和通过一个阶跃/激活函数,如下所示:
Weighted sum passed to an activation function.
激活功能
给定一个输入或一组输入,节点的激活函数定义该节点的输出。一个标准的计算机芯片电路可以被看作是一个激活功能的数字网络,激活功能可以是“开”(1)或“关”(0),这取决于输入。在我们的示例中,我们将使用二元阶跃函数,如下所示:
step function
下面是代码!
Perceptron
- 负载输入(x)和输出(y)
- 初始化权重和其他参数:学习率是控制权重更新量的配置参数,**训练步骤(也称为历元)**是进行向前和向后传播的单个步骤。
- 计算输入(X)和权重矩阵(W)之间的点积,这里我们用 np.dot()做矩阵乘法,点积也叫内积,比如 X 和 W 之间的内积是 x1w1 + x2w2 + x3w3 + … + XnWn。
- 在 l1 上应用激活功能。l1 实际上是我们网络的输出。
- 当我们开始训练网络猜测预测时,计算模型产生的损失或错误,然后我们比较预测的类和真实的类。理想情况下,当我们训练神经网络时,我们想要的是找到最佳权重(W ),使我们的模型误差最小化。
- 计算变化因子,我们称之为更新,如果我们的模型正确地预测了类,误差等于零,并且权重没有变化,但是如果它出错,那么我们可以对权重进行负(减少)或正(增加)更新。
- 我们在 100 个训练步骤中训练我们的模型,并使用在线或随机学习,这意味着我们使用单个训练示例来进行参数更新。这里,单个训练示例是随机选取的。
培训后的输出:
y_pred after training
使用案例和限制
虽然感知器对我们示例中的实例进行了很好的分类,但该模型有局限性,实际上,感知器是一个线性模型,在大多数情况下,线性模型不足以学习有用的模式。
Left: And Gate, Right: Not and OR Logic Gates
像感知器这样的线性模型不是通用函数逼近器,如果您试图改变 XOR 逻辑门的问题,感知器会失败,因为 XOR 不具有线性可分性,如下图所示:
神经网络是众所周知的通用函数逼近器,那么我们遗漏了什么?这就是隐藏层的来源,也是我们接下来要讨论的内容。
下一步是什么?
我们将讨论隐藏层的力量和它们能够进行的处理,以及我们如何使用基于反向传播和梯度下降的算法来训练复杂的神经网络,如果你愿意更深入地研究神经网络的内部细节,请查看下面的链接,敬请关注!
参考资料:
- 神经网络和深度学习
- http://cs231n.github.io/neural-networks-1/
- 用 Python 从零开始实现神经网络——简介
- 在 Python 和 TensorFlow 中从头开始构建神经网络
- 用 Python 和 R 从零开始理解和编码神经网络
- 11 行 Python 中的神经网络(第 1 部分)
在你走之前!
如果你喜欢这些作品,请留下你的掌声👏推荐这篇文章,让别人也能看到。
大卫·福莫的《❤与 T4》。
愿原力与你同在!
使用探索性数据分析和熊猫围绕数据构建故事。数据科学的艺术部分。
探索性数据分析,简称 EDA,是赢得数据科学竞赛的秘方。EDA 是数据科学的创造性部分,是一个使用统计工具围绕数据编写的故事。EDA 还使科学家能够对数据进行隐喻性的考古挖掘,挖掘出任何潜在的见解。训练一个基本的机器学习算法只需要不到五行的代码。相比之下,EDA 和数据准备需要更长的时间,占数据科学家 80%的时间。
EDA 是什么? 简单来说,EDA 是一套在假设检验和实验之外探索和理解数据的统计方法。
使用 python 执行 EDA
使用 python 执行 EDA 非常容易,因为 python 有无数的统计分析包(如 numpy、pandas、matplotlib 等)。在 EDA 中主要进行三种分析,即:
单变量分析
双变量分析
多变量分析
我们将使用 python 逐步执行所有这三种类型的分析,并得出一些结论。从这里下载数据集,从这里下载完整代码。
使用 pandas 加载数据并检查数据框的维度。
reading Employee.csv file
单变量分析
一旦我们加载数据,我们就可以开始第一种 EDA,称为单变量分析。“Uni”表示一个,“Variate”表示变量,因此单变量分析表示对一个变量或一个特征的分析。单变量基本上告诉我们每个特征中的数据是如何分布的,还告诉我们中心趋势,如平均值、中值和众数。
描述性统计
连续特征
首先,检查集中趋势均值、中值和众数的度量,检查每个特征的最小值和最大值以及分位数。要做所有这些事情,我们只需使用 pandas 的“describe()”函数。
statistical description
从上表中,我们可以看到,员工的平均满意度仅为 61.12%,偏离了 24%,这意味着员工满意度之间存在很大差异,这直接影响了生产率。此外,我们可以看到 50%的员工同时从事 4 个不同的项目。这里的 50%分位数也称为中位数,我们使用中位数是因为中位数不会受到离群值的影响。其中平均值容易受到异常值的影响。
分类特征 分类变量中的描述性统计使用频率表和模式技术进行分析
frequency tables
从上图中,我们可以说几乎 48%的员工工资很低,只有 8%的员工工资很高。
可视化
直方图 在单变量分析中,我们使用直方图来分析和可视化频率分布。在熊猫身上绘制直方图非常简单明了。
从上图中,我们看到数据不是正态分布的,因此我们无法对这些数据执行许多统计操作。
箱线图 单变量分析中使用的第二个可视化工具是箱线图,这种类型的图形用于检测数据中的异常值。数据点超过三个标准偏差,通常称为异常值。离群值直接影响统计分析,因此我们必须首先检测它,然后从数据中删除(或修复)它。matplotlib 中的箱线图如下所示
box-plot for time spent in the company
从上图中,我们可以看到,有四名员工在公司花的时间比其他所有员工都多。所以这些员工的待遇与普通员工不同。因此,我们必须单独处理异常值。
离群值
使用中位数的整点是中位数不能受离群值的影响,这里均值容易受离群值的影响。有许多处理异常值的技术,其中一种技术采用三个标准差之间的所有数据。根据经验法则,几乎 99.97%的数据属于如下所示的三个标准差。
数据点位于称为异常值的三个标准偏差之上,因此我们采用三个标准偏差之间的数据来排除异常值。曲线下的面积称为 p 值,距离平均值的度量由标准差给出。
python function for removing outliers
该 python 函数将输入作为 pandas 数据框,并返回异常值和数据在三个标准差之间的数据框,该技术称为 3-sigma 技术。
现在 EDA 被称为数据科学的艺术部分,因为每个人都有不同的方法来查看数据并从中挖掘一些模式。我们用 python 做了很多 EDA。在接下来的博客中,我将向您展示如何用 python 执行推断统计。如果你喜欢这个博客,请喜欢并评论,直到那时快乐学习。
Connect with the Raven team on Telegram
使用 TensorFlow 构建您的第一个深度学习分类器:狗品种示例
Convoluted Neural Networks (like the one pictured above) are powerful tools for Image Classification
介绍
在本文中,我将向您介绍几种技术,帮助您迈出开发算法的第一步,该算法可用于经典的图像分类问题:从图像中检测狗的品种。
到本文结束时,我们将开发出代码,接受任何用户提供的图像作为输入,并返回对狗的品种的估计。此外,如果检测到人类,该算法将提供最相似的狗品种的估计。
1.什么是卷积神经网络?
卷积神经网络(也称为 CNN 或 ConvNet)是一类深度神经网络,已在许多计算机视觉和视觉图像应用中广泛采用。
一个著名的 CNN 应用案例在斯坦福大学研究小组的研究论文中有详细描述,他们在论文中展示了使用单一 CNN 对皮肤病变进行分类。仅使用像素和疾病标签作为输入,从图像中训练神经网络。
卷积神经网络由多层组成,与其他图像分类算法相比,它需要相对较少的预处理。
他们通过使用滤镜并将其应用于图像来学习。该算法采用一个小正方形(或“窗口”)并开始在图像上应用它。每个过滤器允许 CNN 识别图像中的特定模式。CNN 寻找图像中过滤器匹配图像内容的部分。
An example of a CNN Layer Architecture for Image Classification (source: https://bit.ly/2vwlegO)
网络的前几层可以检测简单的特征,如线、圆、边。在每一层中,随着我们越来越深入神经网络的各个层,网络能够结合这些发现,并不断学习更复杂的概念。
1.1 有哪几种层?
CNN 的整体架构由输入层、隐藏层和输出层组成。它们有几种类型的层,例如卷积层、激活层、汇集层、下降层、密集层和软最大层。
Neural Networks consist of an input layer, hidden layers, and an output layer (source: https://bit.ly/2Hxhjaw)
卷积层(或 Conv 层)是构成卷积神经网络的核心。Conv 层由一组滤镜组成。每个过滤器可以被认为是一个小正方形(具有固定的宽度和高度),其延伸通过输入体积的整个深度。
在每次通过时,过滤器在输入体积的宽度和高度上“卷积”。这个过程产生一个二维激活图,它给出了该滤波器在每个空间位置的响应。
为了避免过度拟合,池层用于在激活图上应用非线性缩减采样。换句话说,池层在丢弃信息方面很激进,但如果使用得当,也是有用的。在 CNN 架构中,一个池层通常跟随一个或两个 Conv 层。
Pooling layers are used to apply non-linear downsampling on activation maps (source: https://bit.ly/2Hxhjaw)
通过随机忽略某些激活函数,丢弃层也用于减少过拟合,而密集层是完全连接的层,通常位于神经网络的末端。
1.2 什么是激活功能?
使用激活函数处理层和神经网络的输出,激活函数是添加到隐藏层和输出层的节点。
你会经常发现 ReLu 激活函数用在隐藏层,而最终层通常由 SoftMax 激活函数组成。这个想法是,通过堆叠线性和非线性函数层,我们可以检测大范围的模式,并准确预测给定图像的标签。
SoftMax 通常位于最后一层,它基本上是一个归一化器,产生一个离散的概率分布向量,这对我们来说很好,因为 CNN 的输出是一个图像对应于特定类别的概率。
The most common activation functions include the ReLU and Sigmoid activation functions
当涉及到模型评估和性能评估时,选择损失函数。在用于图像分类的 CNN 中,通常选择类别交叉熵(简单地说:它对应于-log(error))。有几种方法可以使用梯度下降来最小化误差——在本文中,我们将依靠“ rmsprop ”,这是一种自适应学习率方法,作为一种以准确性为衡量标准的优化器。
2.设置算法的构建模块
为了构建我们的算法,我们将使用 TensorFlow 、 Keras (运行在 TensorFlow 之上的神经网络 API),以及 OpenCV (计算机视觉库)。
完成该项目时,训练和测试数据集也可用(参见 GitHub repo )。
2.1 检测图像是否包含人脸
为了检测提供的图像是否是人脸,我们将使用 OpenCV 的人脸检测算法。在使用任何面部检测器之前,标准程序是将图像转换为灰度。下面,detectMultiScale
函数执行face_cascade
中存储的分类器,并将灰度图像作为参数。
2.2 检测图像是否包含狗
为了检测所提供的图像是否包含一张狗的脸,我们将使用一个预训练的 ResNet-50 模型,该模型使用 ImageNet 数据集,该数据集可以将对象从 1000 个类别中分类。给定一个图像,这个预训练的 ResNet-50 模型返回图像中包含的对象的预测。
当使用 TensorFlow 作为后端时,KerasCNN 需要一个 4D 数组作为输入。下面的path_to_tensor
函数将彩色图像的字符串值文件路径作为输入,将其调整为 224x224 像素的正方形图像,并返回适合提供给 Keras CNN 的 4D 数组(称为“张量”)。
此外,所有预训练模型都有额外的归一化步骤,即必须从每个图像的每个像素中减去平均像素。这在导入函数preprocess_input
中实现。
如上面的代码所示,对于最终预测,我们通过获取预测概率向量的 argmax 来获得与模型的预测对象类别相对应的整数,我们可以通过使用 ImageNet 标签字典来识别对象类别。
3.使用迁移学习建立你的 CNN 分类器
现在我们有了在图像中检测人类和狗的功能,我们需要一种从图像中预测品种的方法。在这一节中,我们将创建一个对狗的品种进行分类的 CNN。
为了在不牺牲准确性的情况下减少训练时间,我们将使用转移学习来训练 CNN 这是一种允许我们使用在大型数据集上预先训练好的网络的方法。通过保留早期的层并仅训练新添加的层,我们能够利用通过预训练算法获得的知识并将其用于我们的应用。
Keras 包括几个预训练的深度学习模型,可用于预测、特征提取和微调。
3.1 模型架构
如前所述, ResNet-50 模型输出将成为我们的输入层——称为瓶颈特性。在下面的代码块中,我们通过运行以下代码来提取与训练、测试和验证集相对应的瓶颈特性。
我们将建立我们的模型体系结构,以便 ResNet-50 的最后一个卷积输出作为我们的模型的输入。我们只添加了一个全局平均池层和一个全连接层,其中后者包含每个狗类别的一个节点,并具有一个 Softmax 激活函数。
_________________________________________________________________ Layer (type) Output Shape Param # ================================================================= global_average_pooling2d_3 ( (None, 2048) 0 _________________________________________________________________ dense_3 (Dense) (None, 133) 272517 ================================================================= Total params: 272,517 Trainable params: 272,517 Non-trainable params: 0 _________________________________________________________________
正如我们在上面代码的输出中看到的,我们最终得到了一个有 272,517 个参数的神经网络!
3.2 编译和测试模型
现在,我们可以使用 CNN 来测试它在我们的狗图像测试数据集中识别品种的能力。为了微调模型,我们进行了 20 次迭代(或“时期”),其中模型的超参数被微调,以减少使用 RMS Prop 优化的损失函数(类别交叉熵)。
Test accuracy: 80.0239%
该算法提供了一个测试集,测试准确率为 80% 。一点都不差!
3.3 用模型预测犬种
现在我们有了算法,让我们编写一个函数,它以图像路径作为输入,并返回由我们的模型预测的狗的品种。
4.测试我们的 CNN 分类器
现在,我们可以编写一个函数,它接受一个图像的文件路径,并首先确定该图像是否包含一个人、一只狗,或者两者都不包含。
如果在图像中检测到一只狗,返回预测的品种。如果在图像中检测到一个人,返回相似的狗品种。如果图像中未检测到或,则提供指示错误的输出。
我们已经准备好测试这个算法了!让我们在一些样本图像上测试该算法:
这些预测在我看来很准确!
最后,我注意到该算法容易出错,除非它是一个清晰的正面拍摄,图像上的噪声最小。因此,我们需要使算法对噪声更加鲁棒。此外,我们可以用来改进我们的分类器的一种方法是图像增强,它允许您通过提供训练集中提供的图像的变体来“增强”您的数据。
在 5 分钟内建立自己的卷积神经网络
CNN 和代码介绍(Keras)
什么是卷积神经网络??
CNN
在回答什么是卷积神经网络之前,我相信你们都知道什么是神经网络。如果你基础不扎实,看看这个链接。继续前进。卷积神经网络类似于多层感知器网络。主要的区别是网络学习什么,它们是如何构造的,以及它们主要用于什么目的。卷积神经网络也受到生物过程的启发,它们的结构类似于动物的视觉皮层。CNN 广泛应用于计算机视觉领域,并在各种测试案例中取得了很好的效果。
隐藏层学到了什么??
CNN 中的隐藏层通常是卷积和汇集(缩减采样)层。在每个卷积层中,我们采用一个小尺寸的滤波器,并在图像中移动该滤波器,执行卷积运算。卷积运算只不过是滤波器值和图像中的像素之间的逐元素矩阵乘法,并将结果值相加。
Convolution operations
滤波器的值通过训练的迭代过程来调整,并且在神经网络已经训练了一定数量的时期之后,这些滤波器开始寻找图像中的各种特征。以使用卷积神经网络的面部检测为例。网络的早期层寻找简单的特征,例如不同方向的边等。随着我们在网络中的进展,这些层开始检测更复杂的特征,当你观察最终层检测到的特征时,它们几乎看起来像一张脸。
Different features recognised at different layers
现在,让我们继续池层。共用图层用于对图像进行缩减像素采样。图像将包含许多像素值,并且如果图像尺寸逐渐减小,网络通常很容易学习这些特征。池层有助于减少所需的参数数量,因此,这减少了所需的计算。合用也有助于避免过度拟合。有两种类型的池操作可以完成:
- 最大池化—选择最大值
- 平均池-将所有值相加,然后除以值的总数
很少使用平均池,您可以在大多数示例中找到最大池。
Max Pooling
密码
在我们开始编码之前,我想让你知道我们将使用的数据集是 MNIST 数字数据集,我们将使用 Keras 库和 Tensorflow 后端来构建模型。好了,够了。让我们做一些编码。
首先,让我们做一些必要的进口。keras 库帮助我们建立我们的卷积神经网络。我们通过 keras 下载 mnist 数据集。我们导入了一个顺序模型,这是一个预先构建的 keras 模型,您可以在其中添加层。我们导入卷积和池层。我们还导入密集层,因为它们用于预测标签。下降层减少过度拟合,展平层将三维向量扩展为一维向量。最后,我们为矩阵运算引入 numpy。
上面代码中的大部分语句都很琐碎,我只解释几行代码。我们重塑 x_train 和 x_test,因为我们的 CNN 只接受四维向量。值 60000 表示训练数据中的图像数量,28 表示图像大小,1 表示通道数量。如果图像是灰度图像,通道数设置为 1;如果图像是 RGB 格式,通道数设置为 3。我们还将目标值转换成二进制类矩阵。要知道二进制类矩阵是什么样子,请看下面的例子。
Y = 2 # the value 2 represents that the image has digit 2 Y = [0,0,1,0,0,0,0,0,0,0] # The 2nd position in the vector is made 1# Here, the class value is converted into a binary class matrix
我们构建了一个顺序模型,并添加了卷积层和最大池层。我们还在两者之间添加了 dropout 层,dropout 随机关闭网络中的一些神经元,迫使数据找到新的路径。因此,这减少了过度拟合。我们在末尾添加了密集层,用于类别预测(0–9)。
我们现在用分类交叉熵损失函数、Adadelta 优化器和准确性度量来编译该模型。然后,我们将数据集拟合到模型中,即我们针对 12 个时期训练模型。训练好模型后,我们在测试数据上评估模型的损耗和精度,并打印出来。
输出
结论
卷积神经网络确实有一些由杰弗里·辛顿指出的缺点。他认为,如果我们希望在计算机视觉领域达到人类水平的精确度,他的胶囊网络是必由之路。但是,到目前为止,CNN 似乎做得很好。如果你觉得这篇文章有用,请告诉我,谢谢:)
构建自己的 Python RESTful Web 服务
“An overhead shot of strawberry and blackberry pies next to a white coffee pot and a bunch of flowers” by Brooke Lark on Unsplash
在这篇博客中,我将解释我是如何创建一个 RESTful web 服务来充当数据工程服务的。web 服务是通过一个 Docker 容器中的 python web frameworkCherryPy提供的。以下是如何使用 3 个文件和不到 30 行代码实现这一目标的分步说明。
第一步是通过安装 Docker 、 Python 3 和以下 Python 库来设置开发环境:
- pandas——用于对数据集执行聚合
- CherryPy -服务于 web 服务的 web 框架
这些库可以使用 pip 命令安装:
>> pip install pandas
>> pip install CherryPy
让我们首先编写一个简单的数据处理器 myprocessor.py :
class MyProcessor: def run(self, df):
return df.agg(['mean', 'min', 'max'])
该处理器计算输入数据帧所有列的平均值、最小值和最大值。
在同一个目录中,我们创建一个 web 服务脚本 ws.py ,它包含请求处理程序的定义:
**import** cherrypy
**import** pandas **as** pd
**import** myprocessorp = myprocessor.MyProcessor()
**class MyWebService**(object):
@cherrypy.expose
@cherrypy.tools.json_out()
@cherrypy.tools.json_in()
**def process**(self):
data = cherrypy.request.json
df = pd.DataFrame(data)
output = p.run(df)
**return** output.to_json()**if** __name__ == '__main__':
...
该处理程序接受指向 /process 端点的请求,并期望输入数据在请求体中表示为 JSON 字符串。处理的结果将作为 JSON 字符串返回——使用 panda to_json() 方法方便地进行转换。
接下来是在 ws.py 的主要部分启动 web 服务的代码:
**if** __name__ == '__main__':
config = {'server.socket_host': '0.0.0.0'}
cherrypy.config.update(config)
cherrypy.quickstart(MyWebService())
myprocessor.py 和 ws.py 都是 web 服务所需要的。我们现在可以使用以下 python 命令启动 web 服务:
>> python ws.py
[24/Jul/2018:11:13:53] ENGINE Listening for SIGTERM.
[24/Jul/2018:11:13:53] ENGINE Listening for SIGHUP.
[24/Jul/2018:11:13:53] ENGINE Listening for SIGUSR1.
[24/Jul/2018:11:13:53] ENGINE Bus STARTING[24/Jul/2018:11:13:53] ENGINE Started monitor thread 'Autoreloader'.
[24/Jul/2018:11:13:53] ENGINE Started monitor thread '_TimeoutMonitor'.
[24/Jul/2018:11:13:53] ENGINE Serving on [http://0.0.0.0:8080](http://0.0.0.0:8080)
[24/Jul/2018:11:13:53] ENGINE Bus STARTED
哒哒!这里是我们的网络服务运行在任何时候。
在 Linux 系统中,我们可以使用 curl 发送这个 POST 请求来验证 REST API 是否正常工作:
>> curl -d '{"num1" : [1, 2, 3], "num2":[4, 5, 6]}' -H "Content-Type: application/json" -X POST [http://localhost:8080/process](http://localhost:8080/process)"{\"num1\":{\"mean\":2.0,\"min\":1.0,\"max\":3.0},\"num2\":{\"mean\":5.0,\"min\":4.0,\"max\":6.0}}"
预期结果是一个数据集,包括发送到 web 的两组数字的平均值、最小值和最大值。
码头集装箱
接下来,我们需要编写一个 Dockerfile — 这是一个文本文件,用于设置 web 服务将要运行的环境。如果你以前没有使用过 Docker,我建议至少阅读一下 Docker 入门文档,这样你就可以熟悉 Docker 的概念。文件中的第一行声明使用python:3 . 6 . 4-slim-Jessie作为基础映像:
from python:3.6.4-slim-jessie
这个是官方 Python Linux 映像之一,预装了 Python 3 的普通版本,还有许多其他映像可以从 Docker 存储库中选择,但这是一个精简版本,足以运行一个简单的服务。就像我们必须安装额外的 python 包来本地运行 web 服务一样,在构建 docker 映像时也需要这样做:
RUN pip install pandas
RUN pip install CherryPy
接下来,构建过程需要将 web 服务文件复制到默认的工作目录中:
COPY myprocessor.py .
COPY ws.py .
容器需要公开端口 8080 以允许访问:
EXPOSE 8080
docker 文件中的最后一条语句定义了容器启动时要运行的命令:
ENTRYPOINT ["python", "ws.py"]
这是完成的docker 文件的样子,它应该与之前编写的 python 脚本驻留在同一个目录中:
from python:3.6.4-slim-jessieRUN pip install pandas
RUN pip install CherryPy
COPY myprocessor.py .
COPY ws.py .
EXPOSE 8080
ENTRYPOINT ["python", "ws.py"]
为了执行 docker build 命令,我们停留在创建了 Dockerfile 的目录中。为 docker 映像分配一个标记是一个很好的做法,这个标记可以在以后引用,因此我们使用带有-t 标记的 build 命令来构建映像:
>> docker build -t python-ws .
我们现在已经准备好了一个 docker 图像,让我们试一试:
>> docker run -p 8080:8080 python-ws
该命令以附加模式启动容器,因此 Cherrypy 日志将立即出现在控制台中。同样,之前用于测试的相同 curl 命令也应该工作,因为主机(localhost)现在将定向到端口 8080 的请求转发到正在运行的 docker 容器。
我已经演示了如何构建一个简单的 RESTful web 服务,但是这个服务还远远不能用于生产。如果 web 服务托管在公共云中,应采取额外的安全措施,例如 HTTPS 连接、某种形式的身份验证。如何启用这些安全特性的示例代码可以在我的 GitHub 项目中找到。Cherrypy 教程页面提供了许多关于如何定制 web 服务的例子。
打造你自己的自动驾驶(玩具)汽车
如果你有兴趣建造自己的自动驾驶(玩具)汽车,并在此过程中学习一些人工智能概念,你应该留下来通读。
简短介绍
随着数据和计算能力的不断增加,深度学习的应用正在扰乱当今的许多行业。它的新战场之一是机器人技术。深度学习正在改变机器人在感知和控制领域的格局,这是自动驾驶汽车及其更广泛部署取得成功的关键。
深度学习工具的最新进展( TensorFlow 、 Keras 等)。)和廉价计算平台的可访问性( Raspberry Pi )使得机器人和人工智能的实验变得更加容易(而且有趣!)对于学术界和大型科技公司以外的人来说。
目标
我们将从 Udacity 自动驾驶汽车纳米度课程中获取我的行为克隆项目中描述的深度神经网络,并使用机器人操作系统( ROS )作为中间件在远程控制(RC)赛车上运行它。最终目标是让机器人能够自主完成赛道:
这只是这一领域许多近期项目中的一个,如果你在网上搜索的话,还有很多这样的项目。甚至还有比赛(最著名的一次在美国奥克兰举行),人们和这些机器人赛跑,试图打破人类最好的时间。
我的项目可能与其他项目不同的是,它使用 ROS 作为软件栈和金属之间的连接层。
这个项目是一个很好的例子,展示了深度学习如何用于端到端地训练汽车自动驾驶,并使用人工智能解决机器人的感知和控制挑战。
我如何建立一个?
让我们首先来看一下硬件,以便让您入门:
由于我的硬件构建是基于驴车,你可以在这里获得关于硬件组装的更详细说明。你会注意到,当谈到选择你的遥控车有很多选择。在这个项目的第一次迭代中,我选择了 Elegoo 机器人汽车套件,结果证明这不是一个好主意,因为该套件没有用于控制转向角度的专用伺服系统。这使得对你的神经网络建模以及之后与自动驾驶仪的集成变得更加困难。有了磁铁,你可以更好的控制遥控车。
软件呢?
如果你很急,你也可以从驴车拿软件栈。我走了另一条路,试图通过观察驴车项目并从我以前的 Udacity 项目中吸取经验来自己构建大脑。我喜欢理查德·费曼在这个话题上的一句名言:
我无法创造的东西,我不明白。知道如何解决每一个已经解决的问题。
正如我已经提到的,我决定选择机器人操作系统(ROS)作为基于深度学习的自动驾驶仪和硬件之间的中间件。这是一个陡峭的学习曲线,但就该项目的完整代码库的大小而言,它最终完全得到了回报。
ROS 提供了强大的发布者/订阅者模型,对每个组件(摄像机、转向和油门控制、操纵杆等)的分布式节点支持。).它还具有强大的调试和日志记录功能。如果你是 ROS 新手,我强烈推荐这本书,它通过有趣的项目教你基础知识。
在我的例子中,我在车上运行了摄像机和执行器(转向和油门)节点。操纵杆、自动驾驶和训练节点正在我的台式机上运行。推理(神经网络预测)是计算密集型,所以必须将它从 Raspberry Pi 转移到更强大的机器上。
记住,你需要 Ubuntu Mate 发行版才能在你的 Raspberry Pi 上运行 ROS。这里还有一个链接用于 ROS 节点摄像头支持。
AI 呢?
汽车的自动驾驶基于现在著名的 NVIDIA 的论文,该论文使用卷积神经网络 (CNN)来预测汽车的转向角度,仅基于安装在汽车前面的摄像头的图像输入。你可以在我之前的文章中读到更多关于这个话题的内容。我最近偶然发现了这篇论文,这篇论文探索了针对同一问题的一些其他深度神经网络架构。你应该去看看!
与我之前的 Udacity 项目相比,我必须为 CNN 做的一项调整是引入宁滨数据。在以下情况下,您应该考虑使用它:
一列连续数字有太多的唯一值,无法有效地建模,因此您可以自动或手动将这些值分配给组,以创建一组较小的离散范围。
在这种情况下,连续数字列是来自操纵杆的汽车转向角度。我发现这个修改改进了我的模型预测。另一方面,油门目前是固定的,这也是我想使用预测方法的事情。
结论
参与这个项目是了解 ROS 的一个很好的方式(好处和挑战)。事实证明,ROS 被几家自主汽车/小型巴士公司用作原型平台和/或投入生产。
此外,当你把你的神经网络从模拟器中拿出来放在一辆“真正的”汽车上时,在硬件上工作可以揭示一些问题。
您在自己的机器人车上运行 ROS 节点所需的所有代码都可以在我的项目报告中找到,同时还有助手脚本:
自动驾驶机器人汽车基于 Raspberry Pi 和 Arduino 的机器人汽车,能够基于深度…
github.com](https://github.com/bdjukic/selfdriving-robot-car)
如果你住在柏林,请务必参加即将于 7 月 29 日举行的机器人比赛:
加入我们在海拉风险投资公司举办的柏林自动驾驶汽车和自动驾驶活动的黑客/比赛日。种族…
www.meetup.com](https://www.meetup.com/Berlin-Self-Driving-Cars-Autonomous-Mobility/events/238595677/)
第一次构建回大学/学校预算计算机
从零开始建造一台计算机是我长久以来的一个梦想,但是我很担心,因为我缺乏计算机硬件方面的知识。相反,我经常最终购买笔记本电脑,但这些很快就会过时,不再适合我的数据科学需求。这是关于你自己建造一台计算机的最好的部分;你才是决定计算机到底是用来做什么的人!
这篇文章概述了我决定使用哪些组件,如何将它们组合在一起,以及如何在确保一切正常的情况下削减成本的过程。在此版本中,许多商品的购买价格为其建议零售价的 50% — 70% **,如下表所示,**没有性能问题。
我需要什么来开始?
耐心,而且是大量的耐心!
当然,如果费用对你来说不是一个很大的问题,那么你可以直接订购许多商品,并在几天内全部拿到。然而,如果你想要最好的交易,可能需要一段时间的网上竞价或清仓甩卖,但坚持不懈往往会得到回报。给一个总的想法,我的构建从开始到结束花了 3 到 4 周,这包括一些邮费上的延迟。
做你的研究!
有许多组件可用,但并非所有组件都兼容或最佳。这可能是压倒性的第一,因为有数百个,如果不是数千个电脑组件,它很容易丢失。然而,有一些惊人的资源可以帮助我们,并在下一节中更详细地讨论它们。
有计划,坚持!
当搜索组件时,确切地知道你要的是什么版本是有帮助的,而不是仅仅被现有的所吸引。
就是这样!
除了一些工具和一些方便的工作之外,您将准备好构建自己的工具。有些构建可能有点棘手,但这对我来说肯定不正常,组件手册将是你最好的指南。
我在哪里可以找到关于我的构建的帮助?
PC Part Picker 对于寻找兼容部件非常有用,建议您详细阅读评论,了解每个组件的优点和缺点:
[## 挑选零件。构建您的 PC。对比分享。— PCPartPicker 英国
构建您自己的 PC 并需要从哪里开始的想法?浏览我们的构建指南,其中涵盖了适用于所有人的系统…
uk.pcpartpicker.com](https://uk.pcpartpicker.com/)
有大量的书面指南,许多组件包含的说明通常有助于构建方面,但我发现 YouTube 是一个惊人的资源,许多创作者提供了关于构建计算机的详细建议,我将列出一些我最喜欢的:
OzTalksHW
Oz 为所有规格的预算构建提供了一个很好的来源,如果你愿意冒险,它展示了直接从中国进口的最便宜的组件。
RandomGamingHD
另一位 budget build 创建者经常测试仍然可用且功能正常的旧组件的性能,甚至在他的本地转储中保存旧显卡以免被销毁。
克里斯多福莉娅
有趣的是,一个最初是业余电影制作人的 YouTuber 用户找到了自己的位置,他展示个人电脑的组装,呼吁卖家在二手市场上定价过高,并展示,如果运气好的话,你可以买到二手物品的交易。
这些是我使用的主要渠道,但还有更多,你经常可以找到针对你的构建甚至特定组件的视频。
我想要我的电脑做什么?
这完全取决于你,但就我的目的而言,我想要符合以下标准(按重要性排序)的东西:
- 强大到足以运行数据科学模型
- 尽可能便宜
- 安静且低功耗,因此可以整夜运行
- 微妙的美学和运输相当容易
- 未来可升级
你自己的需求会有所不同,但我想要一些东西,可以在一夜之间运行我的一些机器学习模型,但我不能花一大笔钱这样做。因此,在构建时考虑了项目成本和运行机器的电费。
功耗可能是你甚至没有想过的事情,但是,当你考虑到许多家庭比特币采矿爱好者正在因为运行他们的机器的成本超过他们是我的成本而却步时,如果你正在买单,这可能值得考虑。
一旦你决定了什么对你的构建是重要的,那么你就可以开始考虑哪些组件是最好的。为了符合我的标准,我决定尽可能选择最小的版本,它目前足够强大,如果需要的话,以后可以很容易升级,而且成本效益高。
需要哪些组件?
与你可能认为的相反,如今制造一台计算机非常简单,而且经常被比作将乐高积木拼在一起。我很惊讶这个过程是如此的简单,甚至没有任何经验的人也能做到。
要创建一台完整的计算机,您需要以下部件:
-处理器(称为 CPU)和冷却器
-图形卡(称为 GPU)
-主板
-内存(也称为 RAM)
-存储(称为硬盘)
-凯斯
-电源(被称为 PSU)
我应该买哪些组件?
处理器和显卡
我的构建围绕着 AMD 的新锐龙处理器。这些不仅是英特尔系列的一个很好的预算选择,而且他们还发布了两个也有集成显卡的处理器;锐龙 3 2200 克和锐龙 5 2400 克。这意味着他们根本不需要显卡就可以运行游戏并达到中端显卡的性能!
因此,我能够从构建中完全排除对独立显卡的需求,从而降低至少 150 英镑的成本。当然,这永远无法满足一个独立处理器和一个高端显卡组合的全部性能,但如果达到最大图形性能不是一个优先事项,并且对于一些游戏来说已经足够了,这是一个很好的预算解决方案。
外壳和电源
CPU 和 GPU 都包括在内,然后我考虑我想要的美学。我认为一个小而有吸引力的案例很重要,并把重点放在了作为完美解决方案的 分形节点 202 上。这种外壳不仅很小(大约是 PS4 或 Xbox One 的大小),而且还带有内置电源单元。然而,在选择这个案例时,我需要考虑一些重要的挑战:
-所提供的电源在功率输出、效率和安全性方面是否足够好?
-这会导致我的其他组件出现兼容性问题吗?
首先,机箱的电源提供 450 瓦的功率,因为我们没有单独的显卡,这足以为组件供电。你可以用 这个计算器 检查你的体型,我的体型被计算出大约 200W,用显卡更接近 400W。电源也通过了青铜认证,这基本上确保了它为计算机提供能量的效率相当高,并且不会作为热量浪费掉,这有利于降低能源成本。这也提供了一些安全保证,有一些更便宜的情况下,也包括电源可用,但没有认证,这是一个风险,可能会损坏您的电脑和家用电器。
母板
有了这些决定,然后我必须找到一个兼容的主板。这是最棘手的部分,也是由于选择有限,我最终以全价购买的唯一主要组件。因为机箱的大小,我被迫需要最小的主板,被称为迷你 ITX。此外,由于 AMD 的处理器作为 CPU 和 GPU 的功能是新的,只有一定范围的最新主板开箱即用。因此,我决定购买微星的新 B450I 迷你 ITX 主板,内置 Wi-Fi 和蓝牙。
这种购买感觉像是一个巨大的风险,因为在制作这种产品的日期没有对该产品的评论,但我能够找到几个早期测试 YouTube 视频,证实它应该与处理器兼容,所以我决定值得冒这个风险,因为它比任何替代品便宜近 100 英镑。
内存储器
有了这个主板,我就被要求购买一种通常用于笔记本电脑的 M.2 存储类型。我强烈推荐使用 SSD 存储设备作为主系统,一个很好的总结可以在这里找到但是总之 SSD 运行得更快。如果您需要更多存储空间,您可以随时添加大容量硬盘驱动器,但使用固态硬盘作为您的主要设备将缩短启动时间,甚至缩短 windows 中的文件加载时间。我能够在易贝上购买一个 250GB 的三星 960 evo SSD,对于操作系统和基本使用来说,这已经足够大了。
记忆
然后,我不得不购买一些内存(或 RAM ),并再次需要检查兼容性。理解 RAM 可能有点棘手,但我会尽力总结我的发现。
RAM 有三个质量衡量标准,第一个是 DDR2、DDR3 和 DDR4(https://en.wikipedia.org/wiki/DDR_SDRAM)类别,为了与我的主板配合工作,我需要 DDR 4 类型。
第二个衡量标准是由 MHz 数量表示的内存速度,因为我们使用 AMD 的锐龙 5 2400g 处理器,所以建议使用 至少 3000MHz 的两个棒以获得理想的性能 。
最后,我需要在 8GB、16GB 或 32GB 之间决定所需的内存量。由于 ram 目前很贵,我决定 8GB 对我来说应该足够了,如果需要,以后可以很容易地升级。
冷却
最后,您需要考虑如何确保所有组件都保持冷却并且不会过热。因为这个版本不包括图形卡,所以事情变得简单了一些,但是处理器冷却非常重要。AMD 的锐龙 5 2400g 配备了一个股票风扇包括这是伟大的预算建设,但因为我的情况是如此之薄,这不太可能适合。因此,我决定购买一个 更薄的风扇单元 ,其中包括导热膏,足以让我的组件保持良好的温度。
下图显示了组装前的所有组件:
很难建议您想要购买哪些物品,因为您需要仔细考虑您的需求以及您需要哪些组件。然而,我希望这能让我对我的构建过程有所了解,从而对你有所帮助。
我的建议是决定你需要的一两个组件,例如最快的处理器、最好的显卡或有吸引力的外壳,然后以此为起点寻找其他兼容的组件。如前所述,PC Part Picker 在建议哪些组件适合您的构建方面做得非常出色,评论甚至提供了更多建议。
我怎样才能省钱?
我能够以零售价的 50%-70%在易贝和清仓甩卖上竞价购买我的许多部件。这比简单地购买新的花费更长的时间,但是只要有一点耐心和明智的选择,你就能以低于零售价的价格买到所需的大部分(如果不是全部)部件。
我从 CeX(一家英国零售店)购买了机箱、易贝的 SSD M.2 硬盘和 RAM 以及 AMD 锐龙处理器。不幸的是,如前所述,由于产品太新,主板必须以全价购买。
最终价格汇总如下:
总的来说,我的构建成本约为 470 英镑,通过谨慎购买,我在组件上节省了 200 至 250 英镑。此外,我不仅能够通过一些运气在 AMD 处理器上获得一笔惊人的交易,而且我还通过首先不需要构建显卡至少节省了 250 英镑(英伟达 RTX 1060 6GB)。
购买处理器是有风险的,因为该产品在网上的描述中几乎没有任何信息,并认为这可能是一个错误。然而,处理器来了,工作完美,虽然它没有任何包装或股票冷却器风扇,但这不是一个问题,我的建设,因为股票风扇不会适合的情况下,无论如何。
如果我决定不把它放进这么小的盒子里,成本可能会进一步降低,但它仍然比任何笔记本电脑替代品、类似性能的预建配置甚至新手机都要便宜得多,我对自己能够找到的交易感到惊讶。
如何将这些组件组合在一起?
现在你有了所有的部分,你需要把它们拼在一起,而且通常会按照一定的顺序排列,这样它们才能正确的组合。对齐取决于您购买的产品和构建的类型,但主板和机箱可能应该有一个过程的良好描述。另外,我在网上找到了我正在处理的案件的视频,以确保我的过程是正确的。
对于我的构建,过程如下:
1.将 CPU 安装到主板上,
2.使用导热膏,连接 CPU 风扇并插入主板
3.安装 M.2 固态硬盘
4.安装内存
5.将主板(带端口导轨)放入机箱内
6.将电源线连接到指定的主板插座
除了一些棘手的对齐问题,我发现最后一步是最难的。大多数电缆匹配是显而易见的,但我花了一段时间来找出从外壳的前面电源开关连接电缆的地方,但能够很容易地在网上找到解决方案,并使用主板手册。此外,请确保在连接电源和用电器工作时要小心,你最不希望的就是意外触电!
我应该安装哪个操作系统?
为了方便使用,我最终安装了 windows 10,这可能很贵,但我能在易贝上找到一个便宜的激活密钥。第一次安装时,我按照以下指南从 u 盘运行 window 的安装程序:
http://www . toms guide . com/FAQ/id-3694993/create-bootable-USB-installer-windows . html
如果你真的预算紧张,那么 Linux 是一个很好的选择,它完全免费,并且有一些令人惊讶的界面。如果你愿意接受挑战,你甚至可以在电脑上安装 Mac IOS 来创建一个“黑客电脑”,但这不是我感兴趣的事情。
最终想法
我从组装电脑和在线竞标组件中获得了很多乐趣。这花了一些时间,但值得耐心,并强烈建议任何有兴趣升级其硬件的人这样做,并希望您发现这对您自己的构建想法有用。
与任何网上投标一样,在寻找好的交易时要耐心和小心,以确保你没有买到描述不佳、不起作用的产品。此外,请确保您研究了哪些组件是兼容的,并在头脑中为您想要的构建类型保持一个明确的目标。
最后,你可能要考虑市场价格。例如,我选择避免使用显卡,因为价格处于历史高位,Nvidia 的最新产品系列将很快发布,因此旧产品的价格可能会下降。如果我有耐心,我可以等待主板价格下跌,甚至拯救自己,但这是一个权衡,你将不得不决定自己的建设。
谢谢
哲学(philosophy 的缩写)
构建贝叶斯深度学习分类器
在这篇博客文章中,我将教你如何使用 Keras 和 tensorflow 来训练贝叶斯深度学习分类器。在深入具体的培训示例之前,我将介绍几个重要的高级概念:
- 贝叶斯深度学习是什么?
- 什么是不确定性?
- 为什么不确定性很重要?
然后,我将介绍两种在深度学习模型中包含不确定性的技术,并查看一个使用 Keras 在 cifar10 数据集上的冻结 ResNet50 编码器上训练完全连接的层的具体示例。通过这个例子,我还将讨论探索贝叶斯深度学习分类器的不确定性预测的方法,并提供未来改进模型的建议。
感谢
这篇文章基于两篇博客文章(这里和这里)和剑桥大学机器学习小组关于贝叶斯深度学习的白皮书。如果你在读完这篇文章后想了解更多关于贝叶斯深度学习的知识,我鼓励你查看所有这三个资源。感谢剑桥大学机器学习小组令人惊叹的博文和论文。
贝叶斯深度学习是什么?
Visualizing a Bayesian deep learning model.
贝叶斯统计是统计领域中的一种理论,其中关于世界真实状态的证据是用信任度来表示的。贝叶斯统计和深度学习在实践中的结合意味着在你的深度学习模型预测中包含不确定性。早在 1991 就提出了在神经网络中包含不确定性的想法。简而言之,贝叶斯深度学习在典型神经网络模型中发现的每个权重和偏差参数上添加了先验分布。在过去,贝叶斯深度学习模型并不经常使用,因为它们需要更多的参数来优化,这可能使模型难以工作。然而,最近,贝叶斯深度学习变得更加流行,新技术正在开发中,以在模型中包括不确定性,同时使用与传统模型相同数量的参数。
什么是不确定性?
An example of ambiguity. What should the model predict?
不确定性是一种知识有限的状态,无法准确描述现有状态、未来结果或一个以上的可能结果。当它涉及深度学习和分类时,不确定性也包括模糊性;人类定义和概念的不确定性,不是自然界的客观事实。
不确定性的类型
有几种不同类型的不确定性,在这篇文章中我将只讨论两种重要的不确定性。
任意不确定性
随机不确定性衡量的是你无法从数据中理解的东西。它可以用观察所有解释变量的能力来解释。把随机不确定性想象成感知不确定性。实际上有两种类型的随机不确定性,异方差和同方差,但是我在这篇文章中只讨论异方差不确定性。在的这篇博客文章中,对同性恋进行了更深入的探讨。
立体图像中任意不确定性的具体例子有遮挡(相机看不到的场景部分)、缺乏视觉特征(如空白墙壁)或曝光过度/不足区域(眩光和阴影)。
Examples of occlusions, lack of visual features and under/over exposure.
认知不确定性
认知不确定性衡量的是由于缺乏训练数据,模型不知道什么。它可以用无限的训练数据来解释。将认知不确定性视为模型不确定性。
观察认知不确定性的一个简单方法是在 25%的数据集上训练一个模型,在整个数据集上训练第二个模型。仅在 25%的数据集上训练的模型将比在整个数据集上训练的模型具有更高的平均认知不确定性,因为它看到的例子更少。
一个有趣的认知不确定性的例子在现在著名的非热狗应用中被发现。从我自己使用该应用程序的经验来看,该模型表现非常好。但仔细观察后发现,这个网络似乎从未被训练过“不是热狗”的图片,这些图片中的物品上有番茄酱。因此,如果给模特看一张你腿上沾有番茄酱的照片,模特会被骗以为那是热狗。贝叶斯深度学习模型将预测这些情况下的高度认知不确定性。
为什么不确定性很重要?
在机器学习中,我们试图创建真实世界的近似表示。今天创建的流行深度学习模型产生点估计,但不是不确定性值。了解您的模型是过于自信还是过于自信有助于您对模型和数据集进行推理。上面解释的两种不确定性是重要的,原因各不相同。
注意:在分类问题中,softmax 输出为每个类别提供了一个概率值,但这与不确定性不同。softmax 概率是一个输入相对于其他类成为给定类的概率。因为概率是相对于其他类的,所以它无助于解释模型的总体置信度。
为什么任意不确定性很重要?
Even for a human, driving with glare is difficult
在观察空间的一部分比其他部分具有更高噪声水平的情况下,随机不确定性是很重要的。例如,任意的不确定性在第一起涉及无人驾驶汽车的死亡事故中发挥了作用。特斯拉表示,在这起事件中,汽车的自动驾驶仪未能识别明亮天空下的白色卡车。能够预测任意不确定性的图像分割分类器将认识到图像的这个特定区域难以解释,并预测高度不确定性。在特斯拉事件中,尽管汽车的雷达可以“看到”卡车,但雷达数据与图像分类器数据不一致,汽车的路径规划器最终忽略了雷达数据(已知雷达数据有噪声)。如果图像分类器在其预测中包含高度不确定性,则路径规划者将会知道忽略图像分类器预测,而使用雷达数据(这过于简单,但实际上将会发生。参见下面的卡尔曼滤波器)。
为什么认知不确定性很重要?
认知不确定性很重要,因为它识别模型从未被训练理解的情况,因为这些情况不在训练数据中。机器学习工程师希望我们的模型能够很好地概括与训练数据不同的情况;然而,在深度学习的安全关键应用中,希望是不够的。高认知不确定性是一个危险信号,表明模型更有可能做出不准确的预测,当这种情况发生在安全关键应用中时,该模型不应被信任。
认知的不确定性也有助于探索你的数据集。例如,认知的不确定性可能有助于 20 世纪 80 年代发生的这个特定的神经网络灾难。在这种情况下,研究人员训练了一个神经网络来识别隐藏在树中的坦克和没有坦克的树。经过训练后,网络在训练集和测试集上表现得非常好。唯一的问题是,所有坦克的图像都是在阴天拍摄的,所有没有坦克的图像都是在晴天拍摄的。这个分类器实际上已经学会了辨别晴天和阴天。哎呦。
Tank & cloudy vs no tank & sunny
Radar and lidar data merged into the Kalman filter. Image data could be incorporated as well.
深度学习模型中的不确定性预测在机器人技术中也很重要。我目前就读于 Udacity 自动驾驶汽车纳米学位,并一直在学习汽车/机器人用于识别和跟踪物体的技术。自动驾驶汽车使用一种叫做卡尔曼滤波器的强大技术来追踪物体。卡尔曼滤波器组合一系列包含统计噪声的测量数据,并产生比任何单个测量更精确的估计。传统的深度学习模型无法对卡尔曼滤波器做出贡献,因为它们只预测结果,不包括不确定项。理论上,贝叶斯深度学习模型可以有助于卡尔曼滤波器跟踪。
计算深度学习分类模型中的不确定性
任意不确定性和认知不确定性是不同的,因此,它们的计算方式也不同。
计算任意不确定性
任意不确定性是输入数据的函数。因此,深度学习模型可以通过使用修改的损失函数来学习预测任意的不确定性。对于分类任务,贝叶斯深度学习模型将有两个输出,softmax 值和输入方差,而不是仅预测 softmax 值。教导模型预测任意方差是无监督学习的一个示例,因为模型没有方差标签可供学习。下面是标准分类交叉熵损失函数和计算贝叶斯分类交叉熵损失的函数。
我创建的损失函数是基于这篇论文中的损失函数。在本文中,损失函数创建了一个均值为零的正态分布和预测方差。它通过从分布中采样来扭曲预测的 logit 值,并使用扭曲的预测来计算 softmax 分类交叉熵。损失函数运行 T 个蒙特卡罗样本,然后取 T 个样本的平均值作为损失。
Figure 1: Softmax categorical cross entropy vs. logit difference for binary classification
在图 1 中,y 轴是 softmax 分类交叉熵。x 轴是“正确的”logit 值和“错误的”logit 值之间的差值。“右”表示该预测的正确类别。“错误”表示该预测的错误类别。我将使用术语“logit difference”来表示图 1 中的 x 轴。当“logit difference”在图 1 中为正时,softmax 预测将是正确的。当“logit difference”为负时,预测将是不正确的。在解释任意损失函数时,我将继续使用术语“逻辑差”、“正确的”逻辑和“错误的”逻辑。
图 1 有助于理解正态分布失真的结果。当使用正态分布对 logit 值(在二元分类中)进行扭曲时,这种扭曲实际上创建了一个正态分布,其原始预测“logit 差异”和预测方差的平均值作为分布方差。将 softmax 交叉熵应用于失真的 logit 值与沿着图 1 中的线对“logit 差异”值进行采样是相同的。
对扭曲的逻辑取分类交叉熵应该理想地产生一些有趣的性质。
- 当预测的 logit 值远大于任何其他 logit 值时(图 1 的右半部分),增加方差只会增加损失。这是真的,因为导数在图的右半部分是负的。即,与“logit difference”的相等减少相比,增加“logit difference”仅导致 softmax 分类交叉熵的稍微更小的减少。在这种情况下,最小损耗应该接近于 0。
- 当“错误的”logit 远大于“正确的”logit(图的左半部分)且方差为~0 时,损失应为~
wrong_logit-right_logit
。你可以看到这在图 1 的右半部分。当“logit 差”为-4 时,softmax 交叉熵为 4。图中这一部分的斜率为~ -1,因此随着“logit 差异”继续减小,这应该是正确的。 - 为了使模型能够学习任意的不确定性,当“错误的”logit 值大于“正确的”logit 值(图的左半部分)时,对于大于 0 的方差值,损失函数应该最小化。对于具有高度随机不确定性的图像(即,模型很难对该图像做出准确预测),该特征鼓励模型通过增加其预测方差来在训练期间找到局部损失最小值。
当“错误的”logit 值大于“正确的”logit 值时,我能够使用论文中建议的损失函数通过增加方差来减少损失,但是由于增加方差而减少的损失非常小(<0.1). During training, my model had a hard time picking up on this slight local minimum and the aleatoric variance predictions from my model did not make sense. I believe this happens because the slope of Figure 1 on the left half of the graph is ~ -1. Sampling a normal distribution along a line with a slope of -1 will result in another normal distribution and the mean will be about the same as it was before but what we want is for the mean of the T samples to decrease as the variance increases.
To make the model easier to train, I wanted to create a more significant loss change as the variance increases. Just like in the paper, my loss function above distorts the logits for T Monte Carlo samples using a normal distribution with a mean of 0 and the predicted variance and then computes the categorical cross entropy for each sample. To get a more significant loss change as the variance increases, the loss function needed to weight the Monte Carlo samples where the loss decreased more than the samples where the loss increased. My solution is to use the elu 激活函数,这是一个以 0 为中心的非线性函数)。
ELU activation function
我将 elu 函数应用于分类交叉熵的变化,即原始未失真损失与失真损失的比较,undistorted_loss - distorted_loss
。对于图 1 的左半部分,elu 将正态分布的平均值从零移开。对于接近 0 的非常小的值,elu 也是线性的,因此图 1 右半部分的平均值保持不变。
Figure 2: Average change in loss & distorted average change in loss.
在图 2 中,right < wrong
对应于图 1 左半部分的一个点,而wrong < right
对应于图 2 右半部分的一个点。您可以看到,“错误”logit 情况下的结果分布看起来类似于正态分布,而“正确”情况下的结果大多是接近零的小值。将-elu
应用于损失变化后,right < wrong
的均值变得更大。在本例中,它从-0.16 变为 0.25。wrong < right
的意思保持不变。我将图 2 中下方图表的平均值称为“失真的平均损失变化”。随着图 1 右半部分方差的增加,“失真平均损耗变化”应保持在 0 附近,并且当图 1 右半部分方差增加时,应始终增加。
然后,我用原始未失真的分类交叉熵来衡量“失真的平均损失变化”。这样做是因为对于所有大于 3 的 logit 差异,错误 logit 情况下的失真平均损失变化大致相同(因为线的导数为 0)。为了确保损失大于零,我添加了未失真的分类交叉熵。“损失的扭曲平均变化”总是随着方差的增加而减少,但是对于小于无穷大的方差值,损失函数应该最小化。为了确保最小化损失的方差小于无穷大,我添加了方差项的指数。如图 3 所示,方差的指数是方差超过 2 后的主要特征。
Figure 3: Aleatoric variance vs loss for different ‘wrong’ logit values
Figure 4: Minimum aleatoric variance and minimum loss for different ‘wrong’ logit values
这些是针对二元分类示例计算上述损失函数的结果,在该示例中,“正确”的 logit 值保持为常数 1.0,而“错误”的 logit 值会针对每一行发生变化。当“错误的”logit 值小于 1.0(因此小于“正确的”logit 值)时,最小方差为 0.0。随着错误的“logit”值增加,使损失最小化的方差也增加。
注意:在生成此图时,我运行了 10,000 次蒙特卡洛模拟来创建平滑的线条。在训练模型时,我只运行了 100 次蒙特卡洛模拟,因为这应该足以得到一个合理的平均值。
Brain overload? Grab a time appropriate beverage before continuing.
计算认知不确定性
对认知不确定性建模的一种方式是在测试时使用蒙特卡罗抽样(一种变分推理)。关于为什么辍学可以模拟不确定性的完整解释,请查看这篇博客和这篇白皮书。实际上,蒙特卡洛漏失抽样意味着将漏失包括在模型中,并在测试时打开漏失多次运行模型,以创建结果分布。然后可以计算预测熵(预测分布中包含的平均信息量)。
为了理解如何使用 dropout 来计算认知不确定性,可以考虑将上面的猫狗图像垂直分成两半。
如果你看到左半部分,你会预测狗。如果你看到右半边,你会预测猫。完美的五五分成。这个图像会有很高的认知不确定性,因为这个图像展示了你同时与猫类和狗类相关联的特征。
下面是计算认知不确定性的两种方法。它们做完全相同的事情,但是第一个更简单,只使用 numpy。第二种使用额外的 Keras 层(并获得 GPU 加速)来进行预测。
注意:认知不确定性不用于训练模型。当评估测试/真实世界的例子时,它仅在测试时间(但是在训练阶段)被计算。这不同于随机的不确定性,随机的不确定性是作为训练过程的一部分被预测的。此外,根据我的经验,产生合理的认知不确定性预测比随机不确定性预测更容易。
训练贝叶斯深度学习分类器
除了上面的代码之外,训练贝叶斯深度学习分类器来预测不确定性不需要比通常用于训练分类器更多的代码。
在这个实验中,我使用 Resnet50 中的冻结卷积层和 ImageNet 的权重来编码图像。我最初试图在不冻结卷积层的情况下训练模型,但发现模型很快变得过度拟合。
我的模型的可训练部分是 ResNet50 输出之上的两组BatchNormalization
、Dropout
、Dense
和relu
层。使用单独的Dense
层计算逻辑值和方差。注意,方差层应用了一个softplus
激活函数来确保模型总是预测大于零的方差值。然后,针对任意损失函数重新组合 logit 和 variance 图层,并仅使用 logit 图层计算 softmax。
我使用两个损失来训练模型,一个是任意的不确定性损失函数,另一个是标准的分类交叉熵函数。这允许创建 logit 的最后一个Dense
层只学习如何产生更好的 logit 值,而创建方差的Dense
层只学习预测方差。两个先前的Dense
层将在这两个损失上训练。任意不确定性损失函数的权重小于分类交叉熵损失,因为任意不确定性损失包括分类交叉熵损失作为其一项。
我用了 100 次蒙特卡罗模拟来计算贝叶斯损失函数。每个历元大约需要 70 秒。我发现,将蒙特卡洛模拟的次数从 100 次增加到 1000 次,每个训练周期会增加大约 4 分钟。
Example image with gamma value distortion. 1.0 is no distortion
我通过随机应用 0.5 或 2.0 的伽玛值来降低或增加每张图像的亮度,向训练集添加了增强数据。在实践中,我发现 cifar10 数据集没有很多理论上表现出高度随机不确定性的图像。这大概是故意的。通过向训练集中的图像添加具有调整的灰度值的图像,我试图给模型更多的图像,这些图像应该具有高度的随机不确定性。
不幸的是,预测认知的不确定性需要相当长的时间。在我的 Mac CPU 上,完全连接的层预测训练集的所有 50,000 个类大约需要 2-3 秒,但预测认知不确定性需要 5 分钟以上。这并不奇怪,因为认知的不确定性需要对每张图像进行蒙特卡罗模拟。我运行了 100 次蒙特卡洛模拟,因此有理由预计预测认知不确定性所需的时间是随机不确定性的 100 倍。
最后,我的项目被设置为在未来轻松切换底层编码器网络和其他数据集的训练模型。如果您想更深入地训练自己的贝叶斯深度学习分类器,请随意使用它。
结果
Example of each class in cifar10
我的模型在测试数据集上的分类准确率是 86.4%。这无论如何都不是一个惊人的分数。我能够得到高于 93%的分数,但只是牺牲了随机不确定性的准确性。有几个不同的超参数我可以用来提高我的分数。我花了很少的时间调整两个损失函数的权重,我怀疑改变这些超参数可以大大提高我的模型精度。我也可以解冻 Resnet50 层,并训练这些。虽然在这个数据集上获得更好的准确性分数是有趣的,但贝叶斯深度学习是关于预测和不确定性估计的,所以我将在这篇文章的剩余部分评估我的模型的不确定性预测的有效性。
Figure 5: uncertainty mean and standard deviation for test set
任意的不确定性值往往比认知的不确定性小得多。这两个值不能在同一个图像上直接比较。但是,可以将它们与该模型针对该数据集中的其他图像预测的不确定性值进行比较。
Figure 6: Uncertainty to relative rank of ‘right’ logit value.
为了进一步探索不确定性,我根据正确 logit 的相对值将测试数据分成三组。在图 5 中,“第一个”包括所有正确的预测(即“右”标签的 logit 值是最大值)。“第二”,包括“右”标签是第二大 logit 值的所有情况。“休息”包括所有其他情况。86.4%的样本属于“第一”组,8.7%属于“第二”组,4.9%属于“其余”组。图 5 显示了这三组测试集的随机和认知不确定性的平均值和标准偏差。正如我所希望的,认知和任意的不确定性与“正确”逻辑的相对等级相关。这表明模型更有可能将不正确的标签识别为它不确定的情况。此外,当模型的预测正确时,模型预测大于零的不确定性。我希望这个模型能够展现出这种特性,因为即使它的预测是正确的,这个模型也可能是不确定的。
Images with highest aleatoric uncertainty
Images with the highest epistemic uncertainty
以上是随意性和认知不确定性最高的图像。虽然看这些图像很有趣,但我不太清楚为什么这些图像有很高的随意性或认知不确定性。这是训练图像分类器产生不确定性的一个缺点。整个图像的不确定性减少到单个值。理解图像分割模型中的不确定性通常要容易得多,因为比较图像中每个像素的结果更容易。
“Illustrating the difference between aleatoric and epistemic uncertainty for semantic segmentation. You can notice that aleatoric uncertainty captures object boundaries where labels are noisy. The bottom row shows a failure case of the segmentation model, when the model is unfamiliar with the footpath, and the corresponding increased epistemic uncertainty.” link
如果我的模型很好地理解了随机不确定性,那么我的模型应该为具有低对比度、高亮度/暗度或高遮挡的图像预测更大的随机不确定性值。为了测试这一理论,我将一系列伽马值应用于我的测试图像,以增加/减少增强图像的像素强度和预测结果。
Figure 7: Left side: Images & uncertainties with gamma values applied. Right side: Images & uncertainties of original image.
该模型在增强图像上的准确度为 5.5%。这意味着伽玛图像完全欺骗了我的模型。该模型没有被训练成在这些伽马失真上得分很高,所以这是意料之中的。图 6 显示了左侧的八个增强图像的预测不确定性和右侧的八个原始不确定性和图像。前四幅图像具有增强图像的最高预测随机不确定性,后四幅图像具有增强图像的最低随机不确定性。我很兴奋地看到,与原始图像相比,该模型预测了每个增强图像更高的任意性和认知不确定性!随机不确定性应该更大,因为模拟的不利照明条件使图像更难理解,而认知不确定性应该更大,因为模型没有在具有较大伽马失真的图像上训练。
后续步骤
这篇文章中详细描述的模型只探索了贝叶斯深度学习冰山的一角,并且展望未来,我相信我可以通过几种方式来改进模型的预测。例如,我可以继续使用损失权重,并解冻 Resnet50 卷积层,看看我是否可以在不失去上述不确定性特征的情况下获得更好的精度分数。我还可以尝试在一个数据集上训练一个模型,这个数据集有更多表现出高度随机不确定性的图像。一个候选是德国交通标志识别基准数据集,我在我的一个 Udacity 项目中使用过它。这个数据集专门用于使分类器“应对由于光照变化、部分遮挡、旋转、天气条件而导致的视觉外观的巨大变化”。对我来说听起来像是随机的不确定性!
除了尝试改进我的模型,我还可以进一步探索我的训练模型。一种方法是看我的模型如何处理对立的例子。为此,我可以使用像伊恩·古德费勒创建的 CleverHans 这样的库。这个库使用一个对抗性的神经网络来帮助探索模型漏洞。看看 CleverHans 产生的对立例子是否也会导致高度的不确定性,这将是很有趣的。
另一个我很想探索的库是 Edward,这是一个用于概率建模、推理和评论的 Python 库。 Edward 支持创建具有概率分布的网络图层,并使其易于执行变分推断。这篇博文使用 Edward 在 MNIST 数据集上训练贝叶斯深度学习分类器。
如果你已经做到了这一步,我非常感动和感激。希望这篇文章激发了你在下一个深度学习项目中加入不确定性。
原载于gist.github.com。
建立一个更好的(模型)世界:我们在算法中歪曲世界的 3 种方式
这篇文章是在阅读了凯茜·奥尼尔的《数学毁灭的武器》后收集的想法和观点。没必要读过这本书就去读这篇文章,但如果你感兴趣,这里有一篇发表在《科学美国人》上的 评论 和一篇 NPR 对作者的采访 。
“大多数人说是智力造就了伟大的科学家。他们错了:这是性格。”
我相信爱因斯坦是对的——就像他在大多数事情上一样——当他这样说的时候。科学家有一个重大的责任:他们已经签约研究我们无限复杂的世界,并告诉我们其余的人它是如何工作的。
我们相信科学界,说:“我们相信你教给我们的是真实的,尽你所知。”这就是为什么我们在围绕科学工作的通用语:调查研究做决定、建立我们的企业和塑造我们的生活时感到舒适。这就是为什么我们的药物和医疗设备来自实验室,也是为什么我们被标题为“科学支持的提高生产力的五种方法”的博客帖子所吸引
智慧和好奇心造就了一名优秀的科学家,但是一名伟大的科学家必须有坚强的道德支柱和锻炼这种支柱的纪律。根据爱因斯坦的说法,仅仅研究某样东西是不够的——我们还必须确定我们是否应该研究它,我们的方法是否合乎道德,我们的结果是否会塑造一个更美好的世界。(更不用说对我们的结果保持诚实。)
数据科学领域最近也出现了同样的讨论——具体来说,数据科学家有责任主动警惕他们算法中的偏差。
作为程序员,我们可以很容易地按照别人告诉我们的去做。作为人类,我们很容易忘记与我们长相不同的人的世界是什么样的。
所以,我们来谈谈固有偏见是如何抬起它丑陋的头的。
过度简化世界的危险🌎
我们的大脑不擅长处理复杂性。
这就是为什么我们不断地寻找模式(即使它们不存在)。模式是决定的精神捷径,作为懒惰的人类,我们都喜欢捷径。因此,我们常常忍不住求助于刻板印象和其他简化(但错误)的启发式方法。
我们通过简化世界和在精神上删除无用的东西,在不断的刺激中生存下来——如果我们诚实的话,这并不总是让我们非常客观。
简化意味着选择什么是重要的,什么是不重要的,把现实世界变成一个模型或它自己的玩具版本。当谈到感知世界时,我们的大脑选择我们突出和记住的特征。当涉及到构建算法来代表世界时,人类会做出选择。
以下是我们作为算法设计者曲解或歪曲世界的方式:
- 👥把人们分成几组。
从算法上判断一个人最公平的方式是基于他们过去的行为(这与你测量的结果直接相关),而不是人口统计数据或其他属性。当我们做后者时,我们使用描述符或特征将人们分组,并问“像你这样的人过去是如何表现的?”用最基本的术语来说,你是刻板印象。
奥尼尔在这上面花了很多时间。她称之为“斗”,“一丘之貉”,或者“像你一样的人”模型。
这种简化经常表现出来。书中的例子包括芝加哥警察局的预测性警务——当一个没有暴力犯罪历史的 22 岁年轻人被警察拜访并被告知“小心”,因为他们的分析将他与他在脸书的朋友归类为罪犯——以及由 Kroger 等雇主实施的性格测试——其中一项测验对申请人的外向性和宜人性(以及其他品质)进行评分,并根据过去得分类似的员工对她将成为一名多么优秀的员工以及她将持续多久做出判断。
另一种看待这个问题的方式是,你不应该预测人们在他们还没有真正经历过的情况下会有什么行为。在实践中,这是一条很难走的路,有时很难走,尤其是在你没有历史数据的情况下。
在书中,奥尼尔强调 FICO 信用评分是一个正确的公式。FICO 分数是根据你过去是否支付过贷款/账单来计算的,用来预测同样的行为:你将来是否会继续支付。无论你对 FICO 的其他措施有什么不满,正如奥尼尔所说,“色盲”。
也许有一天我们会有虚拟现实设置,我们可以在不同的情况下测试人们(你会再次犯罪吗?你会继续拖欠贷款吗?)而不必遵从像邮政编码这样简单的特征。
- 🤑让我们的激励成为其他人的激励。
一般来说,为算法付费的人可以决定目标是什么,成功是什么样子。但是有一个论点是,你需要考虑每一组利益相关者或潜在用户想要什么和需要什么。
当你从外部研究一个算法时,寻找制造它的人的固有偏见——以及支付它的人的动机。
可悲的是,通常情况下,利润将代表真理——换句话说,如果算法在赚钱或省钱,那么它一定是正确的或好的。但是如果你从别人的角度来看,你会发现这实际上并不是一个胜利。
这方面的一个例子是 Starbucks 调度算法,该算法偶然发现了调度“clopenings”,即员工会在最后一个班次工作,然后在第一个班次开始第二天的工作(相差几个小时)。这为星巴克节省了一些福利支出和加班费,但如果你问员工,这是一种极端的生活方式和健康压力。
- 🎛选择代理人或使用替代品。
我们已经说过,人类是懒惰的。我们选择走最短的路去得到我们想要的东西。同样,公司也很便宜。他们选择花最少的钱和努力来实现一个目标。
当谈到算法时,这意味着用户和利益相关者将改变他们的行为来影响任何被测量的东西,这一切都是为了确保他们得到他们想要的结果。
当你设计一个算法时,你必须主动考虑用户可能会发现哪些“漏洞”来欺骗系统,然后决定你是否能忍受这些。
例如,人们在简历中加入职位描述中的关键词,以通过职位申请系统,因此在某种程度上,简历是从职位描述倒过来写的,而不是从申请人的技能倒过来写的。
另一个例子是一年一度的《美国新闻与世界报道》学院和大学排名。一所大学将近四分之一的分数是由其他学校的校长和院长的意见决定的,所以实际上是鼓励大学花钱互相营销和做广告,而不是像学生那样。
整个行业都可以从这些漏洞中诞生,比如搜索引擎优化专家和商学院应用顾问。
危险在于,替代品可能是可游戏的,而不是驾驶或测量有机行为,这才是你的真正目标。人类会迎合你的输入。您衡量的内容将推动行为。
一个更好的模型世界…
破坏数学的武器充满了个人的故事,他们的生活受到了数据科学家建立的模型的影响。一名男子被判较长的刑期,因为一名男子说他很可能再次犯罪。一位单身母亲,由于“文凭工厂”将她标记为一个容易的目标,她的债务呈螺旋式下降。一个好老师因为双极算法依赖于他控制之外的输入而丢了工作。
当我们建立算法时,我们需要与真实的人交谈,因为我们创造的东西与真实的人打交道,并以非常真实的方式影响他们。
因此,数据科学家不应该被关在房间里。她应该始终如一地与她的终端用户——一大批终端用户——互动。
直面我们无意识偏见的最简单方法是从受其影响的人那里听到后果。
奥尼尔还建议在代码投入生产之前进行“算法审计”。如果我们将我们的算法视为黑盒,我们可以客观地研究输出,以拼凑模型的假设,并确定它们实际上有多公平。
当然,这些检查说起来容易做起来难,因为大多数算法存在于需要利润的公司和需要工资的员工中。但从长远来看,我们希望所有人都能认识到,代表世界现状的模式——旨在让世界比现在更公平、更平等——将增加我们的经济,让我们所有人受益,不会让我们的邻居进一步陷入债务,让他们继续坐牢,或拒绝他们就业。
…以及我们如何到达那里
因此,下次您构建模型或编写代码时,请考虑您选择输入或数据源的原因,并尝试客观地看待您的模型世界。
想象一下将会受到影响的个人。走出你的方式去满足他们,并理解任何不适合你的模型代表世界的方式的边缘情况。分享你算法的输入,问他们这些是否公平。
如果可能的话,在你的模型投入使用之前,先对它进行实验。输入不同的输入组合,尤其是你能想象到的黑盒发展的任何偏差,然后观察它是如何发展的。
一旦我们更加关注我们的代码所处的世界,并且能够诚实地面对我们设计中潜在的非故意缺陷,我们就可以通过尝试调整激励、基于过去的行为寻找输入以及避免代理(或者至少认识到我们所使用的代理)来更加深思熟虑地制作算法。或许通过这样做,我们可以更接近真实地展现世界。
感谢阅读!我是一名前风投和生物医学工程师,痴迷于 NLP 和小说写作。在Twitter或LinkedIn上与我联系。
使用 Keras 和 tfjs 构建血细胞分类模型
人工智能真的是一个重大的游戏改变者。人工智能的应用是巨大的,它在医疗保健领域的范围是巨大的。先进的人工智能工具可以帮助医生和实验室技术人员更准确地诊断疾病,例如,尼日利亚的医生可以使用这种工具从血液样本中识别他根本不知道的疾病,这有助于他更好地了解疾病,从而可以更快地开发治疗方法,这是人工智能民主化的一个优势,因为人工智能模型和工具在世界各地都可以使用, 尼日利亚的医生可以使用麻省理工学院或世界上任何其他大学的研究学者正在使用的工具和技术。
机器学习的主要问题:
机器学习当然是今天人工智能进步的主要成分。但是,使人工智能民主化意味着建立一个基础设施,允许任何人在世界各地使用相同的技术来构建强大的工具。可能阻止任何人构建人工智能的两个主要问题是计算能力和训练数据集的不可用性。但是这些问题正在以有趣的方式得到解决,它们如下:
- **Kaggle(数据集之家)😗*数据集的不可用性是主要问题之一,但 Kaggle 是人们可以创建数据集并托管它们以供他人使用的最佳场所,人们已经使用这些工具创建了令人惊叹的东西。
- **谷歌联合实验室:**谷歌联合实验室是机器学习的主要驱动力,它允许任何拥有谷歌账户的人访问 GPU。没有这些 GPU,任何人都不可能训练需要巨大计算量的 ML 模型。
血细胞数据集
对于数据科学家来说,数据集就像一座金矿,如果数据集可用于特定问题,它将减少工程团队所需的大量工作,因为不需要开发基础架构来收集和存储数据。几个月前,我想开发这个系统,Kaggle 帮了我很多,以获得数据集。这是我在 Kaggle 上找到的数据集,感谢保罗·穆尼提供了这个数据集。
**数据集结构:**数据集包含 12,500 个血细胞的增强图像。数据集由 4 个类组成,如下所示:
Classes of blood cell dataset
每个类包含 3000 幅图像。该图显示了每个类别的示例图像:
Sample images from all classes
我把每张图片的尺寸缩小到(80×80×3)以便更容易训练。
Kaggle 要求您在下载数据集之前登录,因为我们使用的是 colab,所以不需要将数据集下载到我们的本地机器上,而是将它拉到我们的 google colab 实例中。
使用谷歌联合实验室
简单地说,谷歌联合实验室提供了一个基于云的 python 笔记本,其中有一个虚拟实例绑定到 GPU 运行时,谷歌 colab 的 GPU 运行时由 NVIDIA k-80 提供支持,这是一个强大的 GPU,也很昂贵。但是 co-lab 允许我们免费使用 GPU,而无需付费。一个实例的最大时间是 12 小时,12 小时后该实例将被销毁并创建一个新的,所以我们只能执行那些不超过 12 小时的计算。让我们看看如何使用 colab 来训练我们的神经网络。
向 Kaggle 认证:
Kaggle CLI 允许您下载数据集并向竞赛提交代码/笔记本。注册 kaggle 后,您可以下载 kaggle.json 文件,其中包含所有凭据,kaggle CLI 使用这些凭据进行授权。
- 创建一个新的单元格,并创建一个名为。kaggle,使用命令
!mkdir .kaggle
- 使用 pip:在新单元中安装 ka ggle CLI—
!pip install kaggle
- 下载数据集:
!kaggle datasets download -d paulthimothymooney/blood-cells
- 确保所有目录都存在于下载的数据集中
!ls dataset2-master/images
- 您应该看到 3 个目录:TEST、TEST_SIMPLE 和 TRAIN
- 目录 TRAIN 包含训练图像,我们将使用这个目录作为训练图像。
预处理:
我们需要将图像作为 numpy 数组加载,并将其提供给我们正在训练的神经网络。我们将使用 Keras 来构建一个神经网络,Keras 提供了一个内置的 ImageDataGenerator 来处理大多数预处理任务。
我们导入了开发模型所需的一些对象:
**from** **keras.models** **import** Sequential
**from** **keras.layers** **import** Dense, Conv2D, Dropout, MaxPool2D, Flatten
**from** **keras.preprocessing** **import** image
keras.preprocessing
提供处理各种类型数据集所需的方法和对象。从图像模块中,我们创建一个具有所有必需配置的 ImageDataGenerator。
generator = image.ImageDataGenerator(
rescale = 1./255,
featurewise_center=**False**, *# set input mean to 0 over the dataset*
samplewise_center=**False**, *# set each sample mean to 0*
featurewise_std_normalization=**False**, *# divide inputs by std of the dataset*
samplewise_std_normalization=**False**, *# divide each input by its std*
zca_whitening=**False**, *# apply ZCA whitening*
rotation_range=10, *# randomly rotate images in the range (degrees, 0 to 180)*
width_shift_range=0.1, *# randomly shift images horizontally (fraction of total width)*
height_shift_range=0.1, *# randomly shift images vertically (fraction of total height)*
horizontal_flip=**True**, *# randomly flip images*
vertical_flip=**False**)
如前一节所述,训练数据存在于``dataset2-master/images/TRAIN`目录中,我们提供此路径到 ImageDataGenerator,以便我们所有的配置和扩充都应用于训练图像。
dataset = generator.flow_from_directory(
shuffle = **True**,
batch_size = 32,
target_size = (80, 80),
directory = 'dataset2-master/images/TRAIN'
)
这都是关于预处理,你可以调整这些参数,通过减少或增加图像增强的效果,使之更好地拟合,总有改进的余地。
CNN 简介:
CNN(卷积神经网络)是一种神经网络,它包含一组卷积层和一个与之相连的前馈网络。卷积运算并不是一个新的运算,它在图像处理中的应用已经很多年了。卷积运算的主要作用是从图像中提取边缘,换句话说,它们可用于提取图像的重要特征。如果已知所谓的滤波器值,任何人都不可能确定任何图像的最佳滤波器值,因为我们将卷积与神经网络一起使用,梯度下降将自动优化滤波器值以提取图像的最重要特征。吴恩达的课程 deeplearning.ai 帮助你更好地理解这种网络的工作方式。因为这超出了本文的范围。
我们的网络:
这项任务必须使用 CNN,因为简单的前馈网络不可能学习数据集中每个类的独特特征。我们使用的 CNN 架构如下所示:
Neural Network Architecture
我创建了一个函数模型(),它返回一个顺序模型,如下所示:
**def** model():
model = Sequential()
model.add(Conv2D(80, (3,3), strides = (1, 1), activation = 'relu'))
model.add(Conv2D(64, (3,3), strides = (1, 1), activation = 'relu', input_shape = (80, 80, 3)))
model.add(MaxPool2D(pool_size = (2,2)))
model.add(Conv2D(64, (3,3), strides = (1,1), activation = 'relu'))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(128, activation = 'relu'))
model.add(Dropout(0.5))
model.add(Dense(4, activation = 'softmax'))
model.compile(loss = 'categorical_crossentropy', optimizer = 'adadelta', metrics = ['accuracy'])
**return** model
最后,我们训练模型,如下所示:
nn = model()
nn.fit_generator(dataset, steps_per_epoch = **None**, epochs = 30, verbose = 1)
nn.save('Model.h5')
模型经过 30 个历元的训练,得到了 92.67% 的精度**,这是一个很好的精度,你可以增加更多的层或者进行超参数调整来提高精度。**
部署模型:
一旦训练完成,我们需要将模型部署到生产中,以便每个人都可以使用它,有各种策略可用于部署机器学习系统。我想在客户端机器上运行整个推理,所以我开始构建一个可以这样做的 web 应用程序。
设置先决条件:
我们需要以下要求来建立一个客户端应用程序,该应用程序具有以下架构:
App architrcture
安装节点和 npm 并设置环境,以相同的顺序安装以下依赖项:
npm install -g create-react-app
create-react-app app_name
cd app_name
npm install --save @tensorflow/tfjs//on server side:
mkdir server
cd server
npm init
//fill up the details, make sure package.json is created
npm install express --save
-
模型服务器:这是一个 express.js REST 端点,客户端可以通过发送 REST GET 请求来请求模型文件。(在服务器端)
-
**模型存储:**我们需要创建一个与 tfjs 兼容的模型,tensorflow 提供了一个名为 tensorflowjs 的工具,这是一个包含实用程序的 python 工具包,我们可以使用下面的命令来安装:
pip install tensorflowjs
完成后,我们可以使用下面的命令使用 tensorflowjs_converter 将模型转换为 tfjs 格式:
$tensorflowjs_converter --input_format keras \
Model.h5 \
ModelData/model_data
// Model.h5 is the downloaded model after training, last argument is the target folder, where we need to store the model files.
一旦转换,它将创建一组称为碎片的文件,碎片是通过基于层分割模型获得的,每个碎片包含特定层的权重。使用碎片非常有帮助,因为每个碎片可以存储在不同的地方,并且可以在需要时下载,所以我们可以为我们的机器学习模型建立一个分布式存储。 model.json 当然是包含各个分片信息的文件。如果我们改变一个碎片的目录,我们可以修改这个文件。在 API 调用中,我们只将 model.json 文件发送给客户端,tfjs 将自动获取每个碎片以在客户端机器(即浏览器)上组装一个模型。
最后一部分:开发客户端推理机
在这一节中,我不会过多强调 UI 设计,相反,我会强调推理部分,即如何使用我们安装的 tfjs 运行推理。转到 react 应用程序目录。
- **创建一个模型容器类:**我首先为我们的模型创建了一个包装类。这个类的一个实例表示一个准备好进行推理的模型。这个模型类的代码是自我可理解的:
- **一个推理函数:**我定义了一个函数,可以取模型对象和输入图片源,输入源可以是 HTML img,或者 URL,或者图片的字节流。
代码如下所示:
- **初始化模型对象:**我们现在必须创建一个模型对象来保存一个用于推理的模型。
**let** modelCache = **new** ModelContainer(null);
modelCache.loadFromURL('http://192.168.0.105:5443/model_metadata')
- **运行推理:**一旦我们有了一个模型对象,我们就可以随时运行推理,根据我设计的 UI,每当用户点击 predict 按钮时,就应该执行推理。因此,运行预测的 React 组件部分如下所示:
结论
这个项目对我来说真的是一次很棒的经历,我学会了如何使用 google colab 在云上训练 ML 模型,我也学会了如何为生产部署 ML 模型。
这是一个开源项目,请随意更改:
回购网址: 反应-客户
云笔记本(模型训练用): training.ipynb
非常感谢您花费宝贵的时间阅读本文。如果你感兴趣,请开始回购。也可以在 Linkedin 上联系我。
干杯!
使用 Keras 构建图书推荐系统
如何使用嵌入创建图书推荐系统?
Figure 1: Photo by Brandi Redd on Unsplash
推荐系统试图预测用户在给出其旧的项目评级或偏好的情况下将给予项目的评级或偏好。几乎每个大公司都使用推荐系统来提高他们的服务质量。
在本文中,我们将看看如何使用嵌入来创建图书推荐系统。
对于我们的数据,我们将使用 goodbooks-10k 数据集,其中包含一万本不同的书籍和大约一百万个评级。它有三个特性 book_id、user_id 和 rating。如果你不想自己从 Kaggle 下载数据集,你可以从我的 Github 库获得文件以及本文中的完整代码。
把…嵌入
嵌入是从离散对象到连续值向量的映射,比如我们的例子中的单词或书籍的 id。这可用于查找离散对象之间的相似性,如果模型不使用嵌入层,这些相似性对模型来说是不明显的。
嵌入向量是低维的,并且在训练网络时被更新。下图显示了使用 Tensorflows 嵌入投影仪创建的嵌入示例。
Figure 2: Projector Embeddings
获取数据
熊猫将用于数据集中的加载。然后,数据将被分成一个训练和测试集,我们将创建两个变量,为我们提供唯一的用户和图书数量。
dataset = pd.read_csv('ratings.csv')
train, test = train_test_split(dataset, test_size=0.2, random_state=42)
n_users = len(dataset.user_id.unique())
n_books = len(dataset.book_id.unique())
Figure 3: Rating-Dataset Head
数据集已经被清理,所以我们不需要采取任何进一步的数据清理或预处理步骤。
创建嵌入模型
Keras 深度学习框架使得创建神经网络嵌入以及使用多个输入和输出层变得容易。
我们的模型将具有以下结构:
- **输入:**书籍和用户的输入
- **嵌入层:**书籍和用户的嵌入
- **点:**使用点积合并嵌入
在嵌入模型中,嵌入是在训练期间学习的权重。这些嵌入不仅可以用于提取关于数据的信息,还可以被提取和可视化。
出于简单的原因,我没有在最后添加任何完全连接的层,尽管这可能会增加相当多的准确性。因此,如果你想要一个更准确的模型,这是可以尝试的。
下面是创建模型的代码:
from keras.layers import Input, Embedding, Flatten, Dot, Dense
from keras.models import Modelbook_input = Input(shape=[1], name="Book-Input")
book_embedding = Embedding(n_books+1, 5, name="Book-Embedding")(book_input)
book_vec = Flatten(name="Flatten-Books")(book_embedding)user_input = Input(shape=[1], name="User-Input")
user_embedding = Embedding(n_users+1, 5, name="User-Embedding")(user_input)
user_vec = Flatten(name="Flatten-Users")(user_embedding)prod = Dot(name="Dot-Product", axes=1)([book_vec, user_vec])
model = Model([user_input, book_input], prod)
model.compile('adam', 'mean_squared_error')
训练模型
现在我们已经创建了我们的模型,我们准备训练它。因为我们有两个输入层(一个用于书籍,一个用于用户),所以我们需要指定一个训练数据数组作为我们的 x 数据。对于本文,我训练了 10 个时期的模型,但是如果你想得到更好的结果,你可以训练更长的时间。
以下是培训代码:
history = model.fit([train.user_id, train.book_id], train.rating, epochs=10, verbose=1)
model.save('regression_model.h5')
可视化嵌入
嵌入可以用来可视化概念,比如我们案例中不同书籍之间的关系。为了可视化这些概念,我们需要使用降维技术进一步降低维度,如主成分分析(PSA) 或t-分布式随机邻居嵌入(TSNE) 。
从 10000 个维度(每本书一个)开始,我们使用嵌入将它们映射到 5 个维度,然后使用 PCA 或 TSNE 将它们进一步映射到 2 个维度。
首先,我们需要使用 get_layer 函数提取嵌入内容:
# Extract embeddings
book_em = model.get_layer('Book-Embedding')
book_em_weights = book_em.get_weights()[0]
现在,我们将使用 PCA 将我们的嵌入转换为二维,然后使用 Seaborn 散布结果:
from sklearn.decomposition import PCA
import seaborn as snspca = PCA(n_components=2)
pca_result = pca.fit_transform(book_em_weights)
sns.scatterplot(x=pca_result[:,0], y=pca_result[:,1])
Figure 4: Visualizing embeddings with PCA
使用 TSNE 也可以做到这一点:
from sklearn.manifold import TSNEtsne = TSNE(n_components=2, verbose=1, perplexity=40, n_iter=300)
tnse_results = tsne.fit_transform(book_em_weights)
sns.scatterplot(x=tnse_results[:,0], y=tnse_results[:,1])
Figure 5: Visualizing embeddings with TSNE
提出建议
使用我们训练过的模型进行推荐很简单。我们只需要输入一个用户和所有的书,然后选择对这个特定用户有最高预测评分的书。
下面的代码显示了为特定用户进行预测的过程:
# Creating dataset for making recommendations for the first user
book_data = np.array(list(set(dataset.book_id)))
user = np.array([1 for i in range(len(book_data))])
predictions = model.predict([user, book_data])
predictions = np.array([a[0] for a in predictions])
recommended_book_ids = (-predictions).argsort()[:5]
print(recommended_book_ids)
print(predictions[recommended_book_ids])
此代码输出:
array([4942, 7638, 8853, 9079, 9841], dtype=int64)
array([5.341809 , 5.159592 , 4.9970446, 4.9722786, 4.903894 ], dtype=float32)
我们可以使用图书 id,通过使用 books.csv 文件来获得关于图书的更多信息。
books = pd.read_csv(‘books.csv’)
books.head()
Figure 6: Book-Dataset Head
print(books[books[‘id’].isin(recommended_book_ids)])
Figure 7: Recommended books
结论
嵌入是一种从离散对象(如单词)到连续值向量的映射方法。它们对于寻找相似性、可视化目的以及作为另一个机器学习模型的输入是有用的。
这个例子当然不是完美的,为了获得更好的性能,可以尝试很多方法。但是对于更高级的问题,这是学习如何使用嵌入的一个很好的起点。
您可以添加一些东西来获得更好的结果:
- 在点积后添加完全连接的层
- 为更多时代而训练
- 缩放评级栏
- 等等。
如果你喜欢这篇文章,可以考虑订阅我的 Youtube 频道并在社交媒体上关注我。
如果你有任何问题或批评,可以通过 Twitter 或评论区联系我。
使用自然语言处理构建一个机器人来应对 Reddit 上的负面评论
Reddit 是一个分享一切的神奇网站,它的口号是“互联网的首页”。它甚至在最近取代脸书成为美国第三大最受欢迎的网站。与其他社交媒体网站相比,Reddit 的独特之处在于用户可以匿名发帖。这种匿名性是 Reddit 如此受欢迎的部分原因,但正如任何好事一样,它也有一些负面影响。
几乎没有任何后果的发帖能力意味着几乎在任何提交的文章中都会有负面评论。虽然这些通常是建设性的批评,但少量的可能是全面的,令人讨厌的,总体上对讨论没有建设性。幸运的是,这些通常会很快被其他用户突出显示并否决,如果不够不受欢迎,可能会被隐藏。然而,那些向更小的子群(Reddit 上的子群)提交原创内容的人可能会受到这些负面评论的影响。这是我在一些小的子网站上发帖并收到如下评论后的亲身经历:
发布关于你自己的内容,尤其是图片,可能需要很多努力和信心,这样的评论让人很难继续投稿。不幸的是,我们的思维会自然地关注负面而不是正面的评论。
**每当这种情况发生,我的第一个问题总是‘你凭什么判断?’。**你是对这个子话题有所贡献并有权利不屑一顾的人吗?还是你只是路过,只是从对别人的刻薄中得到乐趣?
然而,我还没有脸皮薄到相信负面评论,不管它们是怎么写的,本质上都是不好的。任何提交到 subreddit 的人都需要了解他们在向谁发帖,以及这是否相关,接受建设性的批评只是这个过程的一部分。例如,在贴出我童年服装的拼贴画后,我收到了下面的回复。现在,这是否仅仅是一个个人观点还可以讨论,但是我承认我的观点可能不适合这个子主题,并且从这个话题中学到了很多。
目标
我想创建一个 Python 机器人,当它被使用时,它可以对用户的判断做出反应,当被调用时,它可以消除负面评论不公平恶意的情况。
基于在 Reddit 上的观察逻辑,如果有人发表了我认为没有建设性的负面评论,我愿意回答如下:
1.用户的账号有多老?(也就是说,他们是否躲在一个新账户后面,不会因为被否决而承担任何后果?)
2.这个用户向 subreddit 提交了多少次他们自己的帖子?
3.用户整体评价中负面的比例是多少?
4.用户对这个子编辑的评论有多大比例是负面的?
如果我能确定这些,那么我希望要么将用户归类为某个似乎在网站上持续负面的人,要么,也许这是不寻常的,他们只是过了糟糕的一天。
设置机器人
为了构建这个机器人,我遵循了 pythonforengineers.com 的T3编写的指南,该指南使用 Python 包 Praw 从 Reddit 的 API 中提取信息。
按照这个指南,第一步是让机器人找到负面的评论。出于前面提到的原因,用户会在使用特定文本短语时专门调用该机器人。为了做到这一点,我将机器人命名为“FloBot ”,如果用户在这里留下评论,机器人就会找到评论并开始分析父评论。下面显示了一个测试示例:
为了测试,我创建了 subreddit/r/flobot review,其中显示了一个测试帖子,演示了机器人给出的响应。机器人将检查对该子编辑的每个评论,如果任何评论包含“FloBot ”,它将选取该评论,然后查看该评论所响应的评论:
for comment_tracker in subreddit.stream.comments(): if re.search("FloBot", comment_tracker.body, re.IGNORECASE): comment = comment_tracker.parent()
然后,我们可以浏览并找出一些关于评论的基本信息(如上图所示),如作者、文本(以防后来被删除)和当前分数。
print("Subreddit: ", comment.subreddit)print("Author: ", comment.author)print("Text: '", comment.body,"'")print("Score: ", comment.score)
自然语言处理
这个过程的一部分是使用一些自然语言处理来确定被提问的用户写的评论是积极的还是消极的。为此,我使用了 Python 包 TextBlob ,它现在允许我们非常容易地分析文本的质量。我们使用这个包来确定评论的主观性和极性,如上面的例子所示。极性是我们将用来确定用户历史评论的负面性,并在以后更广泛地使用。
print("Sentiment Analysis Subjectivity: ", np.round(TextBlob(comment.body).sentiment.subjectivity,4))print("Sentiment Analysis Polarity: ", np.round(TextBlob(comment.body).sentiment.polarity,4))
分析用户的历史帖子和评论
我们现在有了完成分析的基础,我们已经连接了 Reddit 的 API,以:
-找到我们想要反驳的评论
-收集用户的基本信息
-应用一些 NLP 来评估评论文本的负面性。
因为我们已经收集了负面评论作者的名字,所以我们现在可以遍历并收集他们所有的评论,并在 for 循环中计算每个评论的极性。一旦我们对每个评论都有了这些信息,我们就收集这些信息作为 Pandas 数据表,其中包含以下信息:
仅用这张表,我们就可以计算:
-总的评论数量
-负分数评论的百分比
-负面评论的百分比
-发布到此子编辑的评论数量
-发布到此子编辑中的负得分评论的百分比
-发布到此子编辑的具有负极性的评论的百分比
此外,我们可以使用 Python 包 NLTK 来查找负面评论中最常用的单词。
最后,我们可以为用户的提交重复这个过程,以计算他们在这个子编辑中发布的帖子的数量。一旦我们获得了所有这些信息,我们就可以在一些标准文本中很好地对其进行格式化,以产生以下输出:
看起来我已经做出了相当多的负面评论,但总体来说,只有不到 2%的人投了反对票。看来我的评论 http://链接到 imgur.com 被否决最多。
进一步的工作
我已经在 Kaggle 上分享了我的机器人的完整代码,它目前不会自动发布,但在我部署它之前,我需要确保以下问题得到解决。
首先,需要评估自然语言处理的质量,如果可能的话,还需要改进。这个第一阶段只是为了演示这个想法,极性测量肯定还有改进的空间。
此外,如果我要考虑部署它,我将需要考虑它可能被用户错误地滥用和调用的可能性。我希望有一个检查系统在这之前自动响应到位,以确保用户不使用它只是欺负其他用户或其他邪恶的原因。
最后,我想在回复中再补充一点,包括一些例句,比如“这个人通常不会在这个帖子里发表负面评论,也许他们今天过得很糟糕。”给我们的机器人增加一点生命力。
我希望你喜欢这个想法,如果你有任何意见或建议,请让我知道。
谢谢
哲学(philosophy 的缩写)
构建碳分子自动编码器
是什么让碳分子如此特别
化学信息学是一个不断发展的领域,与人工智能一样,原因之一是:可用数据的增加。不可阻挡的数据增长预计不会放缓,有报告显示数据预计在未来十年每两年翻一番。
Welcomes to the information age; data might become the new dollar
这很重要,因为历史上,我们计算算法的准确度和精确度只受到我们给它们的数据的限制。
但是,尽管文本、视觉和数字等流行数据类型数量激增,化学信息却停滞不前。
缺乏数据的原因有很多:
- 化学数据没有单一的标准格式
- 化学数据是离散的,非常脆弱
- 实验数据经常被边缘化并被保密
解决数据问题的最好方法是充分利用现有资源,否则就自己创造数据。令人欣慰的是,网上不乏大量未标记的化学数据,如 Chemspider 、 Pubchem 和 Chemexpr 。未标记数据非常适合无监督学习,在无监督学习中,输入数据不需要预先分配相应的标记数据集列表。
使用 Pubchem 上的未标记碳目录,我建立了一个深度自动编码器,其中潜在层由神经网络(NN)认为是未标记微笑数据集中最重要的细节组成。
项目碳编码
自动编码器是一种神经网络架构,通过它输出被有意训练成尽可能与输入相似。
如果你输入一朵花的图片,输出应该尽可能看起来像原来的花。
The architecture of a vanilla autoencoder
它有一种美学上令人愉悦的对称形状。数据被压缩到红色的潜在层,类似于压缩文件。然而,自动编码器并不一定比其他压缩算法更好。所以我们有一个算法,它输出的东西和它的输入非常相似,这并不比其他压缩算法好多少;那么自动编码器有什么用呢?
自动编码器对于其架构中特定的 T21 部分很有用;隐藏层。也称潜在层,本质上是数据最重要特征的浓缩层。
这使得自动编码器非常适合降维和降噪。
该项目分为 4 个部分:
- 导入和规范化 SMILES 字符串数据
- 将规范化字符串转换为一个热点向量
- 构建深度神经网络模型
- 编译模型并拟合数据
该数据集是超过 12,000 个碳基分子的列表。选择单一元素是为了让自动编码器的潜在层能够学习使碳分子与其他元素相比具有独特性的特征。碳也被选中,因为它是最通用的元素之一,因此有一个更大的具有更多多样性的数据集,这有利于减少过度拟合。
Just a couple examples of carbon based molecules in the dataset
自动编码器被训练以识别其输入和输出之间的损失,以便模型学习最佳地复制给定的输入。输入层由 63 个节点组成,通过大小为 32 和 14 的另外两个过滤器。每层大约减半节点数,直到达到潜在层中 7 个节点的瓶颈。在完成编码过程时,操作被反转,并且解码器的每层的节点数量相对于编码器对称地增加。因此,经过训练的模型对碳分子的独特结构有着牢固的把握。
你可以把它想象成一瓶神奇的精华,让碳变得如此多才多艺。
一旦训练完成,潜在层可以用于生成模型,将普通自动编码器转换为可变自动编码器(VAE)。理论上,这种 VAE 能够产生新的碳分子,其中一些可能在材料科学、纳米技术或生物技术中有用。该模型还可以用作对抗性自动编码器(AAE) 的基础,这是另一种类型的生成算法,在关于药物等分子生成的研究实验中表现优于 VAEs。
Chemical design of a molecule using generative A.I
潜在层为它所压缩的数据的大量新见解提供了基础。人工智能可能会在数据中发现我们以前不知道的模式或特征。
Charged 项目的所有代码和数据集都可以在我的 Github 上的这个库中找到。
我们刚刚开始使用人工智能来帮助科学学科的研究人员加快他们的方法,产生更准确的结果,并为他们的假设提供验证。随着好处越来越为人所知,这两个领域的专家之间的合作被摒弃,我们的数据集将会增长,我们人工智能的力量也将增长。
关键要点
- 数据现在是世界上最有价值的资源之一,但仍然很少找到干净的标记化学数据
- 自动编码器似乎有悖直觉,但对于其架构的一个特定部分:潜在层,却有着巨大的潜力
- 自动编码器从输入数据中压缩和提取最重要的细节;我们可以在生殖人工智能中利用这种压缩
- 变异的自动编码器和敌对的自动编码器已经在生殖人工智能领域和科学界掀起了波澜
还在看这个?想要更多吗?不确定下一步该做什么?
向前!
使用对象检测和 OCR 构建聊天机器人
在本系列的第 1 部分中,我们让我们的机器人能够从文本中检测情绪并做出相应的响应。但这是它能做的全部,而且不可否认相当无聊。
当然,在真实的聊天中,我们经常发送各种媒体:从文本、图像、视频、gif 到任何其他东西。所以在这里,我们旅程的下一步,让我们给机器人一个愿景。本教程的目标是让我们的机器人接收图像,回复它们,并最终给我们一个关于图像中主要物体的粗略描述。
我们开始吧!
如果您还没有跟进,您可以在这里找到最新的代码:
所以我们要修改的代码在我们的事件响应循环方法中,这里:
我们的机器人已经对图像做出反应,但它不知道它们是什么,并且以一种相当温和的方式做出反应。
我们可以试一试,自己看看。让我们启动我们的服务器(和 ngrok),并向我们的机器人发送一个图像。
到目前为止一切顺利。我们的机器人至少知道它何时接收到图像。
在这个系列中,我们一直使用 google cloud APIs,所以对于我们的图像检测,我们将使用 Google Cloud Vision。按照这里的快速入门来设置您的项目:https://cloud . Google . com/vision/docs/quick start-client-libraries。记得使用我们在第 1 部分中设置的同一个项目。
一旦你完成了这些,现在是时候回到编码上来了。让我们将以下内容添加到我们的 Gemfile 中,并运行 bundle install:
gem 'google-cloud-vision'
让我们在 main.rb 中添加以下内容:
require ‘google/cloud/vision’
接下来,我们想要创建云语言 API 的一个实例:
You can find your project ID in your google cloud console.
我们要使用的 vision API 特性叫做 注释 。给定一个文件路径到本地机器上的一个图像,它将尝试基于我们传递给方法调用的值来识别图像。
在下面的例子中(来自 Google 的文档):
vision = [**Google**](https://googleapis.github.io/google-cloud-ruby/docs/google-cloud-vision/latest/Google.html)::[**Cloud**](https://googleapis.github.io/google-cloud-ruby/docs/google-cloud-vision/latest/Google/Cloud.html)::[**Vision**](https://googleapis.github.io/google-cloud-ruby/docs/google-cloud-vision/latest/Google/Cloud/Vision.html).[new](https://googleapis.github.io/google-cloud-ruby/docs/google-cloud-vision/latest/Google/Cloud/Vision.html#new-class_method)
image = vision.image "path/to/face.jpg"
annotation = vision.annotate image, faces: **true**, labels: **true**
annotation.faces.count *#=> 1* annotation.labels.count *#=> 4* annotation.text *#=> nil*
我们告诉 vision API 尝试识别人脸和标签。“标签”本质上是 API 确定它已经识别的对象。如果给我们一张狗的照片,我们可能会被贴上以下标签:
{
"responses": [
{
"labelAnnotations": [
{
"mid": "/m/0bt9lr",
"description": "dog",
"score": 0.97346616
},
{
"mid": "/m/09686",
"description": "vertebrate",
"score": 0.85700572
},
{
"mid": "/m/01pm38",
"description": "clumber spaniel",
"score": 0.84881884
},
{
"mid": "/m/04rky",
"description": "mammal",
"score": 0.847575
},
{
"mid": "/m/02wbgd",
"description": "english cocker spaniel",
"score": 0.75829375
}
]
}
]
}
让我们创建以下方法来利用这一功能:
上面的方法(不可否认是幼稚的)基于 Google cloud vision 的 API 的结果,获取一个文件路径并返回一个字符串。在 annotate 方法中,我们传递了一些参数,这些参数告诉 API 我们想要检测什么。
这个方法的返回(响应)是一个级联的短路流,首先检查著名的地标、任何文本,最后检查它检测到的任何对象(标签)。出于本教程的目的,这个流程纯粹是任意的和简化的(即,不要给我发电子邮件告诉我如何改进它)。
下面这张图我们来试试吧:
和结果(截断):
description: "cuisine", score: 0.9247923493385315, confidence: 0.0, topicality: 0.9247923493385315, bounds: 0, locations: 0, properties: {}
description: "sushi", score: 0.9149415493011475, confidence: 0.0, topicality: 0.9149415493011475, bounds: 0, locations: 0, properties: {}
description: "food", score: 0.899940550327301, confidence: 0.0, topicality: 0.899940550327301, bounds: 0, locations: 0, properties: {}
description: "japanese cuisine", score: 0.8769422769546509, confidence: 0.0, topicality: 0.8769422769546509, bounds: 0, locations: 0, properties: {}
由于没有地标或文本,我们收到了 API 能够检测到的标签。在这种情况下,我们看到它已被确定为“寿司”根据我对标签检测结果的经验,第二个标签(具有第二高的话题性)倾向于普通人如何识别该图片。
让我们在下面再试一次:
输出(再次被截断):
description: "wildlife", score: 0.9749518036842346, confidence: 0.0, topicality: 0.9749518036842346, bounds: 0, locations: 0, properties: {}
description: "lion", score: 0.9627781510353088, confidence: 0.0, topicality: 0.9627781510353088, bounds: 0, locations: 0, properties: {}
description: "terrestrial animal", score: 0.9247941970825195, confidence: 0.0, topicality: 0.9247941970825195, bounds: 0, locations: 0, properties: {}
我们看到了,《狮子》是第二部热播剧。
好的,另一个好的衡量标准,让我们尝试一些文本提取:
Just a screenshot of my text editor
让我们看看我们得到了什么:
2.4.2 :022 > puts analyze_image("major_general.png")
I am the very model of a modern Major-General,
I've information vegetable, animal, and mineral,
I know the kings of England, and I quote the fights historical
From Marathon to Waterloo, in order categorical;
I'm very well acquainted, too, with matters mathematical,
I understand equations, both the simple and quadratical,
About binomial theorem I'm teeming with a lot o' news, (bothered for a rhyme)
With many cheerful facts about the square of the hypotenuse.
=> nil
2.4.2 :023 >
还不错。
好吧,为了完整起见,最后一个。让我们尝试一个地标:
我们的方法给了我们:
2.4.2 :030 > puts analyze_image(“statue_of_liberty.jpg”)
Statue of Liberty
好了,我们的方法正在按预期工作,现在让我们实际使用我们的聊天机器人。
当我们通过我们的客户端(Line)向我们的聊天机器人发送一个图像时,客户端将响应体中的图像数据(以及其他相关信息)返回给我们的回调。因为我们的图像识别方法需要一个文件路径,所以我们必须将上述图像数据保存到我们的本地机器上。
让我们修改我们的方法来做到这一点。将回调方法的相关部分更改为以下内容:
这里有点不对劲。首先,我们创建一个新的 Tempfile ,并使用响应主体(图像数据)作为其内容。然后,我们将临时文件的路径传递给刚刚在控制台中测试过的分析图像方法。让我们用我们的机器人试一试,作为一个理智检查。
Such a nice bot…
它成功地为我们识别出了一个地标。
我们的机器人现在只是作为一个美化的控制台打印行工作,这不是很健谈。我们希望这个东西听起来更自然,让我们稍微清理一下我们的方法,让它听起来更“人性化”。
In fact, it is.
让我们对代码进行必要的修改。我们将修改一个现有的方法 analyze_image 并创建一个新方法get _ analyze _ image _ response。下面是:
同样,这不是一个关于 Ruby 的教程,而是概念;然而,让我们回顾一下我们刚刚做的事情。在 analyze_image 中,我们简单地删除了字符串 reply,并用我们的新方法 **get_analyze_image_response 替换它。**该方法采用一个注释对象,并基于图像中识别的对象类型,使用注释对象的描述值构建一个句子(字符串)。
我们来试试吧!
经典:
It’s a bacon cheeseburger, but I’ll give you that one.
现在是一个里程碑:
It indeed is!
就是这样!我们的机器人现在使用光学字符识别从图像中提取文本,并给我们提供它在我们发送的任何图像中找到的对象的基本描述。
目前,我们的机器人只能回复一次性消息。但是如果它有“记忆”,并且能够进行真正的对话呢?我们将在第 3 部分讨论多步沟通。
以下是我们到目前为止的所有代码: