在 Power BI 中创建网络图
数据科学/电力 BI 可视化
点击几下鼠标就能构建网络图的快速入门指南。
艾莉娜·格鲁布尼亚克在 Unsplash 上的照片
在上一篇 的文章 中,我写了一个使用 networkx 和 matplotlib 可视化熊猫数据帧的快速入门指南。虽然学习和探索 Python 中的网络图很有趣,但我开始思考如何向那些机器上没有安装 Python 或 Jupyter Notebook 的人展示结果。在task us,我们在大部分报告中使用 Power BI,因此我开始寻找一种定制的 Power BI 可视化技术,它可以获取数据并将其转换为有意义的网络图。
进入网络导航器。
Network Navigator 是微软创建的 Power BI 中的一个自定义可视化工具。它允许您“通过平移和放大受力控制的节点布局(可以预先计算或实时制作动画)来浏览节点链接数据。”在本帖中,我们将通过使用自定义可视化工具创建网络图所需的步骤。
首先,让我们得到我们的数据。你可以在这里下载样本数据集。然后,我们可以将数据加载到 Power BI Desktop 中,如下所示:
选择文本/CSV 并点击“连接”。
在 Windows 资源管理器文件夹中选择文件,然后单击打开:
点击“转换数据”。
点击“使用第一行作为标题”。
点击“关闭并应用”。
接下来,找到“可视化”面板末端的三个点。
并选择“获得更多视觉效果”。
将鼠标光标指向搜索文本框,输入“网络”,按“回车”键,然后单击“添加”按钮。
稍等片刻,您将看到下面的通知。单击“确定”按钮关闭通知。
你会看到一个新的图标出现在“可视化”面板的底部,如下所示。
点击新图标,你会看到类似下图的东西。
选择新的可视占位符后,单击“Fields”面板中的“Reporter”和“Assignee ”,它会自动将列分配为源节点和目标节点。
让我们通过点击画笔图标来添加标签。
单击“布局”展开该部分,并向下滚动,直到看到“标签”部分。
点击“标签”下的切换开关将其打开
瞧啊。
就是这样!只需点击几下鼠标,我们就能从 csv 文件创建网络图。
我希望你喜欢今天关于 Power BI 最酷的视觉效果之一的帖子。网络图分析是一个大话题,但我希望这个温和的介绍将鼓励你探索更多,扩大你的曲目。
在下一篇文章中,我将分享我从懒鬼到数据科学家的旅程,我希望它能激励其他人,而不是被仇恨者劝阻。
敬请期待!
[1]:商业应用程序—微软应用程序源。(2020 年 5 月 16 日)。网络领航员图表https://app source . Microsoft . com/en-us/product/power-bi-visual s/wa 104380795?src = office&tab = Overview
使用 Dash 和 CSS 引导创建专业仪表板
实践教程
在 Git 和 Heroku 上有一个逐步解释的例子
介绍
在本文中,我将按照我的步骤创建一个交互式仪表板,使用 PlotlyDash,一个 Python 和 R 的库,并使用 CSS Bootstrap 增强布局。
D ash 库基于 Flask、Plotly.js 和 React.js 编写,允许用纯 Python 构建数据可视化应用程序,通过 web 浏览器呈现。
我产生的最终结果可以显示在这里:https://corporate-dash.herokuapp.com/
作者图片
这是一个多页仪表板,模拟一个业务场景,其中通常有一些布局指南要遵守(公司颜色方案、预定义的字体、可以激励我们的公司网站等)和一些与销售相关的 KPI 要监控。
第一页充满了不同类型的图表(散点图、条形图、气泡图、热图)和一个摘要表,带有随机数据;其他页面是空白的,但是对于展示如何构建多页面结构很有用。
在本文中,我将介绍:
1.仪表板目标
仪表板旨在提供一些与业务相关的 KPI 的清晰而准确的视图,使最终用户能够理解所呈现的内容,找到所需的信息,应用一些过滤器,并有希望得出一些结论。
这个仪表板设计得像一个网站,由不同的页面组成,顶部有一个导航条。
每个页面内容分为三个部分:
- 可以应用于页面中显示的所有图表的一些顶级过滤器
- 摘要表也显示在顶部,使用户能够快速浏览主要 KPI。理想情况下,目的是让用户避免浏览页面上的每一个图表,而是通过查看摘要表就能立即发现应该关注的地方。这个摘要表有一些条件颜色格式,就像交通灯一样,突出显示正/负值。
- 最后是一个图表网格,显示了主要 KPI 的不同视图
我有意避免为用户提供任何导出底层数据的方法:由于对数据隐私和数据丢失的担忧日益增加,仪表板只打算使用聚合数据。最终用户无法获得原始数据点。
2.Dash 入门
plotly Dash 有大量的用户指南和介绍。
我个人发现浏览这些资料非常有用,这解释了大量的例子:
- Dash 官方网站https://dash.plotly.com/非常有用,易于阅读和导航,显示所有可用的组件及其主要属性
- 本文从里到外解释了一个非常完整详细的例子:https://towardsdatascience . com/how-to-build-a-complex-reporting-dashboard-using-dash-and-plotl-4f 4257 c 18 a 7 f
- 我还寻找了大量 Youtube 视频,展示如何创建和定制基本的 Dash 布局和回调
尽管查阅了所有这些有用的资料,我不得不面对许多挑战,尤其是为了理解如何按照我想要的方式定制 Dash 组件。
出于这个原因,我也将在下面的步骤中关注这一方面:增强的功能和布局,最终结果的视觉识别是一个非常重要的方面,可以产生影响。
3.为多页仪表板配置文件夹结构
应按照 Dash 指南(【https://dash.plotly.com/urls】T2)的建议构建应用程序源代码文件,以实现多页面导航。基于这个指南,我使用了以下方法来最小化任何代码更改或改编。
我的根文件夹包含:
- app.py :这个文件很基础,只会定义 Flask 需要的 app 变量。我只是简单地遵循 Plotly Dash 指南来创建这个文件。
- index.py :这是一种导航文件,帮助应用程序管理不同页面的 URL。此外,这个文件是非常标准的:我建议遵循 Plotly Dash 指南,因为我们只需要自定义路径名就可以了。
- layouts.py :所有页面 html 布局都将存储在这个文件中。考虑到一些组件(如页眉或导航条)必须在每个页面上重复,我创建了一些函数来返回它们,避免了代码中的重复
- callbacks.py :所有回调(Dash 组件背后的函数,定义用户与图形的交互)都将存储在这个文件中
在根文件夹中,Dash 将查找:
- “数据子文件夹:包含仪表板的底层数据
- 一个“资产”子文件夹:包含附加文件,如:图像;收藏夹图标,供浏览器使用;。css 文件
如果 assets 子文件夹遵循这种结构,应用程序将自动检测并使用 favico.ico 文件或。css 文件,不需要任何代码!只需将图像命名为“favicon.ico ”,并将其放在 root/assets 中,Dash 就会自动使用它。
根文件夹中还有一些附加文件(例如。gitgnore,README.md,Procfile,requirements.txt):在 Heroku 上部署 app 或者在 Git Hub 上存储代码都需要这些文件。
4.用 CSS 引导网格系统概念化布局
有了应用程序文件夹结构,接下来要配置的是页面的整体布局。谈一个 web 应用布局不能不提。css 文件,集中了几乎所有的布局属性,可以被浏览器读取。
用很少的话来说。css 文件定义 html 组件的属性(字体属性、大小、颜色、背景等),Dash 也使用这些属性。
应用程序将开始应用布局属性到相应的 html 组件,从。存储在应用程序的“资产”文件夹中的 css 文件。
需要注意的是:如果同一个 html 组件的属性(例如 H2 html 标题字体系列)在多个。css 文件,应用程序读取的最后一个文件(让我们忽略!重要的 css 后缀)。
CSS 属性也可以通过创建一些自定义的“类”来定义,然后分配给我们想要样式的 html 组件(如 div)。
在我的例子中,我用了 3。css 文件,我用一些前导数字来命名,以确保应用程序以特定的顺序读取它们:
- 自定义字体,定义应用程序使用的新字体系列(你可以从谷歌下载字体系列,复制它们。css 内容。请注意,在字体文件中,有一些应用程序将下载的 URL。如果您的应用程序将在离线环境中运行,您应该下载这些 url 的内容,并将其放在一个子文件夹中:root/assets/fonts,在字体中根据该路径名调整 URL。css 文件)
- 自举。css 标准文件,我将在下面描述(我基本上是从 Bootstrap 网站下载的官方 CSS 文件)
- 一个“corporate-style.css”包含了我在布局中引入的所有定制
我已经看到许多精彩的破折号例子使用了基本的。css 模板(【https://codepen.io/chriddyp/pen/bWLwgP.css】T2):这不是应用程序的要求,我选择不在我的仪表板上使用它(我已经使用了官方的。而是 css 引导文件)。
4.1 使用 CSS Bootstrap 构建布局框架
CSS Boostrap 提供了很多预定义的。我们可以重用的 css 属性、类和布局功能。CSS Bootstrap 以著名的“网格系统”而闻名,它可以根据所用设备的大小来帮助缩放网站页面。
简而言之,我们可以将我们的网页想象成一个由 12 行和 12 列组成的表格:我们的 html 组件可以放在这个网格中,它将根据显示它的设备的屏幕而具有动态的大小。
我认为这对我获得我心目中的布局帮助很大,如下所示:
作者图片
我已经开始从不同的部分(我的页面的“行”)考虑布局,然后在脑海中描绘仪表板的不同列。
我假设,就像在商业场景中一样,一些颜色已经是企业视觉识别的一部分(在这种情况下,是一种带有一些粉色元素的绿色调色板),我选择了一个很好的字体系列,名为 Dosis。
之后,我一直在创建图片中的方案,用不同的占位符和引导列。我用过的 css 类。
在 CSS 引导网格系统中,不同的。div 元素是嵌套的,每个元素都有自己的类,从一行开始,然后是一列或多列。CSS Bootstrap 有不同的列类,从 col-1 到 col-12,这意味着我们可以拥有我们希望的动态列宽,从最大宽度的 1/12 开始,直到使用全部可用宽度(12/12)的列。在每一列中,可以嵌套另一个. Div 的行列序列。
所有这些类都可以分配给 html。Div([])元素,位于它们的 className 属性中。
该系统有助于保持仪表板的每个部分有序,每个仪表板组件都有一个指定的区域,该区域对所使用的屏幕也是动态的。
例如,下面的结构被用来设计标题、导航条和过滤器的样式。
割台包括:
- 外部 html。Div 组件,它有一个. CSS“row”类,用背景色进行样式化
- 三个 html。Div 组件,在行内;每个都代表一个“col”。css 类(记住这些列宽度的总和必须等于 12):一个 className=“2-col” div(一个宽度为 2/12 的列),它将保持为空,只是为了确保标题居中;一个 8 列的 div,包含主页标题,最后是另一个 2 列的 div,包含公司徽标图像
作者图片
导航条,包括:
- 在行的两侧有两个空的列 3 格
- 三个中央 col-2 div,每个都包含一个 dcc。链接破折号组件,可用于从一个页面切换到另一个页面。dcc。当前页面的链接页面采用不同的样式,突出显示用户所在的页面
作者图片
过滤器部分由以下部件组成:
在外部,我们有一个行和列 div:
- 外部 html。具有“行粘顶”类的 Div。这是一个 Bootstrap 类,和 row 一样,但是它会停留在页面的顶部,即使用户向下滚动。
- 在行内,有一个 12 列的 Div,带有一些样式属性
在 12 列 div 列中,我们有另一个“行”Div,包含以下一组列:
- 内部行两侧的两个空 col-2 div
- 两个 col-4 div,在内部,每个都包含滤波器组件:一个 dcc。DatePickerRange 和两个 dcc。下拉组件
作者图片
4.2 样式化 Dash 组件访问它们的 CSS 类
一旦定义了布局,从用户界面的角度来看,下一个挑战是正确地设计每个 Dash 组件的样式,比如日期范围(dcc。DatePickerRange)、下拉筛选器(dcc。下拉)等。
所有这些组件都有一个“样式”属性,在这里我们可以定义想要样式化的 css 属性,比如字体大小、颜色、空白等等。我们想要实现的大多数布局增强,都可以通过在 Dash 组件的“样式”中定义正确的 css 属性来实现。然而,我在对这些组件的一些特性进行样式化时面临着不同的挑战,这似乎无法从它们的“样式”属性中获得。我在网上看过许多不同用户的类似挑战,想知道如何设计这些组件的某些功能或细节。
我认为这里的主要挑战是识别 Dash 使用的 CSS 属性。事实上,有一种方法可以指向并单击,或者“检查”页面上的每个元素,并揭示定义它的 CSS 属性。
事实上,我们可以在浏览器中运行应用程序,右键单击页面并选择“Inspect”:这将在页面右侧弹出一个窗口,我们可以在其中浏览页面的 html 和 css 代码。在页面顶部,我们可以点击这个工具
作者图片
我们最终可以将鼠标悬停在想要设置样式的元素上,并获取其所有 CSS 类和属性,以了解要更改/重定义什么。
4.2.1 示例:设置 DatePickerRange 元素的样式
默认情况下,DatePickerRange 如下所示:
作者图片
我们可以从“样式”属性中改变组件布局,定义字体大小,添加一些颜色的边框,等等。但是如何修改分隔开始日期和结束日期箭头呢?如何更改突出显示所选日期或助手图标周围的绿色?
这些元素似乎无法从“样式”属性中获得,我们必须使用不同的方法来更改它们的布局属性。在浏览器中,如果我们检查并选择箭头,我们会看到类似这样的内容:
作者图片
该组件使用了一些 CSS 类,我们可以通过在自定义 CSS 文件中添加一些代码来修改这些类,从而将箭头强制调整为新的大小:
作者图片
同样,我们可以通过检查日历选择来揭示如何更改日历样式:
作者图片
通过分析这一因素,似乎”。CalendarDay__selected”是所选日期极值的 CSS 类,而“CalendarDay__selected_span "是用于两个极端之间的所有日子的 CSS 类。可以使用这些类来改变日历的背景颜色(并在鼠标悬停在不同日期时定义一些布局修改)。我已经将下面的代码添加到自定义 CSS 文件中:
作者图片
("!“important”覆盖同一 CSS 元素或类的任何其他布局定义)。
4.2.2 示例:样式 a dash_table。数据表元素
我发现另一个难以设计的元素是我在仪表板顶部的摘要部分使用的数据表。
默认情况下,数据表有一个功能,可以选择一个单元格,使它以粉红色/红色背景出现。此外,通过使用默认的 CSS 引导文件,默认设置会将我们悬停的所有表格行的背景颜色更改为白色。
作者图片
我想真正改变这两个与我的整体布局相冲突的默认属性。
首先,可选单元格实际上不是一个 CSS 属性,而是一个可以被禁用的组件属性:在创建 DataTable 时添加“cell_selectable = False”会删除此功能。
为了改变行悬停的颜色,用之前解释过的方法我们可以看到,DataTable 行实际上是 html 元素,与特定的 CSS 类没有关联。
作者图片
为了自定义当鼠标悬停在行上时的背景颜色,我在自定义 CSS 文件中添加了以下内容:
作者图片
5.回调和组件
一旦定义了仪表板布局,并且图表和过滤器组件已经放置在页面上,让我们转到回调。
我将介绍一些回调的例子,重点是我用过的最麻烦的例子。
5.1 多下拉过滤器:如何拥有“全选”选项
仪表板通常包括一个或多个下拉过滤器,允许用户同时选择一个或多个值。
在非常简单的情况下,下拉组件“背后”不应该有任何回调:用户选择一个或多个下拉选项;所选的值通常是其他回调函数的“输入”,这些回调函数调整图表上显示的内容。
然而,在更复杂的情况下,我们可能希望有一个多下拉选择,其中第二个下拉的选项取决于第一个下拉的选择。在我创建的例子中,我有一个国家下拉列表和一个城市下拉列表:城市下拉列表选项,当然取决于已经选择的国家。
更复杂的是,我注意到 Dash 中没有“全选”的现成功能。特别是在下拉选项是长列表的情况下,强烈建议添加一个“全选”的方法,否则我们每次想要分析所有值时都需要逐个输入所有选项。此外,我还想以一种“无选择”(即将下拉列表留空)意味着考虑所有选项。
为了实现这里描述的所有特性,我遵循了下面列出的步骤。
创建选项列表
首先,我为每个下拉组件创建了一个选项列表。我随机创建的数据在一列中包含“国家”信息,在另一列中包含“城市”信息。我简单地创建了两个唯一的列表,一个用于所有可能的城市,另一个用于所有可能的国家,我添加了一个“(全选)”条目,我希望它位于选项列表的顶部。
接下来,我在页面布局中包含了 Dropdown 组件,只需指定“multi”属性:
作者图片
5.1.2 动态管理选项列表
然后,我定义了一个回调,它将第一个下拉列表中的值(选择)列表作为输入,将第二个下拉列表中的选项列表作为输出返回。
鉴于选项列表取决于值,我生成了一个字典,其中每个键都是第一个下拉列表的可能值,每个值都是第二个下拉列表的所有可能选项的列表。结果如下所示:
{巴西:[福塔莱萨,里约热内卢,圣保罗],
【米兰、威尼斯】,… }
为了完成回拨,一些关键的考虑事项是:
- 第一个下拉列表中的“值”将是一个 python 列表
- 该列表可能包含也可能不包含“全部”选项
- 将值列表留空意味着我们将把[‘’]作为回调的输入
作为第一步,我创建了一个变量(isselect_all),用于确定用户是否将第一个下拉列表留空,或者用户是否选择了“全选”,或者这两种可能性都没有。
在前两种情况下,回调只是返回所有可能城市的排序列表。否则,用户将分别选择一个或多个国家,因此我将使用之前创建的字典(我将其命名为 repo_groups_l1_l2)来计算所有可能城市的排序列表。
作者图片
5.2 通过热图揭示季节性模式
在所有可能的图表中,当我们想要绘制三维图并显示数据的季节性或模式时,热图是理想的。例如,我包含了一个热图来显示全年(在我的例子中是周数)和一周中的某一天的销售趋势,以查看这两个维度上是否有任何季节性。
x 轴表示工作日,y 轴表示日历周数;每个单元格将根据销售量进行着色。热图还需要响应过滤器(基于日期和城市和国家下拉)。
5.2.1 热图:布局
首先,让我们在 dash 布局中包含一个热图占位符。在下面的代码中,headtmap 将位于 id 为“sales-weekly-heatmap”的最后一列:
作者图片
5.2.2 热图:回拨概述
然后,让我们转到回调,它将有:
- 输入:不同的过滤器——在我的例子中,这些是日期选择器中的开始和结束日期,以及“国家”和“城市”下拉选择
- 输出:上面的 dcc。图形“数字”元素
- 第一部分:数据准备。回调将使用 datasource(由单个 dataframe 组成),并按周 nr 过滤和聚集数据。和工作日
- 第二部分:图形准备(使用 Plotly: go。热图)。该图表将使用预定义的色标,我通过一个函数自定义创建
热图:数据准备
在数据准备部分,我必须包含一些语句来处理两个下拉选择的“全选”。如果用户已经从下拉列表中选择了该选项,则数据框架不需要按照国家/城市进行过滤;否则,仅考虑用户从初始完整数据帧中选择的值:
作者图片
然后,我按开始日期和结束日期过滤数据框架,最后按周数和工作日汇总:
作者图片
热图:图形配置
为了在仪表板上绘制一些漂亮且一致的图表,我创建了一个 go。回调文件顶部的 Layout()变量(名为 corporate_layout)。此布局变量包括许多属性,这些属性在所有仪表板图表中几乎都是相同的(图表透明背景、字体系列、标题字体大小、网格线、零线、总高度、图例、边距等等)。
在每个图表回调中,一个新的 fig = go。图(data=data,layout=corporate_layout)已定义。这允许更新 fig 布局(通过这个命令:fig.update_layout())以适应 corporate_layout 并包括图表标题和轴标题。
使用这种方法,图表的主要布局只定义一次:这有助于保持代码的整洁,同时也很灵活;也就是说,为了改变所有图表的高度,我们只需要调整整个代码中的一个变量。
关于 go 的“数据”部分。我用了一个 go。Heatmap(),包括一个色标,我将在下面描述它。
作者图片
5.2.5 热图:添加自定义色阶
Plotly 热图包括一些标准色阶,我们可以从中选择,或者我们可以指定一个自定义创建的色阶。
Plotly 提供了一些指令(此处可用)来创建自定义色标。我使用的色阶是这样的:根据每个数据点的百分比,热图使用的 11 种颜色的列表。
作者图片
为了以某种渐变顺序生成颜色,我创建了一个函数,它将我们需要生成的颜色数量和两种颜色的 RGB 值作为输入:一种是“起点”,另一种是“目标点”。对于每种颜色,该函数以相同的量递增 RGB 值,直至达到目标值。这是一个非常简单的方法,但是这个函数可以满足目的:
作者图片
我们最终可以将色阶添加到热图中,以揭示一些季节性:正如我们所见,销售额似乎在第 10 周和第 20 周之间下降;然后他们开始增加,在第 25 周达到同样的水平。在一周的几天里,我们没有明显的季节性。
作者图片
5.3 悬停在数据点上时提供附加信息
在 Dash 中,可以定义 hovertemplates 来指定当用户将鼠标悬停在数据点上时,什么数据以什么格式显示。
除了图表已经使用的数据(例如,x 和 y 值)之外,在 hovertemplate 中包含附加信息可能很有用。官方文件提供了有用的选择:我将展示我发现最有效的一个。
在下面的图表中,我创建了一个堆积条形图,其中每个国家由每个竖条表示,将销售额显示为每个城市个人销售额的总和。悬停时,我还想显示关于总目标而非销售额的信息:
作者图片
城市的“目标”是数据源中存在的信息,但它并没有显示在图表中:悬停模板从哪里获取这些信息?
我采用的方法是在图表使用的 dataframe 中创建一个新列,包含我想在 hovertemplate 中显示的所有信息:
作者图片
Plotly hovertemplate 需要一些 html 格式:“T2””例如,意味着内容将是斜体; 用于清除数据点的痕迹名称。值使用 d3 格式的语法进行格式化(如 Plotly 这里的所解释的):“{:,d}”用于包含千位分隔符(如果您想知道这对于其他值类型如何工作:具有两位小数的百分比可以这样格式化:“{:. 2% }”;日期的格式可以是:“{x|%a,%d-%b-%Y}”。
一旦数据中有了 hovertext,我们就可以在图表中使用它,只需将 dataframe 列分配给图表 hovertemplate。
6.如何部署和共享仪表板
通过 Dash 创建的仪表板可以部署为 Flask 应用程序。Heroku 无疑是让应用程序在线可用的最有效的方法之一(而且是免费的)。
我用来部署这个应用程序的指南通过这个视频得到了很好的解释,包括一个大约。让这款应用上线的 15 个步骤。
7.结论
Plotly Dash 绝对是一个有趣且非常强大的 Python 库:我一直在寻找一种快速的方法来自动进行可重复的分析,并且非常好地呈现出来,这绝对达到了目的!
凭借 Python 知识、一些 html 和 css 经验,我能够在几周的空闲时间里实现这个仪表板:我必须说,将 CSS Bootstrap 体现到布局中产生了变化,并且肯定允许构建一个底层“网格”,允许以我想要的方式非常容易地控制仪表板的每个部分。
用 Amazon Kendra 和 AWS Fargate 构建一个问答聊天机器人
构建快速问答聊天机器人的分步指南
在 pixabay 上由 manfredsteger 拍摄的照片
亚马逊宣布亚马逊 Kendra 几周前,Kendra 是一个高度准确且易于使用的企业搜索服务,由机器学习提供支持。
在这篇文章中,我将使用 React 和 Amplify 、web socketAPI inAWS API Gateway、 AWS Fargate 和 Amazon Kendra 构建一个问答聊天机器人解决方案。
解决方案提供了问答的对话界面。这个聊天机器人允许用户提出他们的问题,并迅速得到相关的答案。
我们将在这篇文章中讨论的内容:
- 创建一个亚马逊 Kendra 索引,从半结构化文档中提取问题和答案到 Kendra FAQ。
- 在 API Gateway 中部署一个 WebSocket API 来处理问题和回答消息。
- 创建一个 React 应用程序,并使用 AWS Amplify 通过 WebSocket 与这个聊天机器人进行连接和交互。
- 在 AWS Fargate 中创建一个服务,让我们的 bot 调用 Kendra 的 API 来提供答案并将其发送回用户。
下图显示了上述步骤的架构:
为什么 AWS Fargate 如此重要?
构建聊天机器人的一个更简单的方法是使用一个 lambda 函数来查询 Amazon Kendra,而不使用 Fargate。然而,通过 AWS Fargate 或 EC2,我们可以用定制的人工智能模型来扩展聊天机器人,使我们的机器人更加人性化,例如,我们可以基于拥抱脸 最先进的 对话式人工智能模型来构建聊天机器人,并仅查询 Kendra 的特定数据。
如果你的程序是一个长时间的计算任务,需要更多的内存和更高的性能, Fargate 可能是更好的选择。
先决条件
现在,让我们开始吧!
创建亚马逊肯德拉指数
让我们创建一个肯德拉指数。亚马逊 Kendra 是一个高度准确且易于使用的企业搜索服务,由机器学习提供支持。Kendra 支持非结构化和半结构化文档,如存储在 S3 的 FAQ,我们将在我们的案例中使用 FAQ。
首先,让我们下载一个 QnA 数据集并上传到 S3。我们可以为聊天机器人使用
微软研究 WikiQA 语料库 。
下载数据集后,让我们转换为 Kendra 支持的 csv 格式,如下所示:
使用以下脚本转换数据集,并将转换后的 csv 文件上传到现有的 S3 存储桶my-kendra-index
:
现在,我们准备创建一个肯德拉指数。要创建 Kendra 索引,请完成以下步骤:
- 在 Amazon Kendra 控制台上,选择启动 Amazon Kendra。
- 创建索引并输入索引名,如
my-aq-index
。 - 对于 IAM 角色,选择
Create a new role
来创建一个允许 Amazon Kendra 访问 CloudWatch 日志的角色。 - 创建索引。
创建 Kendra 索引后,我们可以添加常见问题文档:
- 从亚马逊 Kendra 控制台添加常见问题。
- 对于 S3,浏览 S3 找到您的桶,并选择常见问题 csv 文件。这里我们用
s3://my-kendra-index/faq/faq.csv
。 - 对于 IAM 角色,选择
Create a new role
以允许 Amazon Kendra 访问 S3 存储桶中的 FAQ 内容对象。 - 添加常见问题。
现在我们有了一个有效的 Kendra 指数,让我们进入下一步。
在 API 网关中部署 WebSocket API 来处理 QnA 消息
在本节中,我们将在 AWS API Gateway 中构建一个 1) WebSockets API, 2) 创建 lambda 函数来管理 WebSockets 路由( c o n n e c t , connect, connect,disconnect,sendMessage )和 3) 创建 DynamoDb 来存储 WebSockets 连接 id 和用户名。
我们将使用无服务器框架来构建和部署所有需要的资源。让我们创建一个新的无服务器项目,并将以下配置添加到serverless.yml
:
请注意,serverless.yml
中的 Cognito App 客户端 Id ( /chatbot/dev/app_client_id
)和 Cognito 用户池 Id ( /chatbot/dev/user_pool_id
)尚未创建,我们在此仅引用 Cognito 详细信息为SSM Parameters
,在下一步中,我们将使用Amplify Cli
创建 Cognito 用户池,然后我们可以从System Storage Manager
控制台修改相关的 SSM 参数。
一旦serviceless.yml
被修改,更新handler.js
为 WebSockets 路由创建 lambda 函数:$connect
with custom authorizer
, $disconnect
,sendMessage
:
运行以下命令来部署 WebSocket API:
$sls deploy --stage dev --region YOUR_REGION
使用 AWS Amplify 构建 React 应用程序
在本节中,我们将使用 React 和 AWS Amplify 构建一个具有身份验证功能的 web 应用程序。
完整的项目在我的 Github repo 中,你可以在项目目录中找到以下文件夹:
amplify/.config/
和amplify/backend/
。project-config.json
在.config/
文件夹中。backend-config.json
在backend/
文件夹中。backend/
文件夹中的云信息文件。
让我们下载源代码,并通过运行以下命令重新初始化现有的 Amplify 项目:
$amplify init
然后推送更改:
$amplify push
并部署:
$amplify publish
我们将在项目部署后获得 web 应用程序 URL:
现在,登录 AWS Cognito 服务控制台,您可以看到 AWS Cognito 用户池已经创建。复制用户池 Id 和应用程序客户端 Id,并将它们用作我们在上一步中已经创建的 SSM 参数。
在 AWS Fargate 中创建聊天机器人服务
在本节中,我们将创建一个 bot 任务,在 AWS Fargate 中运行我们的 chatbot 服务。首先,一个聊天机器人任务连接到一个 websocket API,然后,当用户提问时,机器人可以查询 Kendra 索引,Kendra 将显示相关答案,并将其发送回提问的用户。
要部署 Fargate 服务,请执行以下步骤:
- 点击 下载聊天机器人脚本和 Dockerfile 。
- 构建 Docker,标记一个 Amazon ECR 存储库,并将映像推送到 ECR。更多详情请参考 AWS 官方教程。
- 点击 下载 CloudFormation 模板和 bash 脚本 。
- 如果使用 Fargate 发射类型,则需要
awsvpc network
模式。我们需要部署VPC
和Security Groups
:
$bash create-infra.sh -d dev
5.创建任务定义。
$bash create-task.sh -d dev
6.在 AWS Fargate 中部署聊天机器人服务。
$bash deploy-service.sh -d dev
主要逻辑可以在这里找到:
(可选)用 ConvAI 模型扩展聊天机器人
要使用 ConvAI 模型扩展聊天机器人,您可以尝试下面的示例脚本,注意,您需要投入更多精力来训练模型,并将其放入 docker 或亚马逊 EFS 。
一旦服务被部署,我们应该能够问机器人问题。让我们访问 React 应用程序并进行现场测试吧!
如上所述,仅使用关键字就足以让系统给出正确的答案。
如果你想了解更多关于亚马逊 Kendra 的信息,这里 有一个关于如何使用 Lex 和 Kendra 构建聊天机器人的官方教程。
希望你觉得这篇文章有用,这篇文章的源代码可以在我的 GitHub repo 中找到。
使用潜在狄利克雷分配创建基于时间序列数据的推荐系统
使用经典的 NLP 主题建模技术,根据用户的习惯和偏好对他们进行聚类
卢西恩·阿利克夏在 Unsplash 上的照片
介绍
许多人认为,用户细分和推荐系统的主要目标是预测或更好地理解客户想要或可能购买的东西。然而,有时重要的问题不是顾客可能会买什么,而是什么时候他们可能会买。
考虑下面的例子:(1)一个在线商店想给它最忠实的顾客发送一个符合他们喜好的商品的优惠券。然而,他们也知道顾客通常在一天中的不同时间购物,例如,一些人喜欢在清晨购物,而另一些人喜欢在深夜购物。因此,他们想要确切地知道每个客户(或客户群)何时更有可能购物并在适当的时间发送优惠券。(2)网络代理服务的提供商需要有效地将网络带宽分配给他们的用户。理想情况下,他们会根据用户的活动时间对他们进行分组,并相应地为他们分配带宽。
这些“商业问题”已经假定用户或顾客想要某种产品。他们提出的问题是何时他们最有可能购买或使用它。在这篇文章中,我想分享一个非常简单的方法,它可以添加另一个工具来帮助你回答这样的问题。
我将假设您有一个简单的时间序列数据集,其形式为:
Time ('2020-01-05 10:30')
Entity (user, product, game)
Count (views, orders, downloads)
我将展示 LDA 如何使我们能够(1)根据用户更有可能“活跃”的时间,以一种颇有见地的方式将用户划分成组或簇,以及(2)让我们根据数据预测每个用户与每个组的关联程度。(同样的分析也可以应用于产品,并根据它们更有可能被购买的时间将它们分组,等等)。
在接下来的部分中,我将非常简要地介绍 LDA 及其运行方式,然后深入代码。
潜在狄利克雷分配(LDA)聚类——一个(非常)简短的介绍
LDA 最常用于 NLP 环境中的主题建模,这确实是一个很好的用例来理解它的价值。主题建模算法通常从一个“语料库”或一组由“单词”组成的“文档”开始,并尝试使用观察到的单词混合以及它们一起出现的频率,以便找到文档中的潜在模式或主题。
例如,假设我有 3 个文档:(1)“我的狗吃了我的午餐”;(2)“我就是爱吃水果”;(3)“我对狗过敏”。一个主题建模算法应该能够在这个“语料库”中识别至少两个潜在的主题:一个涉及狗的主题和一个涉及食物或者吃的主题。一些主题建模算法(如 LDA)也能够将一个文档与多个主题相关联,并告诉我们哪个主题在文档中更占主导地位。例如,这些算法将能够告诉我们,句子 1(“我的狗吃了我的午餐”)是既关于狗又关于食物或吃*,并且它更多地是关于狗而不是食物。*
那么 LDA 是如何做到这一点的呢?
LDA 至少做出两个重要的工作假设:
(1) *每个题目都是一个单词的概率分布。*简单来说,每个主题都与处理该主题的文档中以一定概率出现的某些单词相关联。LDA 模型的主要输出之一是术语-主题矩阵,它显示了每个单词在某个主题中出现的概率。这个矩阵允许我们在每个主题中找到语义主题。例如,如果下面矩阵中的单词 0 和单词 1 与动物有关,那么我们可以说主题 3(或其主题)是动物,因为与动物有关的单词很可能出现在其中。
术语-主题矩阵(或特征-聚类矩阵)
(2) *每个文档都有一个“主题食谱”或主题的概率分布。*这意味着,例如,在模型中运行句子 1(“我的狗吃了我的午餐”)将告诉我们,基于它包含的单词,该文档 80%关于食物和饮食,20%关于狗。
话题菜谱 sentence | topic-1 | topic-2 | topic-3 | s1 ____| 80% _____| 20% ____| 0% ____ | s2 ____| 50% _____| 30% ____| 20% ____ | s3 ____| 10% _____| 20% ____| 70% ____ |
当我们在某个语料库或某组文档上拟合 LDA 时,它本质上学习每个主题的哪个单词概率分布能够最好地解释(或生成)我们语料库中每个文档中的单词分布。更准确地说,在给定主题配方的情况下,经过训练的 LDA 模型可以再现它被训练的语料库(或者至少在语义上与之相似的东西)。更重要的是,经过训练或拟合的 LDA 模型可以预测模型在训练时看不到的文档的“主题食谱”。
照片由 Ugur Akdemir 在 Unsplash 拍摄
时间序列数据呢?
经过训练的 LDA 模型允许我们估计任何矢量化文档的“主题配方”。在 NLP 的上下文中,“文档”是文本块或单词的弓形向量,文档的主题食谱可以帮助我们找出文档的主导主题,或者哪个主题比其他主题更具主导性。
然而,归根结底,LDA 是一种聚类算法,也就是说,它估计一组具有 N 个特征的向量,并在每个向量中分配给这些特征的值中找到潜在模式。换句话说,如果我们把主题看作集群,把文档的主题配方看作向量的集群配方,告诉我们向量与每个集群的“关联”有多强,那么很明显,我们可以让 LDA 为 NLP 上下文之外的许多业务问题工作。
这似乎与时间序列分析的领域并不完全相关,所以让我直接进入一个例子,我将在这篇文章中使用这个例子来更清楚地说明这一点。
一个例子:用户和电视节目
假设您有一个“客户”数据集,它记录了每个客户在 24 小时内每小时观看的电视节目数量。因此,我们数据集中的每个向量看起来都像这样:
[customer, # of shows watched on 1AM, # of shows watched on 2AM….]
我们的任务是找到一种有效的方法来预测何时是向给定客户提供观看新电视节目的选项的最佳时间。显然,解决这个问题的方法不止一种。我在这里采用的方法是,尝试根据客户看电视的时间将他们分成不同的组,并根据他们最相关的组的偏好或活动来预测向客户提供新电视节目的最佳时间。
艾达能帮我们什么?
如果我们将一天中的每个小时视为一个特征,其值等于客户平均观看的电视节目数量,那么根据该数据估计 LDA 将使我们能够根据客户观看电视节目的时间将他们分成不同的组。
顾客与时间(价值=电视节目数量)
更重要的是,我们将能够生成一个特征聚类矩阵(或小时组矩阵),它将告诉我们哪个小时在哪个聚类中更重要(以及其重要性如何),此外,它还将为我们提供每个客户的聚类方法,它将告诉我们客户与每个组的“关联”有多强。请注意,虽然这项任务也可以使用其他聚类算法(如 KMeans)来完成,但是能够轻松地生成一个特征-聚类矩阵,该矩阵可以量化每个特征与一个聚类的关联的显著性,这是使用 LDA 的一个明显优势(虽然还有更多,但这里的讨论超出了我的范围)。
让我们编码
我们从这个数据集开始:
我们应该做的第一件事是将数据转换成我们想要处理的时间序列格式。
- 我们将时间列固定在数据帧上
df_raw['ts'] = pd.to_datetime(df_raw['ts'])
2.我们使用 pivot_table 方法转置它,以便为每个客户获得一行,每个小时(或时间箱)作为一个特征/列
df_pivot = pd.pivot_table(
df_raw,
index='customerid',
columns='ts',
values='shows',
fill_value=0)
3.最后,我们使用 Panda 的 GroupBy 来获得每个小时的平均值
df_avg = df_pivot.T.groupby(df_pivot.T.index.hour).mean().T
现在,我们有了正确格式的数据
当我们查看整个数据集每小时的平均观看次数时,我们确实看到了某种程度上预期的曲线,其中在黄金时段观看更多的电视节目,而在深夜时段观看较少。然而,正如我们将很快看到的,使用该数据作为何时提供新电视节目的最佳时间的指标忽略了许多偏好偏离平均值的客户。
平均每小时观看的电视节目
简单的魔术发生在这三行代码中
from sklearn.decomposition import LatentDirichletAllocation as LDAlda = LDA(n_components=3, learning_method='batch')lda = lda.fit(df_avg)
我们假设我们的客户的观看偏好可以分为 3 组,并且*适合()*我们数据上的 LDA 对象。而且,就是这样。我们现在需要做的就是提取数据中潜在的洞察力。
提取洞察力
LDA 产生的第一个也是最重要的洞察是术语-主题矩阵,或时间-聚类矩阵,它将告诉我们每个聚类中哪个观看时间更占优势。这个矩阵通常有助于检查集群是否有意义,或者是否需要进一步调整。
*注意,第一行将生成这个矩阵,但规范化后可读性更好,这就是后面几行的作用。
#Create the hour-cluster / term-topic matrix
df_comp = pd.DataFrame(lda.components_.T, index=df_avg.columns)#Normalize it norm_components = \
lda.components_ / lda.components_.sum(axis=1).reshape(-1, 1)df_comp_norm = pd.DataFrame(norm_components.T, index=df_avg.columns)df_comp_norm * 100
这是一个更精炼的版本:
我们可以清楚地注意到偏好“有意义”的群体。例如,我们可以说 cluster 0 描述了主要在晚上/深夜观看电视节目的客户——他们每天观看电视节目的时间有 40%的可能性(20% + 20%)是在晚上 8 点到午夜之间。我们还看到一个似乎由“每日”观察者(集群 1 )组成的群体,他们在黄金时段上午 8 点到下午 4 点看得最多。
我将很快回到这一点,但是一旦我们的聚类中的小时概率分布有意义,我们就可以使用 transform() 方法,该方法将产生向量-聚类(或客户-聚类)矩阵,该矩阵将显示每个客户与每个聚类的关联程度。
我们之前看到,与第 0 组第 T1 组第 T0 组相关联的主要时间是晚上,而与第 1 g 组第 T2 组相关联的主要时间是中午到下午。因此,我们可以说第一个顾客([0.79,0.14,0.06])主要在晚上看电视节目,而第二个顾客([0.36,0.62。0.01])白天大多看电视剧。如果我们可以选择一个时间段向我们的客户展示新节目,我们可能会选择晚上/夜间,因为尽管第二个客户主要在白天看电视,但他们仍有 36%的机会观看深夜节目。
我们可以通过将每个客户分配到其最主要的聚类,然后绘制每个聚类的平均值来说明这一点。
每个特征的平均值
我们也可以用这个来评估每个组的大小。这将向我们显示,例如,与有些异常的活动时间(集群 2)相关联的组是某种需要进一步探索的异常值(例如,它可能与来自不同时区的用户相关?)
在帖子的开始,我提到了我们需要回答的两个主要问题,或者说我们希望 LDA 帮助我们的两个主要见解:(1)我们希望知道每个组的黄金时段(他们观看最多的时段),以便向每个组的成员提供在他们更有可能观看新电视节目时观看该节目的选项。(2)给定客户的电视观看活动,我们想知道客户与哪个群体的关联有多强。
我们可以用一种相当简单的方法来实现第一个任务,那就是选择每个组或群的平均观看时间,然后找出值超过平均值的小时数。如下例所示,第一组人(守夜人)的黄金时段是下午 4 点到午夜。
至于第二个任务(找到向特定客户呈现电视节目的最佳时间),我们所要做的就是使用我们想要预测的客户的观看时间向量来调用 transform() 方法。
客户 120
我们的模型告诉我们,客户 120 最喜欢在晚上看电视,尽管他们在正常的白天也会花一些时间看电视。换句话说,虽然他们在晚上看更多的电视,但是给他们提供一个新的电视节目让他们在白天看也是值得的。我们可以通过检查他们的实际观看时间来证实这一点。
df_avg.iloc[customerid,:-1].plot.bar()
客户 120
事实上,我们可以看到向客户 120 展示新电视节目的最佳时间是晚上 10 点到凌晨 2 点,尽管他们在白天确实花了相当多的时间看电视。
摘要
总之,我们有相当多的工具可以根据用户的时间序列活动数据对他们进行聚类。我尝试展示了一个相当简单的方法,在分析此类问题时,它肯定可以扩展您的工具集,并轻松产生有价值的见解。
希望这是有帮助的!
你可以在这里找到完整的笔记本
关于 LDA 的一些不错的链接:
[## 潜在狄利克雷分配简介
假设你有下面这组句子:我喜欢吃西兰花和香蕉。我吃了一根香蕉和菠菜…
blog.echen.me](https://blog.echen.me/2011/08/22/introduction-to-latent-dirichlet-allocation/) [## LDA -如何网格搜索最佳主题模型?(带有 python 中的示例)
Python 的 Scikit Learn 提供了一个方便的接口,用于使用潜在的 Dirichlet 等算法进行主题建模。
www.machinelearningplus.com](https://www.machinelearningplus.com/nlp/topic-modeling-python-sklearn-examples/)
使用 Python 创建一个简单的搜索引擎
由 Unsplash 上的absolute vision拍摄
基于余弦相似度和 TF-IDF 加权的术语-文档矩阵的信息检索。
我们所有人每天都在使用搜索引擎,例如谷歌,来搜索一切,甚至是简单的东西。但是你有没有想过,搜索引擎是如何根据我们想要搜索(查询)的内容来检索我们所有的文档的?
在本文中,我将向您展示如何使用 Python 及其支持库从头构建一个简单的搜索引擎。在你看完文章后,我希望你能明白如何根据自己的需要来构建自己的搜索引擎。没有进一步,我们走吧!
**边注:**我还创建了一个代码的笔记本,所以如果你想跟着我,你可以点击这个链接这里。此外,我将使用的文件是在印度尼西亚。但是不用担心,你可以使用任何语言的文档。
概述
在我们动手之前,让我告诉你如何实现它的步骤,在每一部分,我将解释如何构建它。他们是,
- 准备文件
- 使用 TF-IDF 权重创建术语-文档矩阵
- 使用余弦相似度计算查询和文档之间的相似度
- 检索相似度最高的文章。
该过程
取回文件
我们要做的第一件事是从网上检索文件。在这种情况下,我们可以使用 web 抓取从网站中提取文档。我会从kompas.com搜集体育类的文件,尤其是关于流行的文章。由于文档使用的是 HTML 格式,我们初始化了一个 BeautifulSoup 对象来解析 HTML 文件,这样我们就可以更容易地提取我们想要的每个元素。
根据下图,我展示了带有 inspect 元素的网站截图。在图 1 中,我已经展示了我们想要检索的标签,这是带有类“most__link”的突出显示的标签的 href 属性。在图 2 中,我们将使用类“read__content”从
标签中检索
标签上的文本。
图 1,图 2
下面是我用来提取文档的代码以及每行的解释,
import requests
from bs4 import BeautifulSoup**# Make a request to the website**
r = requests.get('[https://bola.kompas.com/'](https://bola.kompas.com/'))**# Create an object to parse the HTML format**
soup = BeautifulSoup(r.content, 'html.parser')**# Retrieve all popular news links (Fig. 1)**
link = []
for i in soup.find('div', {'class':'most__wrap'}).find_all('a'):
i['href'] = i['href'] + '?page=all'
link.append(i['href'])**# For each link, we retrieve paragraphs from it, combine each** paragraph as one string, and save it to documents (Fig. 2)
documents = []
for i in link:
**# Make a request to the link**
r = requests.get(i)
**# Initialize BeautifulSoup object to parse the content**
soup = BeautifulSoup(r.content, 'html.parser')
**# Retrieve all paragraphs and combine it as one**
sen = []
for i in soup.find('div', {'class':'read__content'}).find_all('p'):
sen.append(i.text)
**# Add the combined paragraphs to documents**
documents.append(' '.join(sen))
清理文件
就在我们提取文档之后,我们必须清理它,这样我们的检索过程就变得容易多了。对于每个文档,我们必须删除所有不必要的单词、数字和标点符号,将单词小写,并删除加倍的空格。这是它的代码,
import redocuments_clean = []
for d in documents:
**# Remove Unicode**
document_test = re.sub(r'[^\x00-\x7F]+', ' ', d)
**# Remove Mentions**
document_test = re.sub(r'@\w+', '', document_test)
**# Lowercase the document**
document_test = document_test.lower()
**# Remove punctuations**
document_test = re.sub(r'[%s]' % re.escape(string.punctuation), ' ', document_test)
**# Lowercase the numbers**
document_test = re.sub(r'[0-9]', '', document_test)
**# Remove the doubled space**
document_test = re.sub(r'\s{2,}', ' ', document_test)
documents_clean.append(document_test)
使用 TF-IDF 权重创建术语-文档矩阵
每个文档都清理干净后,就该创建一个矩阵了。谢天谢地,scikit-learn 库已经为我们准备了它的代码,所以我们不必从头开始实现它。代码看起来像这样,
from sklearn.feature_extraction.text import TfidfVectorizer**# Instantiate a TfidfVectorizer object** vectorizer = TfidfVectorizer()**# It fits the data and transform it as a vector** X = vectorizer.fit_transform(docs)**# Convert the X as transposed matrix** X = X.T.toarray()**# Create a DataFrame and set the vocabulary as the index** df = pd.DataFrame(X, index=vectorizer.get_feature_names())
结果(矩阵)将成为文档的表示。通过使用这个矩阵,我们可以找到不同文档之间的相似性。矩阵看起来像这样,
术语-文档矩阵
上面的矩阵被称为术语-文档矩阵。它由所有文档中每个标记(术语)代表的行组成,列由文档的标识符组成。单元格内是每个词的频率数,用某个数字加权。
我们将使用列向量,这是一个表示每个文档的向量,用于计算与给定查询的相似性。我们可以称这个向量为嵌入。
为了计算单元格值,代码使用 TF-IDF 方法来完成此操作。TF-IDF(术语频率-逆文档频率)是由 IDF 加权的词的频率。让我解释一下每一个,
术语频率(TF) 是术语(t)在文档(d)上的频率。公式看起来像这样,
除此之外,我们可以使用基数为 10 的对数来计算 TF,因此数字变得更小,计算过程变得更快。此外,请确保在它上面添加一个,因为我们不希望 log 0 存在。
然后,就是逆文档频率(IDF) 。此公式将用于计算该单词在所有文档中的稀有度。它将被用作 TF 的权重。如果一个词比较频繁,那么 IDF 就会小一些。相反,如果这个词用得不频繁,那么 IDF 就会更大。公式看起来像这样,
回想一下 TF-IDF,我们可以看到它是如何影响每个单元格上的值的。它将删除文档中频繁出现但同时并不重要的所有单词,如 and、or、even、actually 等。基于此,我们用它作为矩阵中每个单元格的值。
使用余弦相似度计算相似度。
创建矩阵后,我们可以准备查询,根据文档和查询之间的最高相似度来查找文章。要计算相似度,我们可以使用余弦相似度公式来完成。它看起来像这样,
该公式计算点积除以每个向量上长度的乘积。该值的范围是从[1,0],但一般来说,余弦值的范围是从[-1,1]。因为上面没有负值,所以我们可以忽略负值,因为它从来没有发生过。
现在,我们将实现代码来基于查询查找文档的相似性。我们要做的第一件事是将查询转换成矩阵上的向量。然后,我们计算它们之间的相似度。最后,我们检索相似度值大于 0 的所有文档。代码看起来像这样,
def get_similar_articles(q, df):
print("query:", q)
print("Berikut artikel dengan nilai cosine similarity tertinggi: ") **# Convert the query become a vector**
q = [q]
q_vec = vectorizer.transform(q).toarray().reshape(df.shape[0],)
sim = {} **# Calculate the similarity**
for i in range(10):
sim[i] = np.dot(df.loc[:, i].values, q_vec) / np.linalg.norm(df.loc[:, i]) * np.linalg.norm(q_vec)
**# Sort the values**
sim_sorted = sorted(sim.items(), key=lambda x: x[1], reverse=True) **# Print the articles and their similarity values**
for k, v in sim_sorted:
if v != 0.0:
print("Nilai Similaritas:", v)
print(docs[k])
print()**# Add The Query**
q1 = 'barcelona'**# Call the function**
get_similar_articles(q1, df)
假设我们想找到关于巴塞罗那的文章。如果我们基于此运行代码,我们会得到这样的结果,
query: barcelona
Berikut artikel dengan nilai cosine similarity tertinggi:
Nilai Similaritas: 0.4641990113096689
kompas com perombakan skuad yang dilakukan pelatih anyar barcelona ronald koeman memakan korban baru terkini ronald koeman dikabarkan akan mendepak bintang muda barcelona yang baru berusia tahun riqui puig menurut media spanyol rac koeman sudah meminta riqui puig mencari tim baru karena tidak masuk dalam rencananya di barcelona rumor itu semakin kuat karena puig....Nilai Similaritas: 0.4254860197361395
kompas com pertandingan trofeo joan gamper mempertemukan barcelona dengan salah satu tim promosi liga spanyol elche laga barcelona vs elche usai digelar di camp nou pada minggu dini hari wib trofeo joan gamper merupakan laga tahunan yang diadakan oleh barca kali ini sudah memasuki edisi ke blaugrana julukan tuan rumah menang dengan skor gol kemenangan barcelona....
最后的想法
这就是我们如何使用 Python 及其依赖项创建一个简单的搜索引擎。它仍然非常基础,但我希望你能从这里学到一些东西,并能根据你的需要实现你自己的搜索引擎。谢谢你。
参考
[1] Jurafsky,D. & Martin,j . h .(2000),普伦蒂斯霍尔。
用 python 创建一个垃圾短信分类器
使用 scikit 的自然语言处理基础-学习
介绍
我一直对谷歌的 gmail 垃圾邮件检测系统着迷,它似乎可以毫不费力地判断收到的电子邮件是否是垃圾邮件,因此不值得我们的关注。
在这篇文章中,我试图重建这样一个垃圾邮件检测系统,但是是在 sms 消息上。我将使用几种不同的型号,并比较它们的性能。
这些模型如下:
- 多项式朴素贝叶斯模型(计数记号化器)
- 多项式朴素贝叶斯模型(tfidf 记号化器)
- 支持向量分类模型
- ngrams 参数的 Logistic 回归模型
使用训练测试分割,使 4 个模型经历 X 训练向量化、X 训练和 Y 训练上的模型拟合阶段,进行一些预测,并生成各自的混淆矩阵和接收器操作特性曲线下的面积,以进行评估。(AUC-ROC)
得到的表现最好的模型是逻辑回归模型,尽管应该注意的是,所有 4 个模型在检测垃圾邮件方面表现相当好(所有 AUC > 0.9)。
4 个模型之间的 AUC 得分比较
数据
数据是从 UCI 的机器学习库获得的,或者我也已经将使用的数据集上传到我的 github repo 上。该数据集总共有 5571 行和 2 列:spamorham 表示垃圾邮件状态和邮件文本。我发现这篇课文很有关联,这很有趣。
定义:垃圾邮件是指通常所知的垃圾邮件,ham 是指非垃圾邮件。
spam.head(10)
数据预处理
由于数据集相对简单,不需要太多预处理。垃圾邮件用 1 标记,而 ham 用 0 标记。
df.head(10)
探索性数据分析
现在,让我们详细看看数据集。取“目标”列的平均值,我们发现 13.409%的邮件被标记为垃圾邮件。
进一步说,也许消息长度与目标结果有某种关联?将垃圾邮件和 ham 消息分割成它们各自的数据帧,我们进一步添加消息的字符数作为第三列“len”。
分割的数据帧
EDA 代码
此外,取消息长度的平均值,我们可以发现 spam 和 ham 消息的平均长度分别为 139.12 和 71.55 个字符。
数据建模
现在是有趣的时候了。
列车测试分离
我们首先使用 75%训练测试分割的默认 sklearn 分割来创建训练测试分割。
计数矢量器
我们将 CountVectorizer 拟合到 X_train 上,然后使用 transform 方法进一步转换它。
计数矢量器代码
MNNB 模型拟合
我们先试着在 X_train 和 Y_train 上拟合一个经典的多项式朴素贝叶斯分类器模型 (MNNB)。
一个朴素贝叶斯模型假设它使用的每一个特征在给定某个类的情况下都是条件独立的。在实践中,朴素贝叶斯模型表现得令人惊讶地好,甚至在复杂的任务中,很明显强独立性假设是错误的。
MNNB 模型评估
在评估模型的性能时,我们可以生成一些预测,然后查看混淆矩阵和 AUC-ROC 分数来评估测试数据集的性能。
混淆矩阵生成如下:
MNNB 混淆矩阵
结果似乎很有希望,真阳性率(TPR)为 92.6% ,特异性为 99.7% ,假阳性率(FPR)为 0.3% 。这些结果表明,仅基于消息中的文本,该模型在预测消息是否是垃圾邮件方面表现得相当好。
受试者操作者特征(ROC) 曲线是二元分类问题的评价尺度。这是一条概率曲线,描绘了在不同阈值下 TPR 与 FPR 的关系,并且基本上将‘信号’与‘噪声’分开。曲线下的面积(AUC) 是分类器区分类别的能力的量度,并用作 ROC 曲线的总结。
图片来自本文
该模型产生了 0.962 的 AUC 分数,这明显好于该模型对结果进行随机猜测的情况。
虽然多项式朴素贝叶斯分类器似乎工作得很好,但我觉得通过不同的模型,结果可能会进一步改善
用于拟合和评估的 MNNB (count_vect)代码
MNNB(Tfid-矢量器)模型拟合
然后,我尝试使用一个 tfidf 矢量器来代替计数矢量器,看看它是否能改善结果。
使用 tfidf 的目标是按比例缩小在给定语料库中非常频繁出现的标记的影响,因此这些标记在经验上不如在一小部分训练语料库中出现的特征信息丰富。
MNNB(Tfid-矢量器)模型评估
在评估模型的性能时,我们再次查看 AUC-ROC 数和混淆矩阵。它产生了 91.67%的 AUC 分数
结果似乎很有希望,真阳性率(TPR)为 83.3% ,特异性为 100% ,假阳性率(FPR)为 0.0%。
tfid 混淆矩阵
当基于 AUC 分数比较两个模型时,似乎 tfid 矢量器并没有提高模型的准确性,甚至在预测中引入了更多的噪声!然而,tfid 似乎大大提高了模型检测 ham 消息的能力,达到了 100%的准确率。
用于拟合和评估的 MNNB (tfid_vect)代码
作为一个固执的人,我仍然相信通过一些调整可以获得更好的性能。
SVC 模型拟合
我现在尝试使用 Tfidf 矢量器来拟合和转换训练数据 X_train,同时忽略文档频率严格低于 5 的术语。进一步添加一个附加特征,文档的长度(字符数),然后拟合一个正则化 C=10000 的支持向量分类(SVC)模型。
SVC 模型评估
这将导致以下结果:
- AUC 得分为 97.4%
- TPR 为 95.1%
- 特异性为 99.7%
- 0.3%的 FPR
SVC 混淆矩阵
SVM 装配和评估规范
逻辑回归模型(n-grams)拟合
使用逻辑回归,我还包括使用 ngrams,它允许模型在考虑消息是否是垃圾邮件时考虑最大大小为 3 的单词组。
逻辑回归模型(n-grams)评估
这将导致以下结果:
- AUC 得分为 97.7%
- TPR 为 95.6%
- 特异性为 99.7%
- 0.3%的 FPR
模型比较
在对这 4 个模型进行训练和测试之后,是时候对它们进行比较了。我主要基于 AUC 分数比较它们,因为 TPR 和 TNR 比率都有些相似。
逻辑回归具有最高的 AUC 分数,SVC 模型和 MNNB 1 模型略微落后。相对而言,MNNB 2 型号的表现似乎不如其他型号。然而,我仍然认为,所有 4 个模型产生的 AUC 分数都远高于 0.5,表明所有 4 个模型的表现都足以击败仅随机猜测目标的模型。
4 个模型之间的 AUC 得分比较
感谢你的阅读!
请在此找到代码。
如果你有问题或者想讨论在后新冠肺炎时代应用数据科学技术的想法,请随时联系我。
在世界上最大的职业社区 LinkedIn 上查看韩德·c 的个人资料。韩德有两个工作列在他们的…
www.linkedin.com](https://www.linkedin.com/in/dehan-c-948045177/)
这里还有一篇文章给你!
单词云和条形图中的新加坡#GE2020SG。
medium.com](https://medium.com/@thedehan/pre-elections-sentiment-analysis-880bc5ad1db0)
用 Python 创建股票价格模拟器
几何布朗运动过程的简单应用来模拟股票价格
马库斯·温克勒在 Unsplash 上的照片
来自《走向数据科学》编辑的提示: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们并不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
在本文中,我将尝试简要解释一种模拟股票价格的方法,这是在寻求减少金融投资的暴露和风险的过程中与金融建模过程相关的研究的结果。
在这种情况下,我利用几何布朗运动 (GBM)过程来模拟资产收益的随机路径,特别是股票。
理解模型的原理:
- 根据这个模型,波动率在股票交易的连续交易期内保持不变**。**
- 预期收益对股票的表现有独立的行为。
- 另外,回报是正态分布,也就是说大规模(指几十万或者几百万)计算,回报趋向于平均值为 0,标准差为 1。
本质上,股票价格在每个交易周期都会有一系列回报,我们正试图以恒定利率复制这种行为,这通常也称为“漂移”,我们在资产价格中添加随机的正或负偏差,也称为“冲击”。
事实证明,所有这些概念都可以很容易地反映在一个 Python 代码中,以利用计算能力的优势,让我们在几毫秒内完成数千次计算。
在这段代码中,我只使用了 Python 的标准库中的模块,这意味着可以通过实现其他库(如 Numpy)来提高计算效率。
- 首先,继续导入数学和随机数生成器库。
- 其次,编写自动计算股票价格的函数,当然是通过 GBM 过程的应用。
- 最后,以达到某个目标为目标,执行一个由数千个模拟组成的循环,在其中模拟股票价格。在我的例子中,130 美元是从最初的 100 美元开始的理想价格,如果资产的随机行为不允许,这肯定是无法达到的。
说实话,尽管这种模型在金融领域有无数的应用,但当用于真实交易场景时,它往往会显示出的缺点,因为它的主要假设是恒定预期收益和恒定波动率,而实际上这并不是现实。
为了评估模型的这些低效率,最好将这些参数建模为随机过程,这意味着它们是独立分布的,与资产的表现无关。
毫无疑问,有很多像这样的编程技能的金融应用,由于技术的使用,这些应用很容易实现。为这个生态系统的发展做出贡献是我们挑战的一部分。
感谢您花时间阅读我的文章!如果您有任何问题或想法要分享,请随时通过我的电子邮件联系我,或者您可以在以下社交网络中找到我以了解更多相关内容:
在 30 小时或更短时间内创建一个监督模型
构建机器学习模型的 8 个步骤
TL;速度三角形定位法(dead reckoning)
- 加载用于进行预测的数据
- 调查数据
- 选择模型的功能
- 将数据拆分到训练和验证集合
- 预处理数据
- 训练模型
- 使用验证集测试模型
- 重复步骤 2 到 7,直到您对模型的准确性感到满意
这个帖子是在以色列最大的高级女性工程师和计算机科学家社区的 #30_hours 计划期间创建的。在 30 小时计划中,参与者投资 30 小时(超过 4 个月)在一个新的领域加深他们的知识,通过与专业导师一起建立一个个人或小组项目。
加载数据
在现实世界的场景中,您可能需要从收集数据开始。我们将跳过这一步,在本文中使用 Kaggle 房价数据集。
房屋数据的部分数据框架
在这个数据集中,我们既有房子的数据——比如房子的状态、位置和出售时间的数据——也有房子的售价。
我们可以使用监督学习训练一个模型,将给定的输入(称为特征,如房屋状况和位置)映射到给定的输出(称为标签,如销售价格)。
首先,让我们使用 pandas 来读取 csv 文件。标签由y
表示:
import pandas as pdhouses_df = pd.read_csv(PATH_TO_TRAIN_DATA)
LABEL = 'SalePrice' # let's make this a constant for future usage
y = houses_df[LABEL]
接下来,我们将了解哪些特征可以帮助我们预测房屋的价格。
调查数据
那需要一段时间!
在选择特性之前,我们需要了解我们的数据是什么样的。让我们从数据列开始:
print(houses_df.columns)"""
Output:
Index(['Id', 'MSSubClass', 'MSZoning', 'LotFrontage', 'LotArea', 'Street', …, 'YrSold', 'SaleType', 'SaleCondition', 'SalePrice'],
dtype='object')
"""
我们有 80 列可以帮助我们预测销售价格。让我们仔细看看每一列。我们将使用两种方法来调查我们的数据:
- value counts() 获取唯一值的计数(包括
NA
值,因为我们想知道我们的列包含多少个空值) - describe() 根据数据类型生成描述性统计
在下面的示例中,我们可以看到“Street”有两个唯一的值,并且几乎都是“Pave”。我们还可以看到大多数“小巷”值都不见了。由于这些数据列没有变化,我们无法了解不同街道或小巷的价格差异。
for col in houses_df.columns:
print(f'_____Column: {col}_____')
# normalize=True - use relative frequencies of the unique values
# dropna=False - include NA values
print(houses_df[col].value_counts(normalize=True, dropna=False))
print(houses_df[col].describe())"""
Output:
_____Column: Street_____
# value_counts:
Pave **0.99589**
Grvl 0.00411
Name: Street, dtype: float64# describe:
count 1460
unique 2
top Pave
freq 1454
Name: Street, dtype: object_____Column: Alley_____
# value_counts:
**NaN** 0.937671
Grvl 0.034247
Pave 0.028082
Name: Alley, dtype: float64# describe:
count 91
unique 2
top Grvl
freq 50
Name: Alley, dtype: object
"""
为了简化调查数据的过程,您可以使用 Kaggle 上为该数据集提供的可视化来获得每个数据列的更多信息。你也可以在这里看看我的代码示例。
点击数据选项卡,向下滚动并选择 train.csv 查看可视化|来源:Kaggle
选择模型的特征
我们希望只选择有助于预测房屋价格的特征,以便降低计算成本并提高模型的性能**—这个过程称为特征选择。**
选择,选择…!
对于这个例子,我们将简化这个过程,但是你可以阅读更多关于特征选择和如何识别相关特征的内容。
下面是一个简化的特征选择示例。特征由X
表示:
include_features = ['MSSubClass', 'MSZoning', 'LotFrontage', ..., 'MoSold', 'YrSold']
X = houses_df[include_features]
拆分数据
模型的工作是在数据中寻找模式,以便预测标签——模式来自模型训练的数据。为了对模型的准确性进行公正的评估,我们需要根据它没有训练过的数据来验证它。
为此,我们将数据分成(至少)3 个部分:
- 训练集-用于训练模型的数据
- 验证集—在调整模型的超参数(模型的属性)并选择性能良好的模型时用于评估模型的数据—该集仅用于调整模型的超参数,其数据不应用于训练模型!
- 测试集——用于评估最终模型的数据——它在模型训练期间对模型没有影响,因此是无偏的
因为我们使用的是 Kaggle 竞争数据集,所以我们已经在一个不同的文件(test.csv)下提供了一个测试集。我们只需要将训练集分成训练和验证。
我们使用 train_test_split 将数据分成两部分。
稍后,我们将看到验证集如何帮助我们调整模型。
from sklearn.model_selection import train_test_splitX_train, X_valid, y_train, y_valid = train_test_split(X, y, train_size=0.8, test_size=0.2, random_state=1)
random_state 值被设置为某个常数,以避免训练模型时的随机性。
预处理数据
我们使用 Python 中的机器学习库 scikit-learn 来创建模型。Scikit-learn(或 sklearn)期望数据是数字的和有意义的**。真实世界的数据可能有缺失值,或者可能包含非数字值(分类值、图像等),因此与 scikit-learn 不兼容。**
对对对。
在我们可以训练模型之前,我们需要准备数据,以便我们可以将它馈送给 scikit-learn。这一步叫做——你猜对了——预处理!
我们如何处理丢失的值?
- 最简单的方法是删除缺少数据的要素/条目。这会导致可能对更准确的预测有价值的数据丢失,因此不建议这样做
- 输入现有数据中的缺失值,例如,输入特征的平均值。分类特征没有“平均值”——我们可以使用“最频繁”策略来填充缺失值(我们使用的是 SimpleImputer ):
from sklearn.impute import SimpleImputer# allowed_strategies = ["mean", "median", "most_frequent", "constant"]
numerical_imputer = SimpleImputer(strategy='mean')
categorical_imputer = SimpleImputer(strategy='most_frequent')
我们如何处理分类数据?
我们希望将分类数据编码成数字数据**。我们可以使用不同的编码器。例如,我们可以使用带有标签编码的类别排序。如果类别没有排序,我们可以使用一键编码,它为每个类别创建一个新的特性,并用布尔值填充它。阅读更多关于清洁和预处理数据的信息。**
标签编码(左)和一键编码(右)|来源:Kaggle
为分类值创建一个编码器—在本例中,我们将使用 OneHotEncoder,但选择可以而且应该根据您的数据而有所不同:
from sklearn.preprocessing import OneHotEncoderone_hot_encoder = OneHotEncoder(handle_unknown='ignore')
您可以更进一步,预处理数字数据来创建一个更加精确的模型!****
拟合模型
差不多到了适合模型的时候了!
我们看到了如何估算缺失值和编码分类值。让我们在一个管道中定义这些步骤,使我们的代码更干净,更容易调试。
我们为数据中的每个列类型定义了一个管道,在我们的例子中,我们需要处理数字和分类数据:
from sklearn.pipeline import Pipeline
# impute and scale
numerical_transformer = Pipeline(steps=[
('imputer', numerical_imputer),
('scaler', StandardScaler())
])# impute and encode
categorical_transformer = Pipeline(steps=[
('imputer', categorical_imputer),
('onehot', one_hot_encoder)
])
很好,我们现在为每种列类型都提供了一个管道。让我们为数据列捆绑这些预处理步骤:
from sklearn.compose import ColumnTransformer# get columns from X_train
numerical_cols = get_numerical_columns(X_train)
categorical_cols = get_categorical_columns(X_train)preprocessor = ColumnTransformer(
transformers=[
('num', numerical_transformer, numerical_cols),
('cat', categorical_transformer, categorical_cols),
])
注意,在这个例子中,我们通过数字/分类数据捆绑了预处理步骤——实际上,您可能希望使用与数据列最匹配的步骤。在研究数据时,您应该看到哪些预处理步骤最适合不同的列**,而不是使用“一刀切”的方法。**
现在我们已经为训练集定义了预处理,我们可以用它来训练我们的模型了!
但是等等…
您可能会问自己——我们不应该预处理所有的数据,而不仅仅是训练集吗?
答案肯定是否定的!如果我们基于所有数据进行预处理,我们将深入了解我们正在验证的数据,从而导致假阳性评估!包括来自列车组外部的信息被称为数据泄漏。
现在让我们使用管道来拟合模型!
受监督的模型可以是分类模型,它输出一个离散的结果,如预测一封电子邮件是否是垃圾邮件,也可以是回归模型,它输出一个连续的结果,如预测房价。阅读更多关于常见 ML 型号的信息。
我们将使用随机森林回归模型——决策树的集合。
决策树示例|来源:Kaggle
定义预处理和拟合随机森林回归模型的管道:
from sklearn.ensemble import RandomForestRegressormodel = RandomForestRegressor(n_estimators=ESTIMATORS_VALUE, random_state=1)pipeline = Pipeline(steps=[
('preprocessor', preprocessor),
('model', model)
])
还记得验证集吗?
这是我们最终使用验证集的地方。
n_estimators
是 RandomForestRegressor 模型的数值型超参数**。我们可以使用不同的n_estimators
值根据验证集创建和评估我们的模型,最终选择最接近验证数据上实际标签的预测值——这样做会导致我们的模型被验证集调整,这就是为什么我们需要一个测试集,一个模型没有见过或已经被调整过的数据集。n_estimators
也用于控制示例模型中的欠拟合和过拟合。**
现在,我们可以使用之前定义的所有步骤,使用该管道来拟合我们的模型:
pipeline.fit(X_train, y_train)
啊啊啊……我们终于有一个合身的模型了!
啊哈。
测试模型
模型能在没见过的数据上成功预测房价吗?让我们使用损失函数来测试这个模型——这个函数可以帮助我们计算原始标签和预测标签之间差异的“成本”,从而帮助我们估计这个模型有多精确。
我们可以使用的一个常见损失函数是 MAE ( 平均绝对误差),它计算原始标签和预测标签之间的绝对差异——较低的 MAE 分数意味着对验证数据的预测更好。
from sklearn.metrics import mean_absolute_errorpredictions = pipeline.predict(X_valid)
mae_score = mean_absolute_error(y_valid, predictions)
你可以玩不同的超参数值,特征,模型和预处理步骤,看看模型的分数如何变化。
下一步是什么?
现在你已经有了一个满意的模型,你可以将预测保存到一个. csv 文件,上传到 Kaggle,然后继续下一个挑战!****
output = pd.DataFrame({'Id': house_df.Id, label: LABEL})
default_filename = f'submission-{mae_score}'
output.to_csv(f'{filename}.csv', index=False)
你可以在这篇文章的末尾找到完整代码的链接。
你做到了!
总结我们所学的内容
- 基本术语(参见备忘单)
- 如何用熊猫调查数据(见 100 个熊猫小窍门
- 为什么我们需要至少 3 组数据
- 如何用 skicit-learn 对数据进行预处理
- 分类模型与回归模型有何不同**
- 如何使用 skicit-learn 创建管道
- 什么是平均绝对误差以及我们如何使用它来测试模型
如果这篇博文对你有帮助,请随意与你的朋友分享!
完整代码见此处。
创建一个合成图像数据集——“什么”、“为什么”和“如何”
缺少图像来训练你的模型?以下是如何使用图像合成技术通过合成图像将数据集的大小增加数倍。
把你的狗送上月球!图像合成技术的一个例子(来自 Pexels 的海伦娜·洛佩斯和皮克斯拜的原始照片)
众所周知,用于训练模型的数据集的质量和数量将直接影响模型的性能。一个广泛、通用的数据集的可用性可以达成协议,你可以跳到你的机器学习/深度学习管道的下一步。但是,您可能经常会遇到这样的情况:您需要的数据集并不容易获得。或者你所拥有的数据不足以训练一个重型模型。现在你做什么?
有许多资源可以帮助您创建任何所需对象类的新自定义数据集。但是如果我必须用一个词来描述构建数据集的过程,我会称之为“繁琐”、“耗时”和“令人沮丧”——我知道我用了不止一个词,但是你明白我的意思了!
尤其是在画分割蒙版的时候,我就是懒得去注释超过几张图片的东西!不要误解我,我知道数据集创建是一个非常非常非常重要的步骤,但是难道没有解决的办法吗?
数据扩充是增加你的模型看到的数据集的多样性的一个很好的方法,但是同样,它的帮助是有限的。不如我们更进一步?
什么是合成数据集?
创建任何类型的数据(图像、音频、文本等。)“人工地”或“程序地”产生我们所说的合成数据集。这些数据不是自然或正常收集的,也不是手动标记的,所以用它来训练你的模型安全吗?会有好的结果吗?
虽然有许多论文声称精心创建的合成数据可以提供与自然数据不相上下的性能,但我建议将两者健康地结合起来。设计良好的合成数据集可以将数据扩充的概念提升到下一个级别,并为模型提供更多种类的训练数据。越多越好,对吗?
创建合成影像数据集有多种方法,在本教程中,我们来看看最基本的方法之一——影像合成。我们将通过将目标图像作为前景合成在多个背景图像上来生成新的图像。
在本教程中,我将为输出类“dog”创建合成图像。事实上,网上有许多现有的数据集包括狗类(例如,可可),但创建更多这些大自然可爱礼物的图片有什么坏处呢?😛
1.进口
看看下面的导入语句。安装任何你可能还没有的模块。
import os
import numpy as np
import skimage.io as io
import skimage.transform as transform
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
%matplotlib inline
2.对象—前景
有两种方法可以解决这个问题—
(A)创建自己的数据集
首先,让我们拍一张网上可以买到的狗的照片。有几个网站允许你免费使用这些图片,比如 pexels 、 flickr 、unsplash——随你挑。我要用下面这个。
照片由 Matheus Bertelli 从 Pexels 拍摄
下一步,你将不得不投入一点体力,把狗从背景中分离出来。是的,很抱歉——没有免费的午餐。但最终这肯定比创建一个完整的数据集要简单,我保证。
我所知道的完成这项工作的几个工具是 Photoshop (付费)或 GIMP (免费)。或者你甚至可以使用永远可靠的微软油漆!最终输出如下所示。
狗的分段图像
阅读图像。接下来,从这个图像中剪切出前景层,并将剩余的像素设置为零。编码这一步的另一种方法是在分割图像本身时,用你使用的工具(GIMP/Paint/Photoshop)添加一个黑色背景。但尽管如此,下面是如何在 python 中提取前景对象——简单的像素阈值处理。
# Read the image
I = io.imread('./dogSeg.jpg')/255.0# Cut out the foreground layer
foreground = I.copy()
foreground[foreground>=0.9]=0 # Setting surrounding pixels to zeroplt.axis('off')
plt.imshow(foreground)
plt.show()
周围像素设置为零,前景层保持不变
(B)使用现有数据集
如果您不想从头开始,另一种选择是利用现有数据集中的图像。
我将在这里使用 COCO 数据集来演示。既然 COCO 已经有了对象类别“狗”,那么检索图像和它的遮罩就很容易了。COCO 数据集对于“狗”类别具有 4385 个(训练)和 177 个(val)图像。
对于本教程,你可以参考我的 GitHub 库中这个过程的全部代码。在这篇文章中,我将不再赘述这一步的代码。
可可图片(左)及其标注(右)
分割蒙版(左)和剪切出的前景层(右)
如果你对操作 COCO 图像数据集和创建一个数据生成器来训练你的图像分割模型感兴趣,我这里有一个广泛的教程。
3。增强前景
让我们和狗玩一会儿(双关语)。我在代码中使用了随机旋转、随机缩放、随机平移和随机水平翻转,但是你也可以使用其他方法。
代码的输出如下所示。看它和原图有多不一样!
增强前景图像
将所有这些变化应用到前景后,让我们从图像中提取分割蒙版。
增强前景的分段遮罩
4.背景
现在你需要一个新的背景图片。使用我前面提到的免费网站来获得各种各样的背景。你可以选择世界上的任何图像(见本文展示图片中我是如何把我的狗送上月球的),但我建议尽量保持逼真。
我将使用这 4 张图片作为本教程的背景。
**
来自 Pexels 的创意 Vix 、皮克斯拜和内森考利的照片
让我们随机选择一个背景。
*# Random selection of background from the backgrounds folderbackground_fileName = np.random.choice(os.listdir("./backgrounds/"))
background = io.imread('./backgrounds/'+background_fileName)/255.0*
5.最后:合成前景和背景
是时候把你的狗图像添加到背景中了!
该函数给出以下输出。现在,我知道它并不完美,但它相当不错!
最终合成的图像
对于对象定位任务,您也可以从我们开发的新分割遮罩中轻松获得框坐标。
图像上标记的对象框
在所有背景下循环执行这些功能,我们得到了一组漂亮的图像!
一只狗在多种背景下的合成图像
在本教程中,我使用了 1 个前景和 4 个背景。如果你随机使用多种背景和多种前景,你可以创造出很多很多的图像!也许你也可以在一个背景上合并两个或更多的前景。发挥创意——根据您的需求,调整大小、角度、前景和背景,构建一个令人惊叹的合成数据集。这里也有很多设计上的考虑,但是只需一点点努力,你就可以做得更多,创建更精确的数据集。
最后,你可以在我的 GitHub 资源库 中找到本教程的完整代码。
作为这个主题的下一步,看看这个关于用 Unity 3D 创建合成图像数据集的漂亮的教程。
好了,现在就到这里——谢谢你一直阅读这篇文章。我希望会有好的结果。有什么想法,问题,评论吗?请在下面的回复中告诉我!
如果你对语义分割的图像数据集感兴趣,可以看看我下面的帖子:
使用 PyCoco、Tensorflow Keras Python…探索和操作 COCO 图像数据集进行语义图像分割
towardsdatascience.com](/master-the-coco-dataset-for-semantic-image-segmentation-part-1-of-2-732712631047)
还是想在股票上用 ML 一夜暴富?这篇文章(不)适合你!
股票和机器学习——天作之合。但是事情真的像看起来那么简单吗?
towardsdatascience.com](/how-not-to-predict-stock-prices-with-lstms-a51f564ccbca)
ML 模型真的能读懂股价图吗?
股票和机器学习——天作之合。如果你的 ML 模型可以从字面上阅读价格图表…
towardsdatascience.com](/can-an-ml-model-read-stock-charts-and-predict-prices-fb73c551c7a4)*
创建一个电报机器人来帮助你学习一门新的语言
网络抓取和谷歌文本到语音的 API 来拯救
莱昂纳多·大久保俊郎在 Unsplash 上的照片
介绍
由于新冠肺炎疫情爆发,我在家有很多空闲时间,所以我试着学习一项新技能。上周我决定开始学习韩文(韩文字母)。
为了阅读和说韩语,你首先需要理解韩文,但有时韩文的书写方式与我们的发音不同。
学习如何发音某个韩国语单词的一种方法是通过在谷歌翻译中复制这些单词并听如何发音。
GIF 1:利用谷歌翻译功能(音频)学习韩文发音
但这似乎很累人,因为我们需要不断地从一个应用程序转移到另一个,并做一些复制粘贴。
在本教程中,我们将构建一个电报机器人,它将帮助我们以一种简单的方式实现我们的目标(学习如何发音韩语单词)。
我们将抓取一个韩语网站(在本例中是 BBC 韩国 ) →获取一些单词→使用谷歌文本到语音转换 API 创建关于如何发音的音频文件→保存它。然后,机器人会发送单词和音频文件来帮助我们学习如何阅读韩文和发音。
这是我们将要创建的一个机器人的例子。
GIF 2:机器人的例子
看起来很酷吧?我们开始吧!
PS:如果你正在学习其他语言,你也可以修改脚本来学习如何用你的首选语言发音某些单词。
入门指南
1.安装库
我们将使用 Requests 和 BeautifulSoup 来抓取网站,使用Google Text-to-Speech API来创建关于如何发音韩文的音频,使用 Pandas 来帮助我们处理数据,使用 python-telegram-bot 来创建机器人。
pip install requests beautifulsoup4 google-cloud-texttospeech pandas python-telegram-bot
2.启用 Google 文本到语音转换 API 并设置凭证
转到谷歌文本到语音转换 API 指南。在开始部分之前的中,遵循指南,直到在步骤 5 中完成环境变量的设置。
在这一步之后,您应该有一个格式为.json
的凭证(在本教程中,我们将其命名为creds.json
),并且您应该有一个指向您的creds.json
路径的环境变量GOOGLE_APPLICATION_CREDENTIALS
。
3.在 BotFather 中创建新的机器人
如果你想在 Telegram 中制作一个机器人,你必须在使用它之前先注册你的机器人。当我们注册我们的 bot 时,我们将获得令牌来访问 Telegram API。
转到机器人父亲,然后通过发送/newbot
命令创建一个新机器人。遵循这些步骤,直到您获得您的 bot 的用户名和令牌。您可以通过访问这个 URL: [https://telegram.me/YOUR_BOT_USERNAME](https://telegram.me/YOUR_BOT_USERNAMEa)
来访问您的 bot,您的令牌应该如下所示。
704418931:AAEtcZ*************
写程序
我们将为本教程创建两个脚本。第一个用于准备数据集(抓取网站、创建音频和保存数据),第二个用于运行机器人。
1.准备数据集
让我们为这个任务导入必要的依赖项。
from google.cloud import texttospeech
from bs4 import BeautifulSoupimport pandas as pd
import requests
import re
我们将从 BBC 韩国抓取特定页面,即头条新闻页面并获取新闻标题。
图 1: BBC 韩国-头条新闻
如果我们看看 Google Chrome inspect 元素,每个标题都被包装在 span 元素和most-popular-list-item _ _ headline类中。这是使用 BeautifulSoup 抓取特定元素的代码。
url = '[https://www.bbc.com/korean/popular/read](https://www.bbc.com/korean/popular/read')'
page = requests.get(url)
soup = BeautifulSoup(page.content, 'html.parser')
titles = soup.findAll('span',
{'class': 'most-popular-list-item__headline'})
现在我们迭代titles
,获取新闻标题,拆分成文字,追加到一个列表中。我们使用正则表达式删除标题中的任何标点符号。
result = []for title in titles:
title = re.sub(r'[^\w\s]', '', title.text)
words = title.split()
result += words
将上面的代码包装到一个名为get_hangeul
的函数中,这样您的代码看起来就像这样。
请注意,我们使用return set(result)
是因为我们希望列表具有惟一的值,我们可以使用Python Set来实现这一点。
在我们获得 Hangeul 之后,我们将使用 Google 文本到语音 API 为每个单词创建音频文件,并将其保存在一个名为audio
的文件夹中。
我在创建音频数据部分使用了谷歌文本到语音快速入门指南中的代码。我们稍微修改一下,把代码包装成带text
(韩语单词)和language
(默认为 ko-KR,是韩语)的create_audio
函数,将音频保存在audio
文件夹中。
现在创建调用get_hangeul
的主函数,遍历其结果并保存音频文件,同时保存名为dictionary.csv
的.csv
格式的韩语单词列表。
words = get_hangeul()for word in words:
create_audio(word)dictionary = pd.DataFrame(words, columns=['word'])
dictionary.to_csv('dictionary.csv', index=False)
使用这些主函数,包装上面的所有代码,并将其保存为dataset.py
。您的文件应该如下所示。
酷!从终端运行脚本(不要忘记首先在与dataset.py
相同的路径中创建文件夹audio
)。
python dataset.py
运行脚本后,您将会看到,我们在audio
文件夹和dictionary.csv
中有.mp3
文件。
太好了!数据集准备好了,让我们创建机器人。
2.创建电报机器人
我们的机器人如何工作非常简单。每次用户发送/word
命令时,我们将从dictionary.csv
中随机抽取一个字,并与相应的.mp3
文件一起发送。
首先,导入库并设置日志功能(这是为了在遇到错误时调试 bot)。
from telegram.ext import Updater, CommandHandlerimport pandas as pd
import logging logging.basicConfig(level=logging.DEBUG,
format='%(levelname)s - %(message)s')
logger = logging.getLogger()
logger.setLevel(logging.ERROR)
让我们为机器人的主要任务创建一个函数。在这个函数中,机器人将读取dictionary.csv
文件,随机选取一个单词,然后将这个单词和音频文件发送回用户,并将其包装在一个名为send_word
的函数中。
现在创建一个主函数来运行机器人。
当我们写CommandHandler('word', send_word))
时,这意味着每次用户发送命令/word
给机器人,它将运行send_word
功能。
将所有这些代码合并到一个名为main.py
的文件中。您的文件应该如下所示。
现在您可以在终端中运行main.py
文件。
python main.py
如果一切运行正常,您应该看到您的机器人在您向机器人发送了/word
命令后发回了单词及其音频。
恭喜你!不难吧?现在你有了一个帮助你学习新语言的电报机器人,酷!
进一步发展
我知道这远非完美,所以如果你想进一步开发这个机器人,让它变得更酷,这里有一些建议。
- 使用 cron job 或 python-telegram-bot 作业队列自动抓取网站,这样字典就会扩展。
- 添加功能,机器人将发送这个词,我们必须发送我们的声音(使用语音笔记)发音,然后使用谷歌语音到文本 API 我们将验证我们是否发音正确或错误。
- 更多…
你可以访问我的 GitHub 个人资料获取代码或者在这里查看工作机器人。
如果您有任何问题,请随时联系我,并在我的 Linkedin 个人资料中留言。
如果你对数据科学或机器学习感兴趣,你可能想看看我关于构建情感分析器和使用 Python 自动化任务的帖子。
再次感谢你,祝你好运!😃
从代码创建一个 YouTube 视频
用 C++演示创建分形缩放
由沃尔夫冈·拜尔用超分形 3 程序创建。( CC BY-SA 3.0
如果你是一名计算机程序员,曾经想过创建一个包含计算机生成动画的视频,那么这篇文章就是为你准备的。在这里,我假设您已经有代码,或者可以编写代码,将某种图像创建为二维像素数组。它是什么样的图像并不重要,只要它适合内存中的数组。
如果你能做到这一点,这篇文章将带你走完剩下的路。您将了解如何创建 MP4 视频文件的详细步骤。当我们完成后,你将有一个适合上传到 YouTube 的视频文件,就像这样:
Mandelbrot 设置缩放视频由作者生成。
计划概述
以下是创建计算机生成视频的步骤概要。
- 将生成图像的 C++代码写入内存数组。我将使用一个简单的 Mandelbrot 集合图像生成器,但同样,这可以是你想要的任何东西。
- 使用开源库 LodePNG 将该图像保存到磁盘上的 PNG 文件中。
- 这段代码重复前两步数百次,一次生成一个视频帧。每个 PNG 输出文件为您的电影保存一个静态帧图像。
- 在 Windows 或 Linux 上,使用 ffmpeg 将一系列 PNG 图像转换为 MP4 视频格式文件。
Mandelbrot 集合图像
Mandelbrot 集合是最著名的分形物体之一。上面的视频将曼德布洛特集合的放大倍数从 1 倍逐渐增加到 1 亿倍。该视频以每秒 30 帧的速率持续 30 秒,总共快速连续播放了 900 幅图像。
值得注意的是,如此多的视觉复杂性从迭代微小的公式中显现出来
源文件 mandelzoom.cpp 中的Mandelbrot
函数迭代该公式,直到复值 z 超出原点半径为 2 的圆,或者 n (迭代次数)达到最大限制。 n 的结果值决定了屏幕上给定像素的颜色。
看一下函数Palette
,看看迭代计数是如何转换成红色、绿色和蓝色值的。
在内存中生成图像
函数GenerateZoomFrames
产生一系列 PNG 输出文件。每个 PNG 文件都包含一个以不同放大率渲染的 Mandelbrot Set 图像。帧图像的分辨率为 1280 像素宽 720 像素高,这是标准的 HD 720p 视频尺寸。
将图像保存到 PNG 文件
对于您自己的视频生成器应用程序,类VideoFrame
可能会有所帮助。它表示视频的单个帧,并知道如何将该帧保存为 PNG 文件。函数GenerateZoomFrames
使用VideoFrame
生成分形缩放电影的每一帧。
您的应用程序必须为每一帧的每一个像素调用成员函数VideoFrame::SetPixel
。您传入一个定义像素的红色、绿色和蓝色分量的PixelColor
结构。这些值都是 0 范围内的整数…255.
PixelColor
还包含范围为 0 的 alpha 值…255 表示像素的透明度。对于视频应用程序,您应该始终将此设置为 255,这意味着像素完全不透明。为了通用性,我包括了 alpha 值,以防您希望生成具有透明区域的 PNG 文件。
使用 ffmpeg 创建电影
我包含了一个 bash 脚本run
,它自动化了从源代码构建 mandelzoom 程序、运行它,以及将生成的 900 个 PNG 文件转换为名为zoom.mp4
的电影文件的整个过程。这最后一步是通过运行 ffmpeg 程序来完成的。下面是run
脚本。它包括一些有用的注释,解释 ffmpeg 的命令行参数。
这就是全部了!您可以使用本文末尾“参考资料”一节中的链接下载整个源代码库mandelzoom
。
另一个例子
我提到过,这种技术可以用于创建你能想象的任何类型的视频,只要你能编写代码来创建每一帧。只是为了好玩,我以我创建的另一个 YouTube 视频样本作为结束。它是基于一个简单的光线追踪我为我的书 光线追踪 的基础创建的。创建这个视频的代码与上面的 Mandelbrot zoomer 工作方式相同:它生成一系列 PNG 文件,然后 ffmpeg 将其转换为 MP4 文件。
参考
- 曼德尔布罗变焦源代码:https://github.com/cosinekitty/mandelzoom
- LodePNG 首页:https://lodev.org/lodepng
- ffmpeg 项目页面:https://www.ffmpeg.org
在深度学习中只用几行代码就能创造出惊人的图像风格效果!
学习使用 CNN 实现神经类型转移
神经风格转移是一种优化技术,其中将 原始图像 和 风格图像 (如著名画家的艺术品或图案)混合在一起,以获得样式图像的设计或图案中的 输出图像 。换句话说,它也可以被称为图像风格转移。
在本文中,我们将应用 卷积神经网络 (CNN)的深度学习方法来创建一个图像效果,其中一个图像的设计或风格可以应用到另一个图像上,以查看创意效果。
主图像、风格图像和输出图像
上面分享的图片是使用 CNN 实现图像的风格转换的图片。
概述—
对于我们的实验,我们将使用下面的’ 原始图像 ‘和’ 风格图像 '分享如下。
原象
风格图像
从上面分享的图片来看,‘原始图片’是我们将应用“ 风格图片 ”的设计得到最终主输出的图片。整个程序的详细代码可以在本文末尾找到。
初始步骤—
在程序代码的初始步骤中,我们将原始图像和样式图像的大小调整为 512X512 。输出大小会是***【512,512,3】***。其中 3 表示图像是 RGB 或彩色图像。
main_image=main_image.resize((512,512))
style_image=style_image.resize((512,512))main_array=np.asarray(main_image,dtype='float32')
main_array=np.expand_dims(main_array,axis=0)
style_array=np.asarray(style_image,dtype='float32')
style_array=np.expand_dims(style_array,axis=0)
下一步是通过使用expand_dims
将图像整形为形状 (1,512,512,3) 的 4D 张量。然后我们创建一个新的变量’ final_image ',这将是我们最终的输出图像。
height=512
width=512
main_image=backend.variable(main_array)
style_image=backend.variable(style_array)
final_image=backend.placeholder((1,height,width,3))input_tensor=backend.concatenate([main_image,style_image,final_image],axis=0)
CNN 架构—
在这种方法中,我们将利用 迁移学习 的概念,应用预先训练好的 VGG16 CNN 模型。
model=VGG16(input_tensor=input_tensor,weights='imagenet', include_top=**False**)
VGG16 架构(来源)
据消息来源强生等人。,为了提取主图像内容层的特征,我们应该选择block1_conv2
,对于样式层,我们需要选择block1_conv2, block2_conv2, block3_conv3, block4_conv3, block5_conv3
。这些层可以准确地从两幅图像中提取特征。
layer_features=layers['block2_conv2']feature_layers = ['block1_conv2', 'block2_conv2',
'block3_conv3', 'block4_conv3',
'block5_conv3']
正如论文中所给出的,所选择的层的组合正确地工作,以获得所需的风格转换。但是,你可以尝试不同的组合,以获得更准确的风格转移。
主要损失—
一旦我们最终确定了 CNN 模型,我们现在可以定义一个主损失函数。这是主图像和我们的输出图像之间的距离。
**def** main_loss(content, combination):
**return** backend.sum(backend.square(content-combination))
风格丧失—
风格损失类似于主损失,因为它是风格图像和我们的输出图像之间的距离。
**def** style_loss(style,combination):
S=gram_matrix(style)
C=gram_matrix(combination)
channels=3
size=height * width
st=backend.sum(backend.square(S - C)) / (4\. * (channels ** 2) * (size ** 2))
**return** st
最终损失—
最后,我们将定义另一个损失,称为最终损失,这将调整最终图像。
**def** final_loss(x):
a=backend.square(x[:,:height-1,:width-1,:]-x[:,1:,:width-1,:])
b = backend.square(x[:, :height-1, :width-1, :] - x[:, :height-1, 1:, :])
**return** backend.sum(backend.pow(a + b, 1.25))
优化—
一旦我们定义了这三种损失,我们可以将风格转换表述为一个优化问题,其中我们的目标是最小化上面定义的所有三种损失,这统称为全局损失。
**def** eval_loss_and_grads(x):
x = x.reshape((1, height, width, 3))
outs = f_outputs([x])
loss_value = outs[0]
grad_values = outs[1].flatten().astype('float64')
**return** loss_value, grad_values
评估员—
在这之后,我们定义了一个类Evaluator()
,在这个类中,我们共同组合了上面定义的所有函数,并在主迭代中使用它进行样式转换。
**class** **Evaluator**(object):
**def** __init__(self):
self.loss_value=**None**
self.grads_values=**None**
**def** loss(self, x):
**assert** self.loss_value **is** **None**
loss_value, grad_values = eval_loss_and_grads(x)
self.loss_value = loss_value
self.grad_values = grad_values
**return** self.loss_value **def** grads(self, x):
**assert** self.loss_value **is** **not** **None**
grad_values = np.copy(self.grad_values)
self.loss_value = **None**
self.grad_values = **None**
**return** grad_values
结果—
在这种情况下,我们将使用有限内存 BFGS,这是一种优化算法来执行 10 次迭代的风格转移。
evaluator=Evaluator()
iterations = 10
**for** i **in** range(iterations):
print('Start of iteration -', i)
ta = time.time()
x, min_val, info = fmin_l_bfgs_b(evaluator.loss, x.flatten(),
fprime=evaluator.grads, maxfun=20)
print(min_val)
tb = time.time()
print('Iteration **%d** done in **%d** seconds' % (i, tb - ta))
对可视化结果用*L-BFGS算法 我们得到如下图像。*
最终图像
从上图中,我们可以看到’ 样式图像 ‘的样式已经成功的被施加到’ 原始图像 '上。因此,我们成功地实现了使用 CNN 的图像风格转换。
我分享了我的 github 库的链接,在那里你可以找到完整的代码供你参考。
这是一个由代码组成的库,用于执行图像风格转换,以动画的形式显示真实的图像…
github.com](https://github.com/mk-gurucharan/Image-Style-Transfer)
其他例子—
这里有更多的图像风格转换的例子,已经用这个程序实现了。
图像风格转移的示例
结论—
从这篇文章中,我们已经能够利用深度学习,特别是 CNN,来创建惊人的风格转移效果。尝试调整超参数,优化器和其他 CNN 架构,以获得新的和不同的结果。到那时,快乐的机器学习!*
使用 PyTorch 和 Streamlit 创建影像分类 Web 应用程序
LinkedIn 销售导航员在 Unsplash 上的照片
你刚刚开发了一个很酷的 ML 模型。
你以此为荣。您希望通过 web 演示向您的朋友展示它,以便他们可以与您的模型进行交互并提供反馈。
然而,你并不熟悉常见的框架,如 Django 和 Flask 。
你开始问自己:有没有一种方法可以用最少的框架构建一个快速的 web 演示?
古玩目录
概观
在这篇文章中,我将通过一个简单的例子来展示如何使用 Streamlit 来构建一个简单的 web 应用程序。
Streamlit 是一个开源的 Python 库,可以轻松构建用于机器学习和数据科学的定制 web 应用[1]。点击查看它的图库来看看其他人创建的一些应用程序。
我在这里选择图像分类作为一个例子,因为计算机视觉(CV)是目前人工智能中最受欢迎的领域之一,由深度学习算法驱动。它还有广泛的应用,比如对医学图像进行分类,帮助医生进行疾病诊断[2]。在这里了解更多关于深度学习模型的图像分类。
出于演示的目的,我将使用 PyTorch 的预训练 ResNet 模型,对于相同的任务,您可以随时使用其他库(TensorFlow、Keras 等)。),其他架构,甚至定制自己的模型。
要查看我的完整 Python 代码,请查看我的 Github 页面。
现在事不宜迟,让我们开始吧!
安装 Streamlit
第一步是安装 Streamlit 库,您可以使用 pip 命令来完成。我建议您使用 Python 虚拟环境来分别保存每个项目的依赖关系。
$ pip install streamlit
成功安装后,您可以使用一个简单的“Hello World”应用程序进行快速检查:
$ streamlit hello
用户界面
对于我们的应用程序,一个关键要素是使用户能够为模型上传图像以进行预测,这可以通过’ file_uploader '函数来完成:
import streamlit as st
file_up = st.file_uploader("Upload an image", type="jpg")
请确保指定适当的文件类型,以便它能与分类模型一起正常工作。
然后我们可以显示这个图像:
from PIL import Image
image = Image.open(file_up)
st.image(image, caption='Uploaded Image.', use_column_width=True)
除此之外,我们还将使用“set_title”为应用程序创建一个标题,并使用“write”显示预测结果。
分类模型
要使用 PyTorch 的预训练模型,请确保安装了“Torch”和“torchvision”库。现在我们可以创建一个 ResNet 模型:
from torchvision import models, transforms
import torch
resnet = models.resnet101(pretrained=True)
简单来说,残差网络(ResNet)是一种改进的卷积神经元网络(CNN),在知名的 ImageNet 数据库中训练,在图像分类、物体检测等 CV 任务中取得了的优异性能。这个特殊的模型“resnet101”意味着它有 101 层(深!).点击阅读更多关于 ResNet 及其变种的信息。
在我们创建这个模型之后,我们需要通过调整大小、标准化等来转换输入图像。这里我们利用了“火炬视觉”中的“变换”模块:
transform = transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize(
mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225]
)])
注意,图像根据其平均值和标准偏差进行归一化。详见文档。
现在,我们能够加载图像、预处理图像并进行预测:
img = Image.open(image_path)
batch_t = torch.unsqueeze(transform(img), 0)resnet.eval()
out = resnet(batch_t)
接下来,我们可以返回按最高概率排序的前 5 个预测。确保 ImageNet 中 1000 个类别的名称可用,以便我们可以通过索引输出预测:
prob = torch.nn.functional.softmax(out, dim=1)[0] * 100
_, indices = torch.sort(out, descending=True)
return [(classes[idx], prob[idx].item()) for idx in indices[0][:5]]
结果
现在,我们可以通过在命令提示符/终端中键入“streamlit run ”来运行应用程序。让我们尝试两个例子,看看结果是什么样的。
第一个例子:
太好了!金毛位居榜首,置信度很高(~97)。
让我们试试另一个例子:
青蛇高居榜首!再次,它的置信度得分相当高。
这里需要注意的一点是,由于该模型是在 ImageNet 上训练的,因此对于 1000 个类别之外的图像,它的性能可能没有那么好。
后续步骤
创建 web 应用程序后,下一步自然是部署和托管它。例如,我通过 Heroku 部署了一个虹膜分类应用程序,你可以通过这个 Github 页面查看。
此外,如果你对其他神经网络模型感兴趣(VGG,Densenet 等。),你可以尝试上传不同的图像,然后比较它们的性能。
摘要
让我们快速回顾一下。
我们通过 Streamlit 构建了一个简单的 web 应用程序,在这个应用程序中,用户可以上传图像来查看模型的顶级预测以及置信度得分。我们还介绍了如何通过 PyTorch 构建预训练 ResNet 模型。
我希望你喜欢这篇博文,并请分享你的任何想法:)
看看我的另一篇关于使用逻辑回归对 Yelp 评论进行情感分类的文章:
情感分析:特征提取、N-gram、过采样/欠采样、TF-IDF 等等…
towardsdatascience.com](/sentiment-classification-with-logistic-regression-analyzing-yelp-reviews-3981678c3b44)
参考
【1】https://docs.streamlit.io/en/stable/
【2】https://www.hindawi.com/journals/cin/2018/2061516/
使用 Matplotlib 创建信息图
君提供的信息图
2019 年澳大利亚城市的温度模式
从我之前关于 [matplotlib](/plt-xxx-or-ax-xxx-that-is-the-question-in-matplotlib-8580acf42f44)
绘制的层次结构和实例化 [axes](/the-many-ways-to-call-axes-in-matplotlib-2667a7b06e06)
的多种方式的帖子中,我们可以看到这些特性赋予了matplotlib
创造高度复杂和可定制可视化的巨大潜力。为了证明这一点,也为了提高我自己对matplotlib
的理解,本周我开始用matplotlib
制作一个信息图。
一个信息图通常将视觉图像、数据图表和最少的文本结合在一起。它旨在说明一个主题的易于理解的概述。由于这种性质,与常规静态数据图相比,其布局和内容更加复杂多样,常规静态数据图通常在一种类型的图中显示一种类型的数据(如条形图、散点图、折线图和盒图或 及其变体 )。此外,信息图可以是一个独立的图,而常规的静态数据图主要作为补充材料,应该在一定的背景下阅读。
你可能已经从标题图中看到了完整的信息图,它显示了 2019 年澳大利亚八个主要城市的每日最高温度和降水量的年度模式(),我真的希望你在阅读这一段之前能了解它的主题。这让我对继续前进充满信心。我的信息图的灵感来自《南华早报》的这张信息图。
我个人非常喜欢将大量数据可视化为网格状结构。当颜色和形状设置得当时(高温时为砖红色,低温时为北极冰蓝色,我的例子是),它开始传达错综复杂背后的图案(如纬度降低时北极冰蓝色减少),同时也传递了一种艺术感(如一串红色条的外观看起来像燃烧的木头)。
好了,事不宜迟,现在让我们深入代码,向您展示我是如何使用matplotlib
创建这个信息图的。像往常一样,你可以从 my Github 访问所有需要的数据和 jupyter 笔记本。
定义目标并收集数据
尽管这不在本文的讨论范围之内,我还是列出了这一部分来强调这是制作有效信息图的基础部分。只有你知道要讲什么故事,你才有收集数据和思考设计、布局、图表和美学的方向。至于我们的例子,天气数据是从澳大利亚气象局网站下载的。我们只需要日最高气温、城市名称和日期值(即max _ tmp _ day*、* 城市 、 日期 如图 1 )。
图 1 |数据处理
布局
正如我在之前的帖子中所说,fig.add_axes([left, bottom, width, height])
是手动将axes
放置在fig
上的好方法。然而,当我们有许多axes
( 我们总共有 18 个 *axes*
)并且需要对齐(我们的眼睛非常挑剔,即使轻微的错位也会使事情失去平衡)时,精确计算fig
上每个axes
的坐标是繁琐的。我于是采用了普通布局和任意布局axes
的fig
的混合。使用fig.add_gridspec()
和fig.add_axes()
。这里,fig.add_gridspec()
是一个函数,它使我们能够指定将放置axes
的网格的几何形状。例如,想象一个 2 行 2 列的网格在一个fig
上,通常如果我们使用fig.subplots(nrows=2, ncols=2)
,这将产生 4 个axes
均匀分布在 2×2 的网格上。如果在 2 乘 2 的网格上,我们只需要 3 个axes
,第一个axes
占据整个第一行,而剩余的 2 个axes
平均占据第二行,会怎么样?这里有了fig.add_gridspec()
的力量,它使我们能够根据需要创建axes
跨越的行和列。我们可以实现上述布局如下:
fig = plt.figure()# Use GridSpec for customising layout
gs = fig.add_gridspec(nrows=2, ncols=2)# Add an empty axes that occupied the whole first row
ax1 = fig.add_subplot(gs[0, 0:2])# Add two empty axes that occupied the remaining grid
ax2 = fig.add_subplot(gs[1, 0])
ax3 = fig.add_subplot(gs[1, 1])
正如你所看到的,一旦一个网格空间对象(即 *gs*
)被创建,我们可以利用它的网格几何,就像从一个 2D numpy.ndarray
中访问值一样,来相应地放置axes
。例如,fig.add_subplot(gs[0, 0:2])
表示添加一个axes
占据 2×2 网格中的整个第一行。
信息图表布局的代码
回到信息图,如上面的代码所示,除了ax2
( 色条的轴)外,其他的axes
都是由fig.add_gridspec(nrows=10, ncols=10)
添加的。具体来说,在一个 10 行 10 列的网格上(图 2),ax1
,也就是标题、文本和注释的axes
,占据了前 2 行 8 列。从ax3
到ax10
的每一个axes
都是绘制温度条的axes
,占据 1 行 8 列。最后,从ax11
到ax18
的每一个axes
,也就是雨量数据的axes
,只占 1 行 2 列。
图 2 |信息图布局
如你所见,当同时需要多个axes
的灵活性和一致性时,fig.add_gridspec()
是一个强大的功能。
内容和配色方案
布局确认后,我们可以添加数据图。这里以温度条为例(图 3)。
图 3 |条形图示例
考虑到信息和美观,每个条形代表这八个主要城市的日最高温度和年平均温度(24.43 摄氏度)之间的差值。这样,观众可以清楚地识别出高于平均气温的日子(条向上)和低于平均气温的日子(条向下)。否则,由于温度值是正的,所有的条形图将在零度以上朝向相同的方向,这使得条形图很无聊。此外,与常规的条形图不同,我删除了所有的网格、x 轴和 y 轴,只留下了必要的部分。
另一个附加功能是带有弯曲箭头的文本注释,分别指出最高和最低温度的日期。从美学的角度来看,这给整个信息图增加了灵活性。这是由ax.annotate()
交付的。关于ax.annotate()
的官方文档已经给出了非常详细的例子,所以本帖不再重复该功能的介绍。
由于这八个城市的温度柱状图的样式需要保持一致,我们只需要为一个柱状图生成代码,并通过for loop
添加其他柱状图(见下面的代码)。
条形图的代码
虽然配色方案是一个非常主观的决定,但我可以在这里分享我遵循的原则:创造对比、分组元素、编码数量。在这张信息图中,我使用了深色背景来突出温度柱状图和降雨圈。黑色的背景也表达了一种阴郁的气氛,以反映极端天气的紧急情况。此外,条形图和雨量圈分别使用一致的颜色,有助于将信息组织在一起。最后,不同温度值的色谱应用(从北极冰蓝色到砖红色)突出了图案。
标题、文本和注释
信息图可以是一个独立的图的原因是必要的文字有助于加强其主题。这里我们可以使用ax.text()
将任何文本放在fig
上我们想要的任何地方。我发现的唯一缺陷是给matplotlib
添加一个自定义字体家族有点麻烦(一解此处)。另一种方法是在信息图主体完成后通过 Illustrator 添加文本,并导出为svg
文件。
和往常一样,我欢迎反馈、建设性的批评以及听到关于您的数据科学项目的信息。可以通过 Linkedin 和我的网站找到我。
使用 R 创建一个交互式的新冠肺炎报告,免费托管并自动更新
引人入胜的可视化,闪亮的用户界面和 GitHub 操作,创造完美的报告!
本帖是 第一部分 一系列 4 期刊物 。请参考 第 1 部分 了解系列概述, 第 2 部分 了解数据源和次要数据清理, 第 3 部分 了解可视化的创建,构建报告以及将文档部署到 ShinyApps.io 和 【项目回购】
***每篇文章都是独立的,*意思是你真的不需要阅读其他部分来充分利用它。
交互式报告的导航
自 2020 年 3 月以来,所有新闻媒体和政府机构一直在用新冠肺炎的统计数据和图表轰炸民众。这篇由 Tomas Pueyo 撰写的中型文章于 3 月初发表,是首批深度探索 COVID 数据的文章之一,揭示了许多见解,并在短短几天内获得了数千万次浏览。美国约翰·霍普斯金大学也提供了一个非常有用的仪表板以及他们的数据每天更新。他们的数据结合了多个来源,如世卫组织、美国疾病传播中心(CDC)和欧盟 CDC 等。
早期,互联网上充斥着大量来自大学的报告。我意识到我无法制作世界级的仪表板或报告,但至少我想制作自己的仪表板或报告,并学习如何制作。
目录
导语
ggplot,Plotly and Shiny
数据来源
计划
后会有期!
戏弄者
在我们开始之前,我想让你看看最终产品会是什么样子。我们将最终得到一个交互式的基于云的 HTML 报告(有一个闪亮的后端),显示不同的 COVID19 相关图。您可以通过以下链接与最终报告互动→https://lucha6.shinyapps.io/covideda/
我们将制作以下(互动)情节,并将它们烘焙成一个漂亮的互动 RMarkdown 文档,每天更新,无需我们做任何额外的工作。
按国家、洲和全球 COVID 显示死亡人数的树形图
显示一段时间内各大洲累计病例数的折线图
样本 R(闪亮)代码和显示单张地图的输出,其中国家由确诊病例数着色
ggplot
、神秘而闪亮
在我看来是最好的绘图库。这个库基于 Leland Wilkinson 的 Grammar of Graphics(GoG),作为一个 R 包来实现和发布。我推荐阅读原文 [ggplot](https://byrneslab.net/classes/biol607/readings/wickham_layered-grammar.pdf)
2010 年论文由全能的 Hadley Wickham 关于ggplot
的第一次实现和由 Dipanjan (DJ) Sarkar 关于 GoG 背后理论的全面而简明的指南。
Plotly 是一个很棒的跨语言库(最初是用 JavaScript 编写的),允许制作交互式图形。在 R 语言中,也就是我们今天要用的语言,他们有一个叫做ggplotly()
的函数,可以让你把任何ggplot
的情节变成一个没有开销的情节。
闪亮的让 R 用户无需了解一点 JavaScript 或 HTML 就能制作出漂亮的仪表板和交互式报告,所有这些都只需要 R。 RStudio 还为每位用户提供多达 5 个免费仪表盘网站,这是一种无摩擦的方式来构建您的第一个仪表盘、网络应用或交互式 R 笔记本。
数据源
当我在三月份开始这个项目时,我开始使用的数据源来自 Kaggle:由用户 SKR 上传和维护的新型冠状病毒数据集。如数据集描述中所述,这只是 JHU 数据集的镜像,GitHub 中也有数据集。不幸的是,在项目后期,我发现这个数据源中有几个工件。例如,在西班牙,4 月 24 日报告了-10000 例确诊病例,5 月 25 日记录了-2000 例死亡,正如本期 GitHub中讨论的(在 JHU 资料库的 1300 多个未决问题中)。数据中还出现了类似的其他问题,而事实上,存储库维护者并没有站出来对此做出解释,这让我对这些数据的使用产生了怀疑。此外,来自谷歌或我们的数据世界(OWiD)的 COVID 每日案例没有显示这些人工制品。
我决定将我的数据源从 JHU 中切换出来,改用 OWiD。令我非常满意的是,OWiD 数据非常干净,充满了预先计算的特性和统计数据(比如测试统计数据、人口统计数据、每个国家的预期寿命……)。
计划
我认为这个项目对于一篇文章来说太大了,因此我决定写一个 4 部分的系列(包括这个介绍)。接下来的三篇文章如下:
- *我们将首先涵盖数据清理,这是一个必要的步骤,使我们的每个后续情节。**我们主要关注每日和累计的死亡和确诊病例数。*这并不令人兴奋或有足够的洞察力来写一篇关于它的中型文章,因此我为那些对 RPubs 感兴趣的人发布了这个步骤(在这里阅读)。你也可以在另一个 RPubs 笔记本中探索我清理和争论 JHU 数据的努力。出于学习的目的,我在第二个笔记本上的努力要有用得多。数据清理是极其重要的一步,但由于它并不花哨,所以经常被忽视。尽管如此,所有的数据科学家都应该熟悉它。
- 接下来,我们将使用
ggplot2,
plotly
和leaflet
制作每个图,并学习如何制作和部署一个闪亮的 RMarkdown 文档。我们还将看到如何将plotly
图存储为常规文件,以加速我们闪亮文档的加载。 - 最后,我们将编写自动化工具(bash 脚本和 Github 动作),这样我们的报告就可以每天更新,而不需要我们做任何额外的工作。
回头见!
在 Power BI 中创建 N 元排序
数据科学/电力 BI 可视化
关于构建 Python 可视化的快速入门指南,只需点击几下鼠标和少量代码。
在之前的一篇 文章 中,我写了一篇关于使用 nltk 进行自然语言处理来创建和可视化 n-gram 排序的快速入门指南。然而,我需要一种方法来与那些机器上没有安装 Python 或 Jupyter Notebook 的人分享我的发现。我需要使用我们组织的 BI 报告工具:Power BI。
进入 Python 可视化。
Python 可视化允许您创建通过运行 Python 代码生成的可视化。在本帖中,我们将使用这种视觉效果来展示我们的 n-gram 排序结果所需的步骤。
首先,让我们得到我们的数据。你可以在这里下载样本数据集。然后,我们可以将数据加载到 Power BI Desktop 中,如下所示:
选择文本/CSV 并点击“连接”。
在 Windows 资源管理器文件夹中选择文件,然后单击打开:
点击“加载”。
接下来,在“可视化”面板上找到 Py 图标。
然后,在出现启用脚本视觉效果的提示时,单击“启用”。
您将看到一个占位符出现在主区域,一个 Python 脚本编辑器面板出现在仪表盘的底部。
选择“字段”面板上的“文本”栏。
您将看到一个预定义的脚本,它是我们将要编写的脚本的序言。
在 Python 脚本编辑器面板中,将光标放在第 6 行的末尾,然后按两次 enter 键。
然后,复制并粘贴以下代码:
import re
import unicodedata
import nltk
from nltk.corpus import stopwordsADDITIONAL_STOPWORDS = ['covfefe']import matplotlib.pyplot as pltdef basic_clean(text):
wnl = nltk.stem.WordNetLemmatizer()
stopwords = nltk.corpus.stopwords.words('english') + ADDITIONAL_STOPWORDS
text = (unicodedata.normalize('NFKD', text)
.encode('ascii', 'ignore')
.decode('utf-8', 'ignore')
.lower())
words = re.sub(r'[^\w\s]', '', text).split()
return [wnl.lemmatize(word) for word in words if word not in stopwords]words = basic_clean(''.join(str(dataset['text'].tolist())))bigrams_series = (pandas.Series(nltk.ngrams(words, 2)).value_counts())[:12]bigrams_series.sort_values().plot.barh(color='blue', width=.9, figsize=(12, 8))plt.show()
简而言之,上面转换的代码从dataset
数据帧的'text'
列中提取 n-grams,并使用 matplotlib 创建一个水平条形图。plt.show()
的结果就是 Power BI 在 Python 可视界面上显示的内容。
关于这段代码的更多信息,请访问我的以前的教程。
使用 nltk 为自然语言处理创建和可视化 n 元语法排序的快速入门指南。
towardsdatascience.com](/from-dataframe-to-n-grams-e34e29df3460)
粘贴完代码后,单击 Python 脚本编辑器面板右上角的“播放”图标。
几分钟后,您应该能够看到如下所示的水平条形图:
就是这样!
只需简单地点击几下鼠标,在 Python 脚本的帮助下,我们就能够可视化 n 元语法排序的结果。
我希望你喜欢今天关于 Power BI 最强特性之一的帖子。Power BI 已经有了一些有用和漂亮的内置视觉效果,但有时,你只需要多一点灵活性。运行 Python 代码对此有所帮助。我希望这个温和的介绍将鼓励你探索更多,扩大你的剧目。
在下一篇文章中,我将分享一个使用 spaCy 从熊猫数据帧中提取命名实体的快速入门指南 。
敬请期待!