Jupyter 笔记本最佳实践
更有效地使用 Jupyter 笔记本的简明建议。
警告:本文中的建议指的是 Jupyter 的原始笔记本。虽然许多建议可以适用于 JupyterLab,但流行的笔记本扩展不能。
目录
1.构建您的笔记本
- 给你的笔记本一个标题 (H1 标题)和一个有意义的序言来描述它的目的和内容。
- 在 Markdown 单元格中使用标题和文档来构建您的笔记本并解释您的工作流程步骤。记住:你这样做不仅是为了你的同事或你的继任者,也是为了你未来的自己。
- toc2 扩展可以在侧边栏(可选的浮动窗口)和 markdown 单元格中自动创建标题编号和目录。突出显示表示您在文档中的当前位置,这将有助于您在长笔记本中保持方向。
- 可折叠标题 扩展允许您隐藏整个代码段,从而让您专注于当前的工作流程阶段。
- 这个默认模板扩展导致笔记本不是空的,而是具有默认结构和公共导入。还有,它会反复要求你把名字从
Untitled.ipynb
改成有意义的。 - Jupyter snippets 扩展允许您方便地插入经常需要的代码块,例如您的典型导入语句。
Using a Jupyter notebook template (which sets up default imports and structure) and the Table of Contents (toc2) extension, which automatically numbers headings. The Collapsible Headings extension enables hiding of section contents by clicking the grey triangles next to the headings.
2.将代码重构和外包到模块中
- 在你已经在单元格中编写了简单的代码以快速前进之后,养成这样的习惯:将稳定的代码转化为 T2 函数,并将它们转移到一个专门的模块中。这使得你的笔记本更具可读性,并且在生产你的工作流程时非常有帮助。这个:
df = pd.read_csv(filename)
df.drop( ...
df.query( ...
df.groupby( ...
变成了这样:
def load_and_preprocess_data(filename):
"""DOCSTRING"""
# do stuff
# ...
return df
最后是这个:
import dataprep
df = dataprep.load_and_preprocess_data(filename)
- 如果编辑一个模块文件,Jupyter 的自动重新加载扩展重新加载导入的模块:
%load_ext autoreload
%autoreload
- 使用 ipytest 在笔记本内部进行测试。
- 使用合适的 IDE ,例如 PyCharm 。了解其高效调试、重构和测试的特性。
- 坚持好编码的标准 —思考 干净代码原则和 PEP8 。使用有意义的变量名和函数名,合理地注释,模块化你的代码,不要懒得重构。
3.对生产力黑客保持好奇
- 学习 Jupyter 键盘快捷键 。将清单打印出来,挂在你屏幕旁边的墙上。
- 了解 Jupyter 扩展: Codefolding , Hide input all , Variable Inspector , Split Cells Notebook, zenmode 和more more。
- Jupyter Widgets (滑块、按钮、下拉菜单……)允许你构建交互式 GUI。
- tqdm 库提供了一个方便的进度条。
4.拥抱再现性
- 版本控制:学习使用 git——有很多很棒的教程。
- 根据您的项目和目的,使用移除笔记本输出的 git 预提交钩子可能是合理的。这将使提交和差异更具可读性,但可能会丢弃输出(绘图等)。)你其实是想储存。
- 在专用(conda)环境中运行您的笔记本电脑。将
requirements.txt
文件存储在您的笔记本和模块旁边的 git 存储库中。这将有助于您重现工作流程,并有助于过渡到生产环境。
5.进一步阅读
结论
良好的软件工程实践、构建和记录您的工作流程以及根据您的个人喜好定制 Jupyter 将提高您的笔记本电脑生产力和可持续性。
我很高兴在评论中听到你自己的建议和反馈。
Jupyter 笔记本——忘记 CSV,用 Python 从 DB 获取数据
从数据库加载训练数据的简单方法
Source: Pixabay
如果你阅读关于机器学习的书籍、文章或博客,它很可能会使用 CSV 文件中的训练数据。CSV 没什么不好,但是大家想想是不是真的实用。直接从数据库中读取数据不是更好吗?通常你不能直接将业务数据输入到 ML 训练中,它需要预处理——改变分类数据,计算新的数据特征,等等。在获取原始业务数据时,使用 SQL 可以非常容易地完成数据准备/转换步骤。直接从数据库中读取数据的另一个优点是,当数据发生变化时,更容易自动化 ML 模型重训练过程。
在这篇文章中,我描述了如何从 Jupyter 笔记本 Python 代码调用 Oracle DB。
第一步
安装 cx_Oracle Python 模块:
python -m pip 安装 cx_Oracle
该模块有助于从 Python 连接到 Oracle DB。
第二步
cx_Oracle 支持从 Python 代码执行 SQL 调用。但是为了能够从 Python 脚本调用远程数据库,我们需要在运行 Python 的机器上安装和配置 Oracle Instant Client 。
如果你用的是 Ubuntu,安装外星人:
sudo apt-get 更新
sudo apt-get 安装外星人
下载 Oracle 即时客户端的 RPM 文件并使用 alien 安装:
alien-I Oracle-instant client 18.3-basiclite-18 . 3 . 0 . 0 . 0–1 . x86 _ 64 . rpm
alien-I Oracle-instant client 18.3-sqlplus-18 . 3 . 0 . 0 . 0–1 . x86 _ 64 . rpm
alien-I Oracle-instant client 18.3-0 . 0 . 0 . 0–1 . x86 _ 64 . rpm
添加环境变量:
导出 ORACLE _ HOME =/usr/lib/ORACLE/18.3/client 64
导出路径=
P
A
T
H
:
PATH:
PATH:ORACLE_HOME/bin
在这里阅读更多。
第三步
安装神奇的 SQL Python 模块:
pip 安装 jupyter-sql
pip 安装 ipython-sql
安装和配置完成。
对于今天的样本,我使用的是皮马印第安人糖尿病数据库。CSV 数据可以从这里下载。我将 CSV 数据上传到数据库表中,并将通过 SQL 直接在 Jupyter notebook 中获取它。
首先,建立到数据库的连接,然后执行 SQL 查询。查询结果集存储在一个名为 result 的变量中。您看到%%sql 了吗——这个神奇的 sql:
Connecting to Oracle DB and fetching data through SQL query
建立连接时必须指定用户名和密码。为了避免共享密码,请确保从外部源读取密码值(可以是本例中的简单 JSON 文件,也可以是来自 keyring 的更高级的编码令牌)。
这种方法的美妙之处在于,通过 SQL 查询获取的数据是数据框中现成可用的。机器学习工程师可以像通过 CSV 加载数据一样处理数据:
在 GitHub 上可以找到 Jupyter 笔记本的样本。样本凭证 JSON 文件。
Visual Studio 代码中的 Jupyter 笔记本
如何使用 Microsoft Visual Studio 代码作为您的数据科学工具
从事 Python 工作的人,他们喜欢在 Jupyter Notebook 上做研究和实验。我是 Visual Studio Code (VS Code)和 Sublime 之类的桌面 IDE 的粉丝。Visual Studio 代码是用任何语言编程的世界级工具。不仅仅是程序,它还支持很多 DevOps 工具,比如 Ansible、Kubernetes、Yaml 等等。
全球大多数数据科学家使用 Jupyter Notebook 作为机器学习开发、研究和实验的编辑器。Jupyter Notebook 支持 Python,Java,R,Julia,Matlab,Octave,Scheme,Processing,Scala 等等。它是一个编辑器,准确地说是一个为 python 和其他编程语言设计的基于网络的编辑器。以前 Jupyter notebook 被称为 iPython。它是开源的,全球每个人都在使用它。
微软通过安装官方 Python 扩展,正式宣布 Visual Studio 代码原生支持 Jupyter Notebook。
如何在 Visual Studio 代码中使用 Jupyter 笔记本
下载并安装最新版本的 Visual Studio Code IDE【https://code.visualstudio.com/download
在 Visual Studio 中安装 Python 和 IntelliCode 扩展并重启。转到分机部分(左侧菜单)并搜索分机。
注意——以防安装了 Visual Studio 代码编辑器 Python 扩展。您可以通过点击 update 来更新您的旧 Python 扩展。
如何在 Visual Studio 代码中使用 Jupyter 笔记本
**在 VS 代码中创建新笔记本:**快捷键 CTRL + SHIFT + P (Windows)或 Command + SHIFT + P (macOS),运行“Python:创建空白新 Jupyter 笔记本”命令。
**在 VS 代码中打开已有的笔记本:**重启 VS 代码 IDE 后,打开 Jypyter 笔记本文件(。ipynb 文件)。
单击每个单元格左侧的播放按钮,执行单元格中的代码。
当创建或打开 Jupyter 笔记本文件时,默认情况下,VS Code 会自动在本地为您创建一个 Jupyter 服务器。
如果你想使用一个远程 Jupyter 服务器——很简单,通过 VS 代码命令面板使用“指定 Jupyter 服务器 URI”命令,并输入服务器 URI。快捷键 CTRL + SHIFT + P (Windows)或 Command + SHIFT + P (macOS)。
你在 Jupyter Notebook 中使用 python 包的方式,你可以使用你所有的 Python 包,你会得到就地结果(cell result)。例如,我使用了 matplotlib,并像 Jupyter 一样就地获得了图形输出。
**在 Visual Studio 代码中调试 Jupyter 笔记本代码:**目前,要调试 Jupyter 笔记本,您需要首先将其导出为 Python 文件。一旦导出为 Python 文件,Visual Studio 代码调试器就允许您逐句通过代码、设置断点、检查状态和分析问题。使用调试器是查找和纠正笔记本代码中问题的一种有用方式。
- 对于整个笔记本,打开命令调板(⇧⌘P)并运行 Python:在 Python 交互式窗口中调试当前文件命令。
- 对于单个单元格,使用出现在单元格上方的调试单元格装饰。调试器专门从该单元格中的代码开始。默认情况下,调试单元只是进入用户代码。如果你想进入非用户代码,你需要在 Python 扩展设置(⌘,).)中取消选中数据科学:调试我的代码
Visual Studio 代码中最好的特性——超越 Jupyter 笔记本
**智能代码自动完成:**当你编写代码时,智能感知会在你的代码单元中给出智能代码完成建议。您可以通过安装我们的 IntelliCode 扩展来进一步增强您的编辑器体验,以获得基于您当前代码上下文的智能自动完成建议。
Microsoft
**变量浏览器:**使用 VS 代码的另一个好处是,您可以通过点击笔记本工具栏中的“变量”按钮来利用变量浏览器和绘图查看器。变量浏览器将帮助您实时跟踪笔记本变量的当前状态,一目了然。
Microsoft
编码快乐!!!
Jupyter 笔记本提示和技巧
快捷指令
- Shift + Enter 运行单元格(代码或降价)。
- 用于在当前单元格上方插入新单元格的。
- b 在当前单元格下插入一个新单元格。
- m 将当前单元格改为 Markdown
- y 将当前单元格更改为代码。
- D + D(两次)删除选中的单元格。
魔法命令
- 记录单行代码或整个单元的执行时间
# Run the code multiple times and find mean runtime
%timeit CODE_LINE
%%timeit CODE_CELL# Run once and report
%time CODE_LINE
%%time CODE_CELL
- 使用
!
前缀运行一个 bash 命令行 %%bash
将当前代码单元改为 bash 模式运行,基本上就是在其中编写 bash 命令
%%bashecho "hello from $BASH"
%%js
,%% html
,%%latex
,%%python2
,%%python3
,…以指定语言或格式运行和呈现代码单元格。- 当您不想在执行新代码之前担心重新加载模块时,IPython 扩展非常有用。换句话说,当你改变当前笔记本使用的某个模块中的某些东西时,改变将在你运行新的代码单元时发生,而不必担心任何事情。
%load_ext autoreload
%autoreload 2
- jupyter 笔记本中的嵌入式 tensorboard
%load_ext tensorboard%tensorboard --logdir logs/model_training_logs
- 最后,您可以通过运行
%lsmagic
列出所有可用的魔术,这将显示当前定义的线条和单元格魔术。
其他的
- 有时你会有这个内存饥渴的变量,你可以通过设置它为
NONE
然后强制 gc 运行来回收内存
some_var = None
gc.collect()
- 使用
sudo service jupyter restart
来重启 jupyter,因为每隔一段时间 jupyter 就会抛出一个 fit,重启内核不足以让它回到响应状态。 - 在几乎任何函数、变量、…并运行代码单元来访问它的文档。
[tqdm](https://tqdm.github.io/)
在阿拉伯语(塔卡杜姆,تقدّم)中的意思是“进步”,它与 jupyter 笔记本并不相关,但可以用来显示智能进度表。只要用tqdm(iterable)
包住任何一个iterable
from tqdm import tqdmfor i in tqdm(range(10000)):
pass
- 当您想要计算目录中文件的数量时,可以运行以下命令
!ls DIR_NAME | wc -l
经典笔记本扩展
在jupyter _ contrib _ nb extensions中有很多很棒的扩展。不过你应该用 Jupyter lab 代替。
首先你需要改为jupyter_contrib_nbextensions
,然后你可以安装各种有用的扩展。
pip install jupyter_contrib_nbextensions
jupyter contrib nbextension install --user
这些是我喜欢的:
- code _ pretify由 autopep8 支持,非常适合根据 PEP 8 风格指南重新格式化笔记本代码单元格中的代码
pip install autopep8
jupyter nbextension enable code_prettify/autopep8
- 拼写检查器突出显示减价单元格中拼写错误的单词,这让我避免了一些令人尴尬的错别字。
jupyter nbextension enable spellchecker/main
- toggle_all_line_numbers 顾名思义,它增加了一个工具栏按钮来切换是否显示行号
jupyter nbextension enable toggle_all_line_numbers/main
- varInspector 非常适合调试 python 和 R 内核。它在一个浮动窗口中显示所有已定义变量的值
jupyter nbextension enable varInspector/main
主题
- dunovank/jupyter-themes 有一个我遇到的最好的主题。我试过,然后我停止使用它,因为我一直在转换环境,所以对我来说习惯股票主题是最好的。
pip install jupyterthemes# dark
jt -t onedork -fs 95 -altp -tfs 11 -nfs 115 -cellw 88% -T# light
jt -t grade3 -fs 95 -altp -tfs 11 -nfs 115 -cellw 88% -T# Restore default theme
jt -r
Jupyter 实验室扩展
目前我只使用两个扩展
- krassowski/jupyterlab-go-to-definition它允许我使用 Alt + click 通过鼠标跳转到定义,或者使用 Ctrl + Alt + B 键盘。
jupyter labextension install @krassowski/jupyterlab_go_to_definition
- krassowski/jupyterlab-LSP增加代码导航+悬停建议+ linters +自动补全的支持。查看他们的支持的语言服务器的完整列表
pip install --pre jupyter-lsp
jupyter labextension install @krassowski/jupyterlab-lspconda install -c conda-forge python-language-server
最后,您需要重新构建 jupyter 实验室应用程序
jupyter lab build
主题
有很多主题,但是我列表中的第一个定制插件不是主题。这是一个顶栏扩展,可以在亮暗主题之间快速切换
jupyter labextension install jupyterlab-topbar-extension jupyterlab-theme-toggle
以下是我最近使用的一些主题
jupyter labextension install @telamonian/theme-darcula
jupyter labextension install @rahlir/theme-gruvbox
jupyter labextension install @kenshohara/theme-nord-extension
分享一下,联系一下,我的 Twitter DMs 开了!
Jupyter Standalone 可能比 Anaconda 更好
如果您已经在数据科学领域呆了很长时间,那么您可能非常了解 Anaconda navigator 和 Jupyter notebook。当数据科学家需要在虚拟内核上逐个单元地执行时,它们都是很好的工具。但是有没有可能在不掉落 Jupyter 的情况下掉落 Anaconda Navigator?
康达的优势
Anaconda 的根源是环境虚拟化。当然,与独立的 Jupyter 相比,这可以看作是使用 Anaconda 的一个巨大优势。此外,Anaconda 附带了“conda”包管理器,它不像常规的 Python 包索引那样具有扩展性。
由于这些特性,对于一个没有经验的人来说,Anaconda Navigator 的启动学习曲线不像设置 docker 映像和虚拟环境来运行 Jupyter 那样激烈。然而,Conda 的一个显著缺点是缺乏常规包装索引。因此,只有通过一个相当具有挑战性的漏洞,才可能安装尚未发布到 Conda 的传统 Python 包。对于使用大量 API 和各种包的人来说,这当然是个问题。
考虑到这一点,Anaconda 对于数据科学家来说无疑是一个很好的工具,因为像 VSCode、Spark managers 等扩展应用程序都可以很容易地实现到 navigator 中,以便在 conda 终端中工作,所以很容易理解为什么这是 Windows 开发人员的普遍选择。有趣的是,我的很多 Windows 朋友都把他们的康达 REPL 当成终端来使用,所以它的价值对他们来说是显而易见的。
Jupyter 通过 SH 的优势
但是随着 Anaconda 在 Windows 上的易用性,在我们已经有了一个包管理器和一个终端来推送命令的操作系统上将会出现什么情况呢?嗯,对我个人来说,我更喜欢 Jupyter SH,希望我可以证明我自己对这种方法的支持和反对。
尽管我们失去了 Conda 环境,但我们保留了从终端启动时使用的任何虚拟环境,所以如果我
$ - source env/bin/activate
然后运行 Jupyter 笔记本,
$ (env) - jupyter notebook
我将保留我的虚拟 env pip 环境。显而易见,这是在 Jupyter 中管理依赖关系生态系统的好方法。
我喜欢使用 Jupyter 而不是 Anaconda 的另一个原因是文件夹选择,任何时候一个笔记本被深埋在你电脑的文件夹迷宫中,在 Jupyter 中打开它都是非常困难的。Jupyter 的文件界面从任何意义上来说都不是完美无缺的,尽管它确实完成了任务。使用带有 SH 的独立 Jupyter,我可以在我电脑的任何位置打开一个终端,输入“Jupyter Notebook”,就可以直接导航到我想要篡改的文件。
我也是一个 Docker 的忠实用户,在 Docker 上使用 Conda 可能是一件很麻烦的事情……然而,用 Docker 在普通 Jupyter SH 上建立一个完全虚拟的操作系统是非常容易的。
最后的想法
尽管这些观点肯定没有得到普遍认同,但我还是独立使用 Jupyter,因为我喜欢它的多功能性。我喜欢 Anaconda,除了不需要它之外,我并不特别愿意安装它。只要你不通过软件包管理器来安装 Jupyter(它会破坏一切),那么你如何安装 Jupyter 并不重要。)
考虑到这一点,我很好奇有多少人在独立版中使用 Jupyter,而不是在 Anaconda 中使用它,他们对这种体验有什么想法。它们都是非常棒的工具,并且说明了有时候有两种完全不同的方法来做完全相同的事情。
jupyter Superpower——与 Python 的交互式可视化组合
简介
牛郎星 是一个交互式可视化库。它提供了更一致的 API。这是作者对图书馆的描述。
Python 的声明性统计可视化库
它的意思是,它专注于要绘制什么而不是如何绘制,你可以像 ggplot 一样轻松组合不同的组件。在进入本库之前,我想快速介绍两个对数据探索有用的工具。你可以很容易地给像 seaborn 或 **matplotlib 这样的库添加更多的交互性。**在 Github 上查看一些简单的例子,我已经将大部分例子包含在资源库中
Ipywidgets
ipywidgets 允许你用鼠标与 Jupyter Notebook/Lab **交互,**它让 Jupyter Notebook 看起来几乎就像一个小应用程序本身。您可以在笔记本中添加切片器、按钮和复选框。这里有一些使用 ipywidgets 的好项目。
针对香港过度拥挤的医院,我用事故&急诊【A & E】服务等待时间做了一个例子。这里的图显示了医院的平均等待时间,而 ipywidgets 在这里简单地添加了一个下拉菜单,您可以交互地更改图的颜色。
Simple dropdown menu to interact with static plotting library
[## jupyter-widgets/ipyleaflet
Jupyter-fleet . js 桥。在 GitHub 上创建一个帐户,为 jupyter-widgets/ipyleaflet 开发做出贡献。
github.com](https://github.com/jupyter-widgets/ipyleaflet) [## jupyter-widgets/pytreejs
Jupyter - Three.js 桥。在 GitHub 上创建一个帐户,为 jupyter-widgets/pytreejs 的开发做出贡献。
github.com](https://github.com/jupyter-widgets/pythreejs)
qgrid
qgrid 让你在 Jupyter 笔记本/实验室里有一个类似 Excel 的表格,在引擎盖下,它使用 ipywidgets。这是非常有用的,当你试图理解你的数据,而不是输入大量的代码,你可以通过点击排序你的数据,通过点击临时过滤一些数据。简直太棒了!
牛郎星
altair 有一个示例库,演示了您可以制作的各种可视化。
Rich Example Gallery of altair
1.交互式绘图
Upper left: Multiple Selection, Upper right: box style multiple selections, bottom left: single selection, bottom right: mouse hover single selection
牛郎星为交互式绘图提供了很多选择。上面的 gif 给你一种感觉,这有多简单。只需一行代码,您就可以改变图表的行为。交互性对于数据探索是至关重要的,因为您经常想要深入数据的某个子集。交叉过滤等功能在 Excel 或 Tableau 中非常常见。
2.简洁的语法和易于组合的图表
语法有点像ggplot
,创建一个图表对象并在其上添加编码/颜色/比例。
如果你使用过 matplotlib ,你可能会多次尝试查找文档。牛郎星充分利用了像+
&
|
这样的符号,当你想要组合不同的图表时,这些符号非常直观。例如,a|b
表示水平叠加图表a
和图表b
。a+b
在图表 a 上平均叠加图表 b。
叠加两个图表的能力非常强大,它允许我们在同一个图表上绘制两个图表,而不需要实际连接它。
这里有一个例子。我从两个不同的数据集创建了两个图表,它们都连接到一个带有医院名称的选择过滤器。你可以在这里找到我的例子。图表 A 按小时显示历史平均等待时间,而图表 B 按小时显示过去 30 天的平均等待时间。
The bottom left chart is created simply using a+b, both chars are controlled by a filter in the upper left bar chart.
3.出口很容易
很多时候你只是想分享一个图表。你只需要做Chart.save()
,直接和你的同事分享 HTML。事实上,它只是 JSON 和 HTML,这也意味着您可以轻松地将其与您的 web 前端集成。
如果你想要一个拥有大量数据的复杂仪表板, Tableau 或 Dash (Plotly)之类的工具,Bokeh 在这一点上还是比较好的。我还没有找到用牛郎星处理大数据的好办法。我发现当你试图做不超过 4 个图表的交互式绘图时,它是最有用的,在那里你有一些交叉过滤,下拉菜单或高亮显示。
结论
这些是我最近试图包含在我的工作流程中的库。让我知道你的感受,并分享你使用的工具。我觉得 altair 的交互控件是最有趣的部分,但在功能上还是要赶上其他库,支持更多的图表类型。
我会尝试实验 plotly + Dash 看看是否更好。到目前为止,我一直很喜欢牵牛星的 API,但它可能不太适合生产。运行 altair 数据服务器可能是一个解决方案,但我还没有尝试过。
请给我一个大拇指,如果你认为这些工具是有用的,不要忘记给这些项目的创造者一颗星。
参考
https://www.youtube.com/watch?v=aRxahWy-ul8(这是《牛郎星》作者之一 Brian Granger 的精彩演讲。我认为 altair 不仅仅是一个可视化库,你也可以从它的 API 设计中学到很多东西)
JupyterLab——新一代 Python 数据科学集成开发环境
一篇将 Python 数据科学家推向 JupyterLab 的文章。
在使用 Python 进行数据科学项目时,您可能会问自己,哪种 IDE 最能满足您在数据探索、清理、准备、建模、评估和部署方面的需求。您可能还在 Google 上做了一些研究,浏览了标题为“顶级 Python 数据科学 IDE”的各种页面,并开始绝望地意识到,没有一个提到的产品为所有必要的实现步骤结合了无缝的外观和感觉。最终,你回到了你所熟知的,但是独立的工具集。好消息是,有一个非常有前途的项目正等待发布 1.0 版本,以解决我们日常的数据科学需求。我指的是 JupyterLab。
A processed image of Jupiter from Juno’s ninth close flyby provided at [13]. NASA / SWRI / MSSS / GERALD EICHSTÄDT / SEÁN DORAN © CC NC SA
为什么是 JupyterLab?
近年来,Python 笔记本作为一种以交互和布局良好的方式显示代码和结果的工具受到了很多关注。这无疑有助于降低开始编程的门槛,并有助于教育,因为输入及其处理后的输出立即显示在浏览器中,这是许多用户非常熟悉的。尽管 Python 笔记本很受欢迎,但需要做的编码越多,经典的 Python IDE 或文本编辑器就越方便。如果有一种工具能取二者之长,从而将两个世界结合起来,那该多好? JupyterLab 正在通过使用户能够以灵活、集成和可扩展的方式处理文档和活动,如 Jupyter 笔记本、文本编辑器、终端和自定义组件,从而实现这一目标[1]。
Jupyter notebooks 的“Jupyter web 界面的演变”到 JupyterLab 是基于 2015 年进行的用户体验调查,强调了以下三个成功因素[2]:
- 用户喜欢笔记本体验。
- 用户想要组合和混合不同的 Jupyter 构建模块。
- 用户需要轻松协作的能力。
根据我使用 Jupyter 笔记本的经验,这些因素并不奇怪。
优点:
Jupyter 笔记本电脑在可视化功能方面尤为强大。例如,像 Google Facets 这样的工具已经被开发用于 Jupyter 笔记本[3]。
+ 与图形的交互非常方便,例如只需使用%matplotlib notebook
或 ipywidgets [4]。
+ 通过将一个单元格从 code 改为 Markdown,可以为一段代码添加一个漂亮简洁的文档。
Jupyter 笔记本是一个非常好的数据讲述和演示工具,因为它可以显示文档和代码输出。
缺点:
- 缺乏内置的变量检查器是有经验的标准 IDE 用户在 Jupyter 笔记本中首先缺少的东西之一。我想强调的是,有一个非常有用的社区贡献的非官方扩展使用了笔记本的元数据[8]。
- Jupyter 笔记本在开发代码时没有提供方便的文件浏览器视图[5]。因此,读写文件变得很笨拙。
- 为了与操作系统的终端交互或使用作为插件添加的终端视图,用户需要在终端命令前加上一个感叹号!
。
- 打开和浏览文件很麻烦,因为你需要先加载文件,然后选择合适的方式以编程方式显示它。这比在 IDE 中双击打开例如 jpg 文件需要更多的努力。
- 测试和模块化在 Jupyter 笔记本中很难处理。
- 缺少与版本控制系统的无缝集成,尽管 nbdime 之类的插件使笔记本的区分和合并变得更加容易,这是一个有趣的进步[7]。
- 缺乏方便的可视化调试和剖析功能,尽管有像 pixedebugger[10]这样非常有前途的开发。
我想强调的是,这并不是一份详尽的利弊清单。“缺点”一节中列出的陈述表明所提及的功能根本无法实现。它也被列在缺点下面,以防它在 Jupyter 笔记本中不直观。
让我们看看当前可用的 JupyterLab 版本(0.35.6)的详细信息,看看从 Jupyter 笔记本迁移到 JupyterLab 时会涉及哪些内容。
Python 和 Jupyter 笔记本文件共享一个内核
JupyterLab 让您可以开发复杂的 python 代码以及 Jupyter 笔记本,并轻松地将它们连接到同一个内核。我认为这是解决弊端的一个关键特征。
在下面的动画中,您将看到如何在 JupyterLab 中连接多个 Python 文件和笔记本。
Creation of two Python files and one Jupyter notebook in JupyterLab. Consecutively, you see the selection of one common kernel for each of the files. At the end you can observe that all three files have access to the same kernel as they are using the the variables a
and b
interactively.
现在来看看下面的动画,它展示了将数据加载到数据框架、单独开发模型,同时利用 Jupyter 笔记本的强大功能以无缝方式测试和可视化模型的简单性。除了拥有一个通用的变量检查器和文件浏览器之外,所有这些都是可能的。这里可以看到一个简单的手动函数逼近任务。
Exploration of the csv file and loading it into a dataframe in a kernel which is shared among the open files. The dataframe is visible in the variable inspector. First the given x
and y
vectors are plotted in blue. Afterwards, the function approximator plotted in orange is iteratively improved by manually adjusting the function fun in the file model.py. The approximator covers fully the given data input at the end. Therefore, only an orange line is visible anymore.
这有效地分离了提取、建模和可视化,而不必为了共享数据帧而读写文件。这为您的日常工作节省了大量时间,因为它降低了文件加载中的错误风险,并且因为在项目的早期阶段设置 EDA 和试验要快得多。此外,它有助于减少代码行的数量,以防您像我一样向数据管道中添加同样多的asserts
。
如果您在项目的相同上下文中需要一个真正快速的终端,那么您只需打开 launchpad 并创建一个新的终端视图。如果要检查模型或算法所需的资源,这尤其有用,如下图所示。
JupyterLab- Ian Rose (UC Berkeley), Chris Colbert (Project Jupyter) at 14:30 shows how to open a terminal within JupyterLab [9].
用 JupyterLab 打开数据文件也很简单。它以一种很好的方式呈现,例如以 csv 文件的表格形式呈现,并且利用了延迟加载,因此使它很快,并且它支持巨大的文件大小。下一个动画展示了如何从 csv 文件中打开虹膜数据集。
JupyterLab- Ian Rose (UC Berkeley), Chris Colbert (Project Jupyter) at 19:15 shows the IRIS data set in a csv file being opened with a simple click [9].
你也可以通过点击打开图像文件,这在处理计算机视觉任务时非常方便。在下面的动画中,你可以看到 Jupyterlab 如何在一个单独的最后使用的面板中渲染哈勃望远镜的图像。
JupyterLab- Ian Rose (UC Berkeley), Chris Colbert (Project Jupyter) at 17:58, shows an image being rendered in by clicking on it in the built in file explorer [9].
此外,您可以通过 JupyterLab 的 Git 扩展导航和使用 Git,如下所示。
Parul Pandey’s gif showing the navigation in the Git extension provided in [6].
在撰写本文时,JupyterLab 中还没有可视化调试和分析功能。目前计划在未来发布[11]。因此,开发将在 1.0 版本发布后最早开始。尽管有这样的计划,在 Jupyterlab [12]中仍有工作要做,以使 PixieDebugger 适用于笔记本电脑。
结论
JupyterLab 为 Jupyter 笔记本电脑添加了一个完整的 IDE,这无疑是 Jupyter 笔记本电脑的一个强大发展。它可以很好地集成到数据科学家的日常工作中,因此也可以被视为下一代工具。数据提取、转换、建模可视化和测试的分离已经非常容易。
考虑到这一点,我希望看到 1.0 版本很快推出。如果你对 JupyterLab 项目感到兴奋,并想自己尝试一下,只需按照 Parul Pandey 的文章中的说明:
为了给更好的东西让路,所有美好的事情都会结束。
towardsdatascience.com](/jupyter-lab-evolution-of-the-jupyter-notebook-5297cacde6b)
Jupyter 项目,JupyterLab 概述(2018),https://JupyterLab . readthedocs . io/en/stable/getting _ started/Overview . html
[2] N. Tache,JupyterLab:Jupyter web 界面的演变(2017),https://www . oreilly . com/ideas/JupyterLab-The-evolution-of-The-Jupyter-web-interface
[3] J. Wexler,Facets:机器学习训练数据的开源可视化工具(2017),https://ai . Google blog . com/2017/07/Facets-Open-Source-Visualization-Tool . html
[4] 5agado,朱庇特笔记本中的交互可视化(2017),朱庇特笔记本中的交互可视化
[5] I. Rose 和 G. Nestor,Jupyter lab:Jupyter 笔记本的进化(2018),https://www.youtube.com/watch?v=NSiPeoDpwuI&feature = youtu . be&t = 254
[6] P. Pandey,Jupyter Lab:Jupyter 笔记本的进化(2019),https://towardsdatascience . com/Jupyter-Lab-Evolution-of-the-Jupyter-Notebook-5297 cacde 6b
[7] Project Jupyter,Jupyter Notebook Diff and Merge tools(2019),https://github.com/jupyter/nbdime
[8] Jupyter Contrib Team,Variable Inspector (2019),https://Jupyter-Contrib-nb extensions . readthe docs . io/en/latest/nb extensions/varInspector/readme . html
[9] I. Rose 和 C. Colbert,Jupyter 项目的 JupyterLab 下一代用户界面(2018 年),https://www.youtube.com/watch?v=t5q19rz_FNw&feature = youtu . be
[10] D. Taieb,你一直想要的 Jupyter 笔记本的可视化 Python 调试器(2018),https://medium . com/codait/The-Visual-Python-Debugger-for-Jupyter-Notebooks-youve-Always-Wanted-761713 babc 62
[11]Jupyter 项目,JupyterLab (2019),https://github . com/Jupyter/roadmap/blob/master/JupyterLab . MD
[12]Jupyter 项目,JupyterLab (2017 年),https://github.com/jupyterlab/jupyterlab/issues/3049
[13] M. Bartels,美国宇航局发布了来自朱诺任务(2017 年)的令人难以置信的木星新图像宝藏,https://www . Newsweek . com/NASA-Releases-Treasure-Trove-Incredible-New-Images-Jupiter-Its-Juno-Mission-705210
本文旨在通过结合作者的实践经验和深入的文献研究,提供 JupyterLab 可能是 Python 数据科学家的首选 ide 的理由。它不应作为安装指南,也不应作为功能的列表和比较。
复杂 Python 和 Scala Spark 项目的 JupyterLab
JupyterLab 是一项用于原型和自我记录研究的了不起的技术。但是你能把它用于有一个大代码库的项目吗?
外部库的情况
笔记本工作流对全球所有数据科学家来说都是一大进步。能够直接看到每个步骤的结果,而不是一遍又一遍地运行同一个程序,这是一个巨大的生产力提升。此外,自我记录的能力使它很容易与同事分享。
也就是说,你在笔记本上所能实现的是有限的。它最适合交互式计算,但是当每个单元超过 100 行代码时,它就不再是交互式的了。在这一点上,你需要的是一个真正的 IDE,比如 T2 VS 代码,或者 T4 py charm,也许还有一些单元测试。
一个好的库是在你当前项目之外开发的,它应该足够通用,能够在广泛的项目中帮助你和你的同事。把它看作是一项未来会有很多倍回报的投资。
现在,你如何把这个图书馆推回朱庇特?
Python 内核
假设您想要向 Spark 对象添加新的功能,例如 Spark 上的 doSomething()方法和 DataFrame 上的 predict()方法。使用以下代码创建一个模块(Python 中的一个文件,例如 mylib.py ):
mylib_init()使用 setattr()函数来扩展 SparkSession 和 DataFrame 的类定义,并添加新方法。你要做的就是用下面的两行代码创建一个代码块(代码块 4)。首先导入函数“mylib_init()”定义,然后调用它。
小问题是,如果您更改 mylib.py 文件,即使您再次调用 mylib_init(),它也不会更改工作簿中的任何内容。我在这篇文章中发现了关于自动卸载插件的内容。这将允许 Jupyter 每 2 秒检查一次. py 的新版本,您只需要调用 mylib_init()来使用新的模块。
因此,当您使用 pyspark 库在 Jupyter 实例中创建 Spark 驱动程序时,这是一个简单的例子(例如通过使用下面的代码)。
这是最简单的方法,因为它们都在同一台电脑上。当事情变得遥远时,这就有点复杂了(但没那么难),例如当使用 Sparkmagic 时。
Sparkmagic 内核(Python 和 Scala)
Sparkmagic 内核允许你的 Jupyter 实例通过 Livy 与 Spark 实例通信,Livy 是 Spark 的 REST 服务器。Sparkmagic 会将你的代码块作为 web 请求发送到 Livy 服务器。然后,Livy 会把它翻译成 Spark 驱动程序并返回结果。
正如您在下图中看到的,Spark 驱动程序在集群上是远程的,根本不能访问 Jupyter 实例下的文件。
你如何解决这个问题并使用你的图书馆?
如果您使用 Python,您可以将代码存储在底层 HDFS 上并使用 sc。 addPath (sc 是 Sparkmagic 自动创建的 SparkContext)。由于驱动程序和执行程序都可以访问 HDFS,所以它会起作用。
对于 Scala,我们希望能够在类路径中添加一个或多个 JAR 文件。JAR 是 Java 生态系统中的库。遗憾的是,虽然 SparkContext 上有 addJar,但这种方式行不通。随着 Scala 的编译和类型化,你不能只是在一大块代码中添加 JAR,然后立刻使用这个 JAR 中的类型。addJar 将使这对于执行者成为可能,但是对于驱动程序来说,当调用 addJar 时,不再可能添加类定义。
幸运的是,有一种方法可以在 Livy 创建 SparkContext 时通知它将哪个 JAR 添加到类路径中(在发送任何代码进行编译之前)。
注意,如果已经有一个上下文,这个块将重新启动一个上下文,所以它应该是您笔记本的第一个块。
两全其美
正如我们所看到的,无论您的情况如何,都有一种方法可以利用现有的代码库,只在 Jupyter 笔记本中保留高级的有意义的代码。
我强烈感觉到,高性能数据科学团队的关键是始终在提高生产力的工具上投入时间。共享的高级原语库对生产力至关重要。Jupyter 对此很满意,这是个好消息。
原载于 2019 年 10 月 6 日https://dataintoresults.com。
Jupytext 1.0 亮点
Jupytext 是 Jupyter Notebook 和 JupyterLab 的扩展,可以保存各种文本格式的 Jupyter Notebook:Markdown、R Markdown、Python、Julia 和 R scripts 等等!
A Jupyter Notebook represented as a Python script (light or percent format), Markdown, and R Markdown
Jupytext 将允许您:
- 在您最喜欢的代码编辑器中编写或编辑 Jupyter 笔记本
- 在具有清晰差异历史记录的笔记本上启用版本控制
- 在 Jupyter 笔记本上协作,轻松合并稿件
- 重构笔记本并将它们的代码提取到库中
使用 Jupytext 的一种便捷方式是通过配对笔记本。配对笔记本是一个传统的.ipynb
笔记本,它与一个文本表示同步——比如一个 Python 脚本。保存笔记本后,Jupytext 会更新这两个文件。该脚本有一个清晰的差异历史,只关注输入单元格。
用户可以在代码编辑器中编辑或重构脚本:当在 Jupyter 中读取或刷新笔记本时,将从脚本中读取输入单元格。此外,匹配未更改输入单元格的输出单元格从.ipynb
文件重新加载。
Jupytext 于 2018 年 9 月日推出,并受益于社区的大量反馈。我们已经建立了反馈,我们很高兴地宣布 Jupytext 达到了 1.0 版本。
现在让我们回顾一下这个主要版本的主要新特性!
Jupyter 笔记本中的 Jupytext 菜单
Jupytext 获得了一个 Jupyter 笔记本扩展:使用新的 Jupytext 菜单来选择笔记本的配对格式,并在另一个编辑器中编辑文本表示时禁用自动保存功能。
JupyterLab 中的 Jupytext 命令
Jupytext 1.0 还为 JupyterLab 提供了一个扩展:使用新的 Jupytext 命令将您的笔记本与文本文件配对。
一个强大的jupytext
司令部
jupytext
命令可能已经:
- 转换笔记本
--from
和--to
各种笔记本格式、 --update
一个.ipynb
笔记本中的输入单元格,给定一个笔记本的文本表示,- 使用 Git 预提交钩子维护笔记本的最新文本表示。
在 1.0 版本中,jupytext
命令扩展了新的模式:
--sync
同步笔记本的多个表示--set-formats
(以及可选的--sync
),设置或更改笔记本或文本文件的配对--pipe
将笔记本的文本表示输入另一个程序。
也许你想用[black](https://github.com/ambv/black)
、不妥协的 Python 代码格式化程序重新格式化你的 Jupyter 笔记本?就这么简单jupytext --pipe black *.ipynb
!
子文件夹中的配对笔记本
在 Jupytext 的早期版本中,配对的笔记本必须共享同一个目录。在 1.0 版本中,Jupytext 可以将笔记本与不同文件夹中的文本文件配对。
将当前文件夹中的笔记本与带有以下内容的python
子文件夹中的 Python 脚本配对:
jupytext --set-formats ipynb,python//py --sync *.ipynb
(使用--sync
实际创建 Python 文件;如果您想使用percent
格式,请将py
替换为py:percent
。
将文件夹notebooks
中的笔记本与文件夹markdown
中的 markdown 文件和文件夹python
中的 Python 脚本配对,使用
jupytext --set-formats notebooks//ipynb,markdown//md,python//py --sync notebooks/*.ipynb
关于笔记本前缀和后缀的更多信息可在文档中找到。也可以激活所有笔记本的默认配对。
氢格式
Jupytext 已经可以将 Jupyter 笔记本表示为 light 或 percent scripts。Jupytext 1.0 引入了一种新的hydrogen
格式,这将最适合 Hydrogen 编辑器的用户。hydrogen
格式与percent
格式相同,除了 Jupyter magic 命令,这些命令没有注释。
下面是 Python Hydrogen 笔记本的截图,其中包含许多其他语言——看看 Hydroden 如何呈现多种输出类型!
久经考验的程序
我们已经尽了最大努力确保 Jupytext 能够完美运行。我们的用户和测试人员已经做了很好的工作。对于他们发现的每个 bug,我们增加了测试数据库。
但是你可能想对你自己的笔记本电脑系列进行压力测试?给jupytext --test
或jupytext --test-strict
一个尝试。
Vim 的插件
感谢迈克尔·戈尔兹,Jupytext 有了一个用于 Vim 的插件。安装插件并编辑以 Markdown 文档或脚本表示的 Jupyter 笔记本。jupytext.vim
是另一种非常方便的使用 Jupytext 的方法!
在未来,我们希望为更多的编辑器提供 Jupytext 插件,包括 PyCharm 和 Visual Studio 代码。请让我们知道你是否能在这里提供帮助——一个好的插件只需从jupytext --sync
开始!
谢谢你
Jupytext 非常感谢社区的反馈!
对于这个版本,我特别感谢:
-Florian Wetschoreck,Fran ois Wouts和 Amjad Haouriqui,感谢他们在设计 Jupyter 扩展
- Philip Austin 时给予的支持,他们提出了将笔记本与其他工具连接的想法,以及将笔记本与不同文件夹中的脚本配对的想法
- Michael Goerz ,Andre Thrill
你想帮忙吗?你可以在很多方面做出贡献。我们很乐意了解 bug。欢迎想法!文档的改进也很有帮助。明星让我们保持动力。来加入我们的 GitHub 吧!
诺瓦克·德约科维奇到底有多好?
数据分析师-网球运动员对 2019 年澳大利亚网球公开赛决赛中密谋的事件的分析
今年的澳网决赛是 2012 年诺瓦克·德约科维奇和纳达尔之间的决赛的复赛。2012 年的比赛具备了被认为是游戏史上最伟大的比赛之一的所有要素。这场比赛有各种各样的东西,从长时间的艰苦拉力赛,最高的防守打法,来自另一个星球的制胜一击,以及最高级别的精神勇气的展示。这场比赛为网球场上的痛苦提供了一个新的定义,在颁奖仪式上,球员们几乎无法站立。
2012 年的 AO 决赛是一场相当公平的比赛,直到第五盘,纳达尔在第一盘就击败了德约科维奇,并有望获得例行的五盘胜利。德约科维奇是一个不屈不挠的斗士,他继续对纳达尔的发球局施加压力,并以决定性的方式保持自己的发球局,以保持自己在比赛中的相关性。在第五盘的第六局,纳达尔错过了一次常规的反手击球,这被证明是至关重要的,并使诺瓦克回到了比赛中。(下面的视频链接)
剩下的就是历史了,德约科维奇找到了打破纳达尔发球局的方法,赢得了他的第三个澳网冠军。2019 年澳大利亚网球公开赛决赛预计将是两位传奇人物之间的又一场大战,但没有人会记得这场比赛是一场势均力敌的比赛。德约科维奇在三盘比赛中决定性地击败了纳达尔,这场比赛持续了 2 个多小时,赢得了他的第七个澳大利亚网球公开赛冠军。
纳达尔
要了解德约科维奇在比赛中有多好,重要的是要了解纳达尔在过去两周的表现有多好。纳达尔没有丢掉任何一盘,并在通往决赛的道路上击败了一些著名的选手。事实上,纳达尔看起来像是进入决赛前的状态。
发球
在 11 月接受脚踝手术和职业生涯中多次膝盖受伤后,纳达尔决定调整他的发球动作。修改后的发球动作旨在增加击球的冲击力,帮助纳达尔更具侵略性,缩短得分,以保护他的身体。
Rafael Nadal’s Serve Stats
在三个重要的方面(第一发球百分比,第一发球得分和第二发球得分),纳达尔似乎在赢得发球得分方面超越了他的职业生涯最佳数据。这使得纳达尔占据了所有发球比赛的 92.6%,这也是职业生涯的新高。除此之外,第一次发球比去年快了 5 英里。发球的有效性帮助他缩短了比赛时间,并自始至终保持领先。
地滚球和截击球
就在几年前,纳达尔以其令人难以置信的回球技巧、从底线后 10 英尺处回球以及多次重新开始得分的能力而闻名。特别是在过去的 3 年里,纳达尔改变了他的战术,在比赛中融入了进攻型打法。这在 2017 年澳大利亚网球公开赛决赛中得到了充分展示,纳达尔与费德勒展开了激烈的进攻。在最近的脚踝手术后,纳达尔缩短了他的后摆,并开始在击球时变得更平。众所周知,纳达尔有一个惊人的截击(看看这个)并且在他的单打比赛中融入这一点后,在过去的几年里,它变得更加强大。这有助于他在进攻中开始得分,并快速完成得分。
统治地位
纳达尔在 2019 年澳大利亚网球公开赛上直落两盘击败澳大利亚选手詹姆斯·杜克沃斯。比分无疑表明纳达尔由于缺乏比赛而生疏,但他的发球在比赛中被破了两次。从第二轮开始,他的发球局真的开始变得有节奏了,他在决赛中一次也没有丢掉发球局。他在半决赛中令人信服地击败了 Stefano Tsitsipas(罗杰·费德勒的攻击者)。
匹克-德约科维奇
德约科维奇的肘部受伤让他的统治地位受到了影响,这让他在 2017 年和 2018 年的大部分时间里都没有参加大满贯比赛,后来他在 2018 年赢得了温布尔登网球公开赛,打破了他的大满贯冠军头衔。虽然球迷们觉得他从伤病中复苏已经完成,但很少有人希望他能像在 2019 年澳大利亚网球公开赛决赛中那样统治比赛。
调整服务动作
在退出 2017 年下半年的比赛后,德约科维奇团队提出了一个肘部更轻的发球动作。肘部受伤使得德约科维奇的发球不稳定,不可靠,缺乏欺负对手的力量。调整后的发球动作似乎没有改变德约科维奇的命运,他不得不在比赛前接受手术,没有任何痛苦。德约科维奇在 2018 赛季前半段展示的发球动作受到了阿加西发球动作的启发。德约科维奇在美国硬地球场夏天解雇了阿加西和斯捷潘内克,并抨击了他的新发球动作。重新雇用 Marian Vajda 看到他的发球大幅提高,回到了 2016 年的水平。我会让数字自己说话。
费德勒和德约科维奇并不以最强有力的发球而闻名,但却以在正确的时间击中正确的位置而闻名。德约科维奇的发球比以往任何时候都更经常地击中正确的位置。他所有的发球中有 8.3%被证明是 ace 球,他在 ace 球方面从来没有做得更好。下一个要检查的统计数据是第一发球的百分比。
德约科维奇的第一次发球命中率是他能够击败纳达尔的原因,这让他在发球比赛中完全没有表现出来。第一次发球火力全开,对他的所有对手来说都是令人恼火的一致。尽管本赛季开局糟糕,输给了排名前 100 名之外的球员,诺瓦克还是在本赛季的后半段将自己的第一次发球得分率提高到了一个可观的数字。
如果你认为发球的准确度和精确度有所提高,那你就错了。当你看看这些数据时,发球的有效性是不可否认的。我们已经确定,首次发球的次数比以往任何时候都多,而且每次发球都比以往任何时候都有更多的回报。他今年赢得了职业生涯最高的第一发球得分,这包括在多哈锦标赛中的惨淡表现。有一句谚语说“你只像你最薄弱的环节一样强大”,这让我们看到了第二次发球,德约科维奇大大提高了第二次发球,比他的职业生涯平均水平高出近 10 个百分点。在过去,特别是 2011 年,德约科维奇的身体习惯于在他的第二次发球被中和后接管,但这在 2019 年应该是不正确的,因为他变得更老了,因此比以前的自己更弱。不可思议的是,他比以往任何时候都更擅长长基线拉力赛,他的触地击球也比以前更有穿透力。
回归游戏
我可以坐一整天,大声谈论诺瓦克过去的回报有多好,但还能更好吗?
诺瓦克赢得的回球点数当然不像 2011 年那样高,当时他连续得分,差点断送了罗杰和拉法的职业生涯。2011 年,他不得不面对纳达尔和费德勒,他们的状态非常好,因此,回报实际上需要那么好。令人惊讶的是,诺瓦克仍然能够与他在 2011 年创下的纪录相抗衡,并在 2016 年平了自己的纪录,他在本赛季结束时获得了 2 个大满贯。罗杰的接发球率是职业生涯平均 40%,对于一个完全处于巅峰状态的球员来说,这并不算太差,但诺瓦克和罗杰的区别在于赢得的破发点的百分比。在澳网期间,罗杰赢得了 14.7%的破发点,诺瓦克赢得了 39.4%的破发点。下面看看今年的断点统计与他在其他年份打网球的情况如何。
地面“体击”比划
不幸的是,ATP 没有提供足够的数据来评估某人的正手和反手比赛,但在定性的层面上,正手和反手正在全力以赴。在令人失望地输给罗伯托·布蒂斯塔·阿古特之后,诺瓦克打得如此被动,看起来他无法穿透他的任何对手(Marton Fucsovics,Nikoloz Basilashvilli)。他从澳网第一轮开始就很好地掌握了自己的比赛,并且在每一轮比赛后都有很大的进步。在半决赛对阵 Pouille 的比赛中,他犯了 5 次非受迫性失误,而在决赛对阵 Nadal 的比赛中,他犯了 9 次非受迫性失误,这实在是太可笑了。
他的场地位置非常具有攻击性,并多次压平他的反手,以中和纳达尔多圈的斜线正手。看看下面链接中的照片。
显然,马里昂融入的变化将诺瓦克的比赛带到了一个新的水平,没有任何真正的竞争(除非纳达尔和费德勒能够回到 2017 年的状态),他可能会在今年赢得 2 个或 3 个大满贯。
基于树的分类器在处理缺失数据时有多健壮?
这是一个有趣的小型实验,通过使用中位数和众数插补,对照逻辑回归的预测,测试没有缺失值替换的树集合的预测。
Train set with 36% of the values missing on average for every row entry.
首先,这不是一个科学实验来确定一个人应该如何预处理缺失值的数据,或者当适合缺失值的数据时,哪个树集成擅长给出最准确的预测。我的主要动机是研究随着数据集中缺失值数量的增加,不同模型的预测如何变化。该实验的结果可能不表示使用不同数据集来拟合相同模型的结果。然而,我希望它可以提供一些关于预测准确性开始加速恶化的临界点的见解。
数据来源及描述
信用批准数据集是从 UCI 机器学习库下载的。它由 690 个条目组成,具有 9 个分类属性和 6 个连续特征属性。为了保护敏感信息的机密性,这些功能的名称和值已被更改为不可识别的类型。有 37 个行条目缺少一个或多个值,但它只占总数据的不到 1%。批准和拒绝这两个目标类别几乎是平衡的,这使得评估不同的模型变得更加简单。
模型训练和测试
数据集分为 80%用于训练,20%用于测试。在训练集的 552 个条目和测试集中的 138 个条目中,分别只有 29 个和 8 个缺失值。每个模型都适合一个流水线,其中诸如输入缺失值、定标器转换和模型训练等过程被简化。作为这个实验的设置,我决定估算数据集的均值和模式,以在逻辑回归上进行训练,并估算一个空字段和’-999,999,999 '(看起来很傻,但像我说过的,这只是一个有趣的实验)以使数据集在额外的树、随机森林、Adaboost 和梯度增强上进行训练。
Pipeline for Logistic Regression
Pipeline for Tree Based Classifiers
每个模型的结果和缺失数据的数量都记录在 Pandas 数据框架中。
缺少价值生成和阈值
我通过向训练集和测试集随机添加缺失值来引入更多的噪声。我将缺失值的行数设置为函数的阈值。这些阈值大约为 15%、30%、50%、75%和 100%的行。在每个阈值对每个模型进行模型训练和附加结果的过程。
初步结果
总的结果肯定不是我所期望的。即使有 75%的行包含至少一个缺失值(即 9.4%的定型集和测试集不包含任何数据),我的大多数模型的预测得分也只有微不足道的下降。与逻辑相反,任何模型的最佳预测可能不是来自缺失值最少的数据集。如下表所示,在缺失值为 2.6%的数据上构建随机森林比缺失值为 0.6%的初始数据集获得更好的预测。
AUC vs percentage of missing data in training set
重新校准的实验
对初始实验的一个疏忽是,应该定期对数据集中发现的缺失数据进行评估。我修改了缺失数据生成器,以 5%的间隔随机删除数据点,直到一半的数据集(训练和测试)不包含任何数据,同时只保留 25%的行没有任何缺失值。
AUC vs percentage of missing data for recalibrated experiment
决赛成绩
随着缺失值的百分比变高,所有模型的结果最终都会恶化,但这种关系并不像我最初假设的那样接近线性或二次关系。仍然有可能从任何模型,逻辑回归或基于树的分类器中获得很好的预测,建立在具有 20%缺失数据的数据集上。鉴于我没有为基于树的模型估算有意义的值,我对这些模型的结果印象深刻。我的迷你实验的主要收获是,有相对大量的缺失值并不一定会导致糟糕的模型预测。可能还有其他未知因素影响预测的质量。
继续猜测:蒙特卡罗方法的力量
Photo by Martinp1
蒙特卡罗方法是一个非常强大的工具,广泛应用于各种领域。从数学到科学到金融,蒙特卡罗方法可以用来解决各种独特而有趣的问题。
蒙特卡罗方法的思想相当简单。它依靠大量的重复随机抽样来获得数值结果,并取所有这些结果的平均值来找到问题的最终答案。
让我们尝试用蒙特卡罗方法找到积分的数值解。在我们开始之前,应该注意到蒙特卡罗模拟对于单变量函数来说并不是最优的。他们在解决多变量函数时做得最好,但是为了清楚和简单起见,我们现在将坚持一个。
先说函数平均值的定义。平均值可以表示为
其中 a 和 b 是我们的开始和结束积分点, x 是我们正在积分的值。因此,从这里我们可以通过将方程的两边乘以范围 (b-a)来计算积分。
现在积分等于一个函数的平均值乘以我们想要积分的范围。
从这里我们要求 F 的平均值。我们可以这样做:取一个大的随机数样本,找到每个随机数的对应值,将这些值相加,然后用随机数的总数除总和。数学上,这个关系看起来像
值得注意的是,这只在随机数均匀分布的情况下有效。记住这一点,感兴趣的积分的最终方程是
现在剩下要做的就是插入我们想要积分的函数,我们积分的极限,以及在计算积分时我们想要猜多少次。
让我们举一个简单的例子。让我们将函数 sin(x) 从 0 到 pi 进行积分。分析上,这个积分并不太难,计算只是
但是我们的兴趣是看看蒙特卡罗方法能多好地完成这个计算,所以我们要解的方程是
这是你运行自己的蒙特卡洛计算所需的所有代码。
import numpy as np
from scipy import randoma, b = 0, np.pi # limits of integration
N = 100_000 # Number of random points
integral = 0.0 # initialize the value of the integralx_random = random.uniform(a,b,N) # array of random numbersdef func(x):
'''This is the function that we want to integrate'''
return np.sin(x)# Makes a guess at the integral, adds that guess to the other guesses, and prints intermediate answers
for x in range(N):
integral += func(x_random[x])
if (x % 10_000 == 0) & (x != 0):
intermediate_answer = (b-a)/float(x)*integral
print(f'Value after {x} iterations is {intermediate_answer}')
answer = (b-a)/float(N)*integral
print(f'The value of the integral from {a} to {b} is: ', answer)
结果是
我们可以看到,我们的蒙特卡洛计算正在慢慢地向正确答案靠拢!
67%对 45%的 TD 通过率对运行率。随着 NFL 常规赛的结束,这种奇怪的趋势会持续下去吗?
你应该跑还是应该越过球门线?
(这篇文章最初发表于 2019 年 10 月 22 日,涵盖了截至第 6 周的统计数据。本次更新涵盖统计数据,直到第 16 周。)
所以你一直走到了对手的 1。传统观点认为你应该直接运行它。然而,许多主教练认为这太容易预测了,所以他们选择传球。基于数据的决策应该是什么?
我收集了从 2014 年到 2019 年在对手 1 码线开始的所有比赛的日志。像往常一样,我在这里排除了投篮尝试,唯一合理的解释是,在那个特定的时刻,你更加重视眼前的收益——时间不多了,和/或投篮实际上帮助你的球队赢得了很多的概率,比如从 6 到 9 分的领先优势,或者追平或在晚些时候领先。剧透一下,1 号位的投篮命中率是 49/49。所以让我们把注意力集中在传球和抢攻上。当然,我也排除了下跪戏。
总的来说,触地得分率徘徊在 55%左右,有些年份比其他年份好。2019 年实际上是非常好的一年,整体触地得分率超过 60%。(这不是一个小样本的人工制品,或者只是在赛季初还没有解决的问题,因为当只考虑 9 月和 10 月的比赛时,可以得出相同的结论)。几年过去后,你会有稍微好一点的机会,比如 2014 年和 2017 年,类似的几年,2015 年对两者都不好。但到目前为止,我们从未有过像 2019 年这样的一年,即通过与运行的 TD 比率分别为 67%和 45%。大多数教练知道他们应该少传球,因为他们已经选择传球的时间低于 30%,今年是所有教练中最低的。但不是我的绿湾包装工队。在周四晚上的足球比赛中对阵老鹰队,他们在费城 1 号连续四次传球,导致四次失误和失误。
P(TD,4 次运行)=1-(1–0.68)⁴= 0.985
P(TD,4 遍)=1-(1–0.448)⁴= 0.907
相差 8%!
接下来,一个理念是你应该在第一次传球时多传球,让对手措手不及。从历史上看,这是有数据支持的。TD 通过率在第一次下降时高得多,在第四次下降时低得多。但这在 2019 年不再成立。事实上,在第一、第三和第四次下降时冲得更好,在第二次下降时稍微差一点。
另一个支持足球的理由是风险更小。失误率实际上非常相似——所有传球和跑位的拦截率为 1.8%,失球率为 2.1%。奇怪的是,你甚至可以在前面只有 1 码的绿草地的情况下摸索出一个信号。到目前为止,这项荣誉属于我的数据集中唯一的充电器。
Philip Rivers pass complete short middle to Austin Ekeler for no gain (tackle by Kareem Jackson). Austin Ekeler fumbles ball out of bounds at DEN-1 (forced by Kareem Jackson)
我们应该考虑事情变得非常糟糕的极端情况。就像今年底特律的失球,堪萨斯城的达阵得分。
Kerryon Johnson up the middle for no gain (tackle by Xavier Williams). Kerryon Johnson fumbles (forced by Xavier Williams) recovered by Bashaud Breeland at KC-0 and returned for 100 yards touchdown
在我们的数据集中,最糟糕的传球失误是 Blake Bortles 拦截,他在 84 码处回球。
Blake Bortles pass incomplete short left intended for Marcedes Lewis is intercepted by Kemal Ishmael at ATL-0 and returned for 84 yards
这是过去几年中唯一一次比触球收益更高的失误。但当然,100 码的拦截回报是可能发生的,最令人难忘的是匹兹堡钢人队对红雀队的超级碗第四十三届选秀权(库尔特·华纳传球不完整的短中路,打算给安泉·波尔丁,在 0 号坑被詹姆斯·哈里森拦截,并返回 100 码触地得分)。综合来看,冲向或越过球门线的风险似乎不相上下,但冲向现在给团队带来了更大的好处。所以只管跑那该死的足球!
那么这种趋势会在赛季末保持吗?
下图来自 2019 年常规赛第 16 周的更新。
嗯……没那么引人注目,但仍然是一个巨大的差异。在 60%的情况下,冲球仍然能让你触地得分;而现在通过至少让你有 52%的机会获得 50%以上的机会。但是,在必须得分的情况下,6 分在起跑线上, 8%的触地得分率增长仍然有很大的不同。
更有趣的见解来自唐斯的分解。虽然的传球率在第四轮比赛中飙升,但 rushing 仍然更加成功,达阵率高出 10%。如果你真的想传球,第二次触地得分应该是在你传球的时候,因为传球和冲刺给你的触地得分率是 58%。
你可以在我的 Github 上找到我的代码,并在 LinkedIn 上与我联系。数据来自 Profootballreference.com。它在 2019 年 NFL 赛季的第 6 周更新,首次发布;并且在第二次发行的第 16 周。
证明图像分类的合理性:用什么像素来决定?
在本文中,我将向您展示一种简单的方法来推理图像分类神经网络模型所做的预测。我已经为您提供了代码来重新创建我的发现,但是您不需要阅读代码来理解这篇文章(希望如此)。
你应该从这篇文章中得到的想法是,你想对神经模型“看到”什么或“它在看哪里”有一些了解,这样你就可以更有信心地相信它做出的预测。
基础知识
让我们回顾一下,在一个超高的水平上回顾一下基础知识。可以训练一个卷积神经网络模型,根据图像中的内容对图像进行分类,我们用准确度、精确度、召回率等指标来衡量这个图像分类器的性能。这些模型非常标准,你基本上可以下载一个预先训练好的神经网络模型(例如 inception-V4 、 VGG19 、 mobilenet 等等)。如果您想要识别的类(事物)不在预训练模型识别的内容列表中,那么您通常可以通过使用预训练模型的大部分权重和连接来重新训练预训练神经网络模型以识别新内容。这叫做迁移学习。
所以,基本上,我们有一堆模型,它们接受图像,吐出标签。但是我为什么要相信这些模型呢?让我们来看看这些模型中的一个使用什么信息来进行预测。这种方法也可以用来测试许多其他模型,包括定制模型。
信任但核实
我们在的真实世界 AI 问题中很好地提到了 The Verge 谈论这些图像分类系统如何可能出错,如果你不考虑它们正在做的事情的细节(全文在此)。
神经网络可以学习从训练数据的错误部分进行预测。这是我们试图通过验证模型预测的基础来消除的问题。如果您想要建立一个分类器模型来区分狼和狗,您想要通过查看背景中的雪(狼)和玩具(狗)来确保该模型没有作弊。我们想知道哪些像素参与了预测。我们不希望雪中的狗被视为狼。把这种方法想象成人工智能(AI) 的测试 - 驱动开发 ( TDD ) 。我们首先定义一个测试(来自某个显而易见的类的一些图片),然后对照这个图片检查模型,看看模型是否使用我们认为相关的信息做了我们想要它做的事情。然而,我们并没有写测试用例,而是用我们的眼睛来观察这个测试用例,看看发生了什么。
我的文章的最初版本使用了一张黛米·罗斯的图片,因为为什么不呢…但新版本使用了库存照片比基尼模型,因为版权和合理使用法正在粉碎创意世界。好的。发泄完了,又回到文章:我们就用deep shap来看看-16(其中使用了 imagenet 类标签 )如何解读一张图片。
Shap builds an explanation for the model prediction using information about the dataset, and the activations in the model itself (source: the shap github repo)
真实的例子
以下是本文代码的链接,您可以直接将其放入 Google Collab:
检查 deepSHAP 如何在 VGG-16 上工作(探索预言的原因)- dcshapiro/funWithShap
github.com](https://github.com/dcshapiro/funWithShap/)
代码的第一部分安装 deepSHAP 并运行其中一个示例的一部分,以显示该库工作正常。接下来,我们查看输入图像的形状(224,224,3 ),并看到 VGG-16 模型接受高度和宽度为 224 的正方形图像,具有 3 个颜色通道(红色、绿色和蓝色)。
我们现在抓取比基尼模特的图像,并将其裁剪为 224×224×3 的正确尺寸。
The image on the left was cropped to the right shape/size, using the image on the right as a starting point.
既然 cv2 决定为恶,对颜色通道使用 BGR 编码,那么就有一个将 RGB 颜色数据切换为 BGR 颜色数据的编码步骤。
既然预处理已经完成,让我们开始工作吧。模型在这张图片中看到了哪些类(类别)?哪些像素有助于或有损于这些分类意见?
From left to right: The input image, the strongest prediction (cowboy_hat), followed by the second strongest prediction (sombrero), and so on. The scale on the bottom of the image shows relative positive or negative strength (the SHAP value). In each prediction image, the contribution of each pixel to the prediction is shown.
显然,在预测“cowboy_hat”时查看上面的图像,牛仔帽使用帽子中的像素来做出决定。那很好。它还使用了泳衣的几个像素,但让我们更深入地挖掘一下。为什么不用白色、黑色或随机噪声遮挡图像的一部分,看看这如何改变预测。
Prediction explanation when the top half of the image is whited out.
Prediction explanation the when top half of the image is blacked out.
Prediction explanation when the top half of the image is filled with random noise pixel values.
我们来思考一下上面的结果。首先,很高兴看到顶级预测(模型看到的)对我们使用的屏蔽类型(白色、黑色或噪声)不敏感。这表明模型关心真实的数据。此外,无关掩蔽区域对决策的贡献非常小,只有少数例外(创可贴和凉鞋)。此外,根据我们对人类的期望,预测的类 maillot 是正确的。“maillot”是个有趣的词。我得去查一下。它的发音更像“my-yo”而不是“mail-lot”,根据谷歌的说法,它是“一件女式泳衣”很高兴知道。比基尼在这里也很有意义。其余的类都与图像相关,这也是一个好现象。注意凉鞋也在里面。我猜沙滩装会让模特想起穿凉鞋的照片。或者胸罩上的斑点图案看起来像凉鞋?也许纱笼和超短裙经常伴随着皮肤,我们看到触发那些标签的像素是女孩脸上的皮肤和胸罩肩带附近的肩部区域。
好吧!所以我们到了图像的上半部分。让我们做同样的掩蔽工作,看看会发生什么:
Prediction explanation when the bottom half of the image is whited out.
Prediction explanation when the bottom half of the image is blacked out.
Prediction explanation when the bottom half of the image is filled with random noise pixel values.
我们看到顶级预测类 cowboy_hat 是有道理的。图像中有一顶帽子,脸部(尤其是眼睛)的像素大概有助于网络知道帽子在一个头上。
结论
在本文中,您了解了一种简单的方法来推理图像分类神经网络模型所做的预测。这只是神奇的形状库的一个应用。我们研究了输入图像中的哪些像素有助于神经网络模型进行预测。我们看到,图像的掩蔽(分块)部分会改变预测,但模型的顶部预测不会根据掩蔽的类型而改变。重要的是,我们观察到各种预测中涉及的像素位置是有意义的。欢迎您使用这种方法来验证和询问您自己的神经网络模型。
如果你喜欢这篇文章,那么看看我过去最常读的一些文章,比如“如何给一个人工智能项目定价”和“如何聘请人工智能顾问”嘿,加入我们的时事通讯!
下次见!
——丹尼尔
Lemay.ai
丹尼尔@lemay.ai
JVM 与 DVM
在本文中,我们将看到 Java 虚拟机和 Dalvik 虚拟机之间的区别
Photo by patricia serna on Unsplash
七年前,当我学习 Java 编程时,我曾经向我自己和朋友询问过许多关于这种奇妙语言的问题,但是有一个问题在我没有找到满意答案之前,大部分时间都是突然出现的。问题是为什么 java 字节码可以在任何机器或平台上运行,它与其他代码有什么不同?。这个问题的答案在当时对我来说并不容易,因为我刚刚起步。
因此,在本指南中,我将回答以下问题
- JVM 与 DVM
- Android OS 为什么用 DVM 而不是 JVM?
Java 虚拟机
一个 Java 虚拟机 ( JVM )是 Java 程序和运行 Java 代码的平台之间的抽象层。JVM 是平台相关的,不同的实现可用于特定的平台。
例如,如果您有一个Hello.java
类,当您运行这个类文件时,javac 编译器会将您的源代码转换为bytecode
并创建Hello.class
文件,这意味着javac
编译器不会像其他编译器那样将 Java 代码直接转换为机器码。字节码是中间代码,这意味着人类不能理解这种代码,并且这种代码不依赖于机器/平台。因为字节码是一种中间代码,所以你可以把它交给任何人在任何平台上运行,这就是为什么我们称 Java 应用程序为 WORA(编写一次,在任何地方运行)。
Image credit to netjs
从上图可以看出,一旦你有了。类文件准备好了,你就可以把这个文件给任何平台,它会把它转换成本机代码。
达尔维克虚拟机
Dalvik 虚拟机(DVM) 是执行 android 应用程序的虚拟机。因为手机的一切都非常有限,无论是电池寿命、处理能力还是内存等等。它已经过优化,可以适应低功率设备。
Image Credit to Tam H. Doan
从上图中可以看出,除了最后两步,一切都和 JVM 一样。Dex 编译器将类文件转换成。在 Dalvik 虚拟机上运行的 dex 文件。多个类文件被转换成一个 dex 文件。
JVM 与 DVM
在 android 中使用 DVM 的主要原因之一是因为它遵循基于寄存器的模型,并且比基于堆栈的模型快得多,而 JVM 遵循基于堆栈的模型,后者占用大量内存并且比 DVM 慢。
有一些主要的区别,让我们来看看
Credit to aatul.me
Android OS 为什么用 DVM 而不是 JVM?
Google 不选择 JVM 而选择 DVM 有几个原因,所以让我们一个一个地理解它们。
- 尽管 JVM 是免费的,但它是在 GPL 许可下的,这对 Android 是不利的,因为大多数 Android 是在 Apache 许可下的。
- JVM 是为桌面设计的,对于嵌入式设备来说太重了。
- 与 JVM 相比,DVM 占用的内存更少,运行和加载速度更快。
——俄亥俄州立大学
结论
JVM 将基于字节码工作,DVM 将基于优化的字节码工作,它针对移动平台进行了优化,因为移动设备具有更少的内存、低进程和低功耗,这就是它使用 linux 内核的原因。
我希望你喜欢读这篇文章,你也可以访问我的 网站 ,在那里我会定期发布文章。
订阅 我的邮件列表,以便在您的收件箱中直接获得我的文章,并且不要忘记关注我自己在 Medium 上发表的文章The Code Monster来完善您的技术知识。
了解你的作者
希曼舒·维尔马毕业于印度勒克瑙的 APJ 阿卜杜勒·卡拉姆大学博士。他是 Android & IOS 开发人员、机器学习和数据科学学习者、金融顾问和博客作者。
K-means:完全介绍
K-means 是一种无监督聚类算法,旨在将未标记的数据划分为特定数量(即“K”)的不同分组。换句话说,k-means 找到共享重要特征的观察值,并将它们一起分类到聚类中。一个好的聚类解决方案是找到这样的聚类,使得每个聚类内的观察值比聚类本身更相似。
这种自动数据分组非常有用的例子数不胜数。例如,考虑为投放市场的一系列全新产品创建在线广告活动的情况。虽然我们可以向所有人展示单一的通用广告,但更好的方法是将所有人分成具有共同特征和兴趣的人群,向每个人群展示定制的广告。K-means 是一种算法,它在大数据集中找到这些分组,而手动完成这些分组是不可行的。
算法背后的直觉实际上非常简单。首先,我们为 k (集群的数量)选择一个值,并为每个集群随机选择一个初始的质心(中心坐标)。然后,我们采用两步流程:
- 分配步骤-将每个观察值分配到其最近的中心。
- 更新步骤-将质心更新为其各自观察的中心。
我们一遍又一遍地重复这两个步骤,直到集群中没有进一步的变化。此时,算法已经收敛,我们可以检索我们的最终聚类。
The K-means algorithm in action
进一步的细节
在继续下一步之前,值得后退一步来明确我们所说的好的集群解决方案的含义。我们到底将什么定义为可能的最佳集群解决方案?考虑以下对同一个质心的两种可能的观测分配的可视化。
Which data points should be assigned to this centroid?
很明显,第一个赋值优于第二个,但是对于 k-means 算法,我们如何量化这一点呢?解决方法是考虑连接每个观察到的潜在中心的红色虚线。如果我们比较好的赋值和坏的赋值的这些行的平均长度,很明显前者会产生一个小得多的值。这是我们的目标!在我们可能选择的无限多个可能的聚类中心中,我们正在寻找使这些线的总和最小化的一个,或者更正式地说是误差平方和(SSE) 。用数学术语来说,对于 xᵢ ∈ {x₁,x₂,…,xm 的一组观察值,我们希望找到质心 C 以最小化:
其中,由于我们已将质心定义为其各自观测值的中心,我们可以计算:
这个等式给出了单个质心 C 的误差平方和,但实际上我们希望最小化所有质心cⱼ∈{c₁,c₂,…,ck}对所有观测值 xᵢ ∈ {x₁,x₂,…,xn}的误差平方和。因此,k 均值的目标是最小化误差平方和(SST) 目标函数:**
虽然随着数据的增长,检查每个可能的聚类解决方案变得不可行(NP-hard),但 k-means 在许多实际应用中倾向于找到足够好的解决方案。
到目前为止我们忽略的一个问题是选择集群的数量。偶尔我们会从一开始就知道 k,也许我们的在线广告活动已经预算了正好五个独特的广告,需要正好五个聚类,但是更多的时候我们不知道数据集中聚类的最佳数量。选择 k 没有完美的解决方案,但是一种流行的启发式方法被称为肘法。这包括对一系列的 k 值应用 k 均值,并在所谓的样板图中绘制出相对于 SST 的 k 的选择。然而,请注意,随着我们增加聚类的数量,SST 将总是下降(考虑当我们设置聚类的数量等于观测的数量时 SST 会发生什么),因此我们正在寻找添加更多聚类不再提供 SST 的显著下降的点。换句话说,我们希望在碎石图中找到一个拐点,在此拐点之后,增加 k 不再能改善我们的整体解决方案。
Finding “the elbow” where adding more clusters no longer improves our solution
k-means 的最后一个关键方面回到了这个概念收敛。我们之前提到过,k-means 算法不一定会收敛到全局最小值,而是可能会收敛到局部最小值(即 k-means 不能保证找到最佳解)。事实上,根据我们为初始质心选择的值,我们可能会得到不同的结果。
由于我们只对给定选择的 *k,*的最佳聚类解决方案感兴趣,因此该问题的常见解决方案是多次运行 k-means,每次使用不同的随机初始质心,并且只使用最佳解决方案。换句话说,总是运行 k-means 多次,以确保我们找到接近全局最小值的解决方案。
进一步的考虑
到目前为止,我们已经讨论了 k-means 聚类方法的具体细节,本节将介绍对原始算法的一些扩展。
K-均值算法的一个问题是它对异常值的敏感性。由于质心是作为聚类中观察值的平均值来计算的,因此数据集中的极值会严重破坏聚类解决方案。K-medoids 是克服这个问题的流行方法。顾名思义,这种替代算法使用球心而不是质心作为聚类的中心点,这仅仅意味着聚类的中心必须是该聚类中的一个观测值。
In this case, the medoid is a more representative centre than the centroid
这可以比作取一组数字的中间值而不是平均值,同样的,中间值对极值不太敏感。使用 medoid 需要调整常规 k-means 算法的更新步骤。更新阶段现在变成了一个交换阶段,在这个阶段,我们贪婪地考虑将当前的 medoid 与集群中的其他观测值进行交换,并检查这种交换是否会改进整个集群解决方案。
分类数据 —我们应该承认的 k-means 算法的一个局限性是它要求数据是数值型的。性别等分类变量对 k-means 没有意义。一群男女的意思是什么?我们还能对部分甚至完全分类的数据进行聚类吗?
完全分类数据的解决方案被称为 k-modes。这种方法非常类似于 k-means,但是以一个聚类的模式为中心,然后使用一种新的度量来计算每个观察值与其聚类中心之间的距离。该距离度量比较观察值 X 和聚类模式 Z 之间每个属性的相异度,并对这些值求和。与几乎与 Z 相同的观测值相比,与 Z 具有许多不同属性的观测值将采用更高的相异度值。具体来说,对于观察值 X 和质心 Z 的属性,相异度计算如下:
相异度通过频率进行加权,该频率试图说明属性内值分布的不平衡,因此 n 是聚类中的观察总数,而 n ⁽ʳ⁾是聚类中采用相关值 n 的观察总数。K-modes 然后以与 k-means 相同的方式使用这种相异度作为距离的度量来分配和更新聚类。
最后,对于分类数据和数值数据的混合数据,我们可以应用 k 原型算法,它本质上是 k 均值和 k 模式的混合。我们的聚类中心现在被称为原型,正如我们在这一点上可能猜到的,简单地对数字属性应用 k-means 距离度量,对分类属性应用 k-modes 相异度度量,将两者结合起来作为相异度的总体度量。有了这个设置,我们可以再次应用相同的旧的分配-更新方法。
聚类验证—k-means 等无监督方法的一个缺点是,没有明显的方法来评估我们得到的解决方案。我们得到的解是否充分地抓住了集群结构?数据中是否存在任何聚类?当然,有时我们可以绘制数据并观察结果,但这仅在二维中有效,而且聚类通常只会在更高维中变得有趣(如果我们已经可以看到数据中的聚类,为什么还要麻烦 k-means)。
一种流行的方法是检查集群解决方案的稳定性。这种方法背后的基本原理是,如果数据中真的存在聚类,那么当我们比较来自该数据的多个样本时,它们应该表现出相似的聚类解决方案。在下面的例子中,我们采用了两个数据集,一个显然包含三个聚类,另一个只是均匀随机放置的观察值。我们从每个样本中抽取若干 bootstrap 样本(替换样本),并对每个样本应用 k-means。在结构化数据中,k-means 反复找到相似的解决方案,然而在非结构化数据中,聚类更加不一致。这种稳定性差异可以通过比较聚类平均值的位置或使用更多的技术统计数据(如连续样本的平均轮廓宽度)来更严格地量化。
模糊 C-means—K-means 的另一个我们尚未解决的限制可以归因于硬聚类和软聚类之间的差异。 K-means 是一种硬聚类方法,这意味着每个观察值都被划分到一个单独的聚类中,而没有关于我们在该任务中有多自信的信息。实际上,如果观测值大约在两个质心的中间,将这种不确定性编码到输出中会很有用。软聚类通过给我们一个观察值属于每个质心而不是一个分类的概率估计,解决了这个问题。当然,我们仍然可以将每个观察值分配给提供最高值的质心,但现在我们有了一个对该决策的置信度估计,允许我们区分正好在某个簇质心旁边的观察值和那些更模糊的观察值。模糊 C 均值采用这种软聚类方法。
那么模糊 C-means 和原来的 K-means 算法有什么不同呢?幸运的是,这种调整根本没有改变我们的方法,相反,它只是包括了所谓的模糊化器项wt16】ᵢⱼᵐ(用 m 简单地说就是一个超参数)来包含我们在集群 j 中的成员确定性 X ᵢ的权重。这意味着我们希望最小化的模糊 C 均值目标函数由下式给出:
在哪里
并且应用这些新的等式,我们重复在原始 K-means 中采用的完全相同的分配和更新方法。
R 实施
做得好,一路走到了最后,在 twitter 上关注我以了解未来的帖子。所有的观想都是我自己的。
k 均值聚类
更简单直观的解释。
K-means 是最简单的无监督学习算法之一。该算法遵循一种简单易行的方法,将给定的数据集分组为一定数量的相关子集,称为簇。这个想法是找到 K 个中心,称为簇质心 *,一个对应一个簇,因此得名 K-均值聚类。*当看到一个新示例时,该算法根据距离度量(如欧几里德距离)报告该示例所属的最接近的聚类。
The dataset used for illustration. The dataset consists of 8 points — those 8 points are plotted as blue circles in the graph below.
The diagram is a typical illustration of clustering, with K=2 clusters and their cluster centroids shown evidently with a green and a yellow cross respectively. The circles correspond to the dataset and the crosses correspond to the cluster centroids.
为了更好地理解,让我们考虑一个例子——假设一个社交网站想要找到具有相似兴趣的人群,并向他们投放相关广告。解决这个问题的一种方法是通过聚类,该公司可以使用喜欢的页面、分享的帖子和登记的位置等特征来建立数据集,并通过聚类算法来运行它,以识别相关的群体。不过需要注意的一点是,数据集是未标记的。
A note on the notation. x_{i} means x subscript i, x_{^th} means x superscript th and x_{^th}{i} means x superscript th and subscript i.
算法
K 均值聚类算法从初始化步骤开始,称为随机初始化步骤。该步骤的目标是为每个 K-聚类随机选择一个质心, u_{i} i ∈ {1,2,3…K}。
For the sake of simplicity only 8 data points have been considered. Out of these 8 points two points, drawn as a cross have been randomly chosen as cluster centroids illustrating random initialisation step.
然后使用迭代算法将这 K 个质心收敛到最优值。迭代的每一步都执行以下两步—
- 集群分配
- 移动质心
聚类分配步骤遍历数据集中的每个示例 x_{^i} ,并基于距离度量(比如欧几里德距离)将其分配给其最近的聚类质心。对于下面讨论的例子,可以说——给定一个例子,聚类分配步骤根据该例子离聚类质心的距离将其分配给一种颜色,绿色或黄色。
Cluster Assignment Step
移动质心步骤通过取分配给相同聚类质心的样本的平均值来计算新的聚类质心。或者,用黄色和绿色着色的所有点的平均值给出聚类质心的新值。为了清楚起见,这是负责随机初始化的群集质心收敛到最佳值的步骤。
Move Centroid Step.
该算法一直持续到收敛,也就是说,直到两次后续迭代没有给出几乎相同的聚类质心值。
改进随机初始化
如前所述,该算法从随机初始化步骤开始,但随机初始化可能会导致算法陷入局部最优。
一种提高我们以更好的聚类质心值结束的几率的方法是多次执行随机初始化步骤,并选择一组值,该组值导致由下式给出的失真成本函数的最小值—
||a-b|| implies the Euclidean distance between vectors a and b. Interpret u_{^i}{c} as — cluster centroid of the cluster, to which example x_{^i} has been assigned. Concretely, u_{^ 3}{2} means, the third example is closest to the 2nd cluster centroid.
上面的成本函数正在计算每个训练示例 x_{^i} 和它被分配到的集群 u_{^i}{c}.之间的平方距离的平均值平方是为了完全避免欧几里德距离引起的平方根。显然,较小的成本函数值对应于较好的初始化。
这种技术对于 K≤10 的值有效,但是已经观察到,对于较大的 K 值,它不会产生显著的差异。对于较大的 K 值,K-means 算法将几乎收敛到可接受的聚类质心值。此外,这种优化随机初始化步骤的方法计算量很大。
选择 K 的值
到目前为止,您一定已经对 K-means 聚类算法有了直观的了解,但还有一个方面需要处理,即参数 K。让我们看看如何知道数据集需要划分的聚类数。
肘形法可用于寻找 K 的最佳值。该方法根据失真成本函数值绘制聚类数,并在图形向外弯曲或急转弯处选择 K 值。
Elbow method : The optimal value of K is 3 from the above graph as graph elbows out at 3.
但实际上这种方法用得不多,因为当绘制真实世界的数据时,图形通常没有一个显著的拐点来选择 k 值。
Elbow method : Real world plot where it is hard to point out any elbow.
不幸的是,没有自动选取 K 值的方法。大多数情况下,参数 K 的值是通过查看可视化来手动选取的。
k 均值聚类
Source: Pixabay
使用无监督学习理解文本数据
、客户细分、文档分类、房价估算、欺诈检测 。这些只是集群的一些实际应用。这种算法还有许多其他的使用案例,但是今天我们将把 K-means 应用于文本数据。特别是,我们将从头开始实现该算法,并将其应用于安然电子邮件数据集,并展示这种技术如何成为总结大量文本并揭示有用见解的非常有用的方法,否则这些见解可能是不可行的。
那么 K-means 到底是什么?嗯,它是一种无监督的学习算法(意味着没有目标标签),允许您在数据中识别相似的数据点组或聚类。为了了解它为什么有用,想象一下上面提到的一个用例,客户细分。使用这种算法的公司可以根据客户的特点将他们分成不同的组。这可能是一种非常有用的方式,可以进行有针对性的广告或提供个性化折扣或促销等可能推动收入增长的东西。对于我们的用例,它可以帮助我们快速洞察和解释文本数据。当我们有大量的数据时,这是非常有用的,并且对于某些人来说手动浏览它是不实际的。
作为一名经济学家,我能够用这种方法来分析一次公众咨询,其中很多回答都是定性的。利用我的机器学习知识,我能够创建有用的见解并对数据有所了解,同时为我的同事避免了相当多的手动工作,这很好。
更正式地说
同样,K 均值的问题可以被认为是将数据分组为 K 个聚类,其中对聚类的分配是基于到质心的某种相似性或距离度量(稍后将详细介绍)。那么我们如何做到这一点呢?好吧,让我们首先概述一下所涉及的步骤。
- 我们随机初始化 K 个起始质心。每个数据点被分配到其最近的质心。
- 质心被重新计算为分配给相应聚类的数据点的平均值。
- 重复步骤 1 和 2,直到我们触发停止标准。
现在你可能想知道我们在优化什么,答案通常是欧几里得距离或者欧几里得距离的平方更精确。数据点被分配给最接近它们的聚类,或者换句话说,最小化该平方距离的聚类。我们可以更正式地把它写成:
K means Cost Function
J 就是每个数据点到它所分配的聚类的平方距离之和。其中 r 是指示函数,如果数据点(x_n)被分配给聚类(k ),则等于 1,否则等于 0。这是一个非常简单的算法,对吗?如果还不完全清楚,不要担心。一旦我们将它可视化并编码,它应该更容易理解。
k 表示可视化
我一直热衷于使用视觉辅助工具来解释主题,这通常有助于我对各种算法实际发生的事情有更深的直觉。所以让我们看看每次迭代后 K 的意思是什么。
K mean Algorithm, Source: Bishop
正如你所看到的,上图显示了 K 值的作用。我们已经定义了 k = 2,所以我们在每次迭代时将数据分配给两个集群中的一个。图(a)对应于随机初始化质心。在(b)中,我们将数据点分配给它们最近的聚类,在图 c 中,我们分配新的质心作为每个聚类中数据的平均值。这一直持续到我们达到停止标准(最小化我们的成本函数 J 或预定义的迭代次数)。希望上面的解释和可视化能让你很好的理解 K 的意思。接下来,我们将在 Python 中实现这个算法。
数据集和代码
正如我之前提到的,我们将使用文本数据,特别是,我们将查看在 Kaggle 上提供的安然电子邮件数据集。对于那些不知道围绕安然的故事/丑闻的人,我建议看看房间里最聪明的人。这是一部关于这个主题的特别好的纪录片。
只有一个问题
我们能不能只给我们的算法一堆文本数据,然后期待任何事情发生?很遗憾,不行。算法很难理解文本数据,所以我们需要将数据转换成模型可以理解的东西。计算机非常擅长理解数字,所以我们试试看怎么样。如果我们将每封电子邮件中的文本表示为一个数字向量,那么我们的算法将能够理解这一点并据此进行处理。我们要做的是使用**术语频率-逆文档频率或 TF-IDF 将每封电子邮件正文中的文本转换为数字向量。**我不会太详细地解释这是什么,因为我在之前的帖子中已经解释过,但本质上它使我们能够计算每封电子邮件中的单词相对于该电子邮件中的内容以及相对于数据集中所有电子邮件的重要性。更多关于 TF-IDF 的信息请点击这里。
好了,我们需要做的第一件事是导入所需的库和数据集。我应该提到,我试图在 Kaggle 内核中使用完整的数据集,这是一个挑战。我遇到了一些内核故障,所以我最终使用了大约 70%的完整数据集,运行时没有任何问题。请注意,我没有把代码的数据清理部分放在帖子里,因为我们关注的是 K 均值算法。对于那些感兴趣的人来说,完整的代码可以在我的 Kaggle 内核上找到,链接在文章的最后。像往常一样,我们导入将要使用的库,并读入数据集。
在我们做了一点文本清理之后,例如转换成小写,删除无用的单词和 HTML,我们可以继续使用 TF-IDF,这在 sklearn 中非常简单。
运行这段代码后,我们可以使用下面的 get_feature_names()方法先睹为快。
pd.DataFrame(tf_idf_array, columns=tf_idf_vectorizor.get_feature_names()).head()
现在我们需要考虑我们的 K 意味着类将会是什么样子。嗯,我们需要实现一些方法,这些方法对应于我上面概述的步骤。我们将实现以下 5 个方法,这将有助于我们把算法分成可管理的部分。
- 初始化 _ 质心
- assign _ clusters
- 更新 _ 质心
- fit_kmeans
- 预测
上面的代码定义了我们的 Kmeans 类,init 和 initialise _ centroids 方法。我们希望我们的类接受一些参数,比如聚类的数量、迭代的次数以及我们需要的可重复性的种子。设置种子是一个重要的步骤,因为我们在算法开始时随机初始化我们的质心。如果我们没有设置种子,那么每次运行算法时,我们可能会收敛到不同的聚类集。初始化 _ 质心方法简单地选择 k 个随机数据点,并将它们设置为初始聚类中心,以开始算法。
我们现在需要编写将数据点分配给特定聚类的方法,并更新聚类中心。请记住,我们根据到中心聚类的欧几里德距离将数据分配给聚类。我们使用 sklearn 的成对距离方法,该方法简化了我们的计算,并返回到每个聚类中心的距离。argmin 函数确定到每个聚类的距离最小的索引,从而允许我们为该索引分配正确的聚类标签。现在,为了完成算法的一次迭代,我们只需要将质心更新为分配给特定聚类的所有数据点的平均值。
接下来的两个方法也很重要。预测方法基本上基于我们的算法为每个数据点返回相应的预测聚类标签。下面代码片段中的最后一个方法通过调用我们之前定义的函数来适应我们的模型。好了,这就是我们的 k-means 类。现在,我们只需在运行我们的算法时,计算出要选择的最佳聚类数。
最佳聚类数
当使用 K-means 时,我们需要做的事情之一是确保我们选择了最佳的聚类数。太少,我们可能会把有显著差异的数据分组在一起。太多的聚类,我们将只是过度拟合数据,我们的结果将不会概括得很好。为了回答这个问题,我们将使用 肘法 ,这是这项任务中常用的技术。它包括使用不同数量的聚类来估计模型,并使用 sklearn 的评分方法来计算每个所选数量的聚类的 组内平方和 的负值。请注意,这只是我们上面的目标函数的负值。我们选择这样一个数字,在这个数字上增加更多的聚类只会略微增加分数。绘制的结果看起来明显像一个肘部(或者在这种情况下是颠倒的肘部)。群集数量的最佳选择是肘部形成的位置,在我们的示例中为 3,我们可以从下图中看到这一点。(我们也可能用 4 个集群进行实验,但对于此实施,我们将使用 3 个集群)
Optimal Number of Clusters
我的实现
在这篇文章的这一部分,我们将实现刚刚用 Python 编写的算法。为了以图形方式查看我们的聚类,我们将使用 PCA 来降低我们的特征矩阵的维度,以便我们可以以二维方式绘制它。也就是说,我们选择两个组件,并使用 PCA 类的 fit_transform()方法转换我们的 tf_idf_array。然后我们创建一个 Kmeans 类的实例,根据上面的分析选择 3 个集群。现在只需要调用 fit_kmeans()和 predict()方法将我们的数据点放入集群中。因为我们已经将阵列投影到一个 2-d 空间中,所以我们可以很容易地使用散点图来显示它和聚类中心。
我们可以在这里看到三个非常不同的集群,紫色集群的分离度特别大,这表明电子邮件的内容有很大的不同。但是,大部分数据都包含在绿色集群中。
Figure 2: My Implementation Clustering Results
SK-Learn 实现
作为一种感觉检查,我们将使用 sklearn 重新进行这个估计。在现实世界中,我非常怀疑你会从零开始实现它,因为它并不是真正需要的。然而,这是一个非常有用的方法,可以具体地理解 k-means 是如何工作的,因此绝对值得亲自去做。我们可以看到,sklearn 使估计变得简单得多,如果我们绘制结果,两个图形看起来非常相似。这是令人放心的,并使我们自己的代码不太可能有错误。尽管星团的颜色因为某种原因发生了变化??
Figure 3: sklearn Clustering Results
检查每个聚类中的顶部单词
在这一部分,我们将快速浏览一下我们得到的结果。我们主要感兴趣的是看每个词群中的词之间是否有任何共性或者任何突出的特定词。换句话说,我们能在每个集群中识别主题吗?如果我们可以,那么这是一种非常强大的方式来获得对电子邮件内容的总体感觉,并可以指导我们希望做的任何进一步分析,最好的部分是我们不必阅读 35,000 封电子邮件。我们可以使用下面的方法来查看每个聚类中的顶部单词,该方法仅识别每个聚类中具有最高平均 tf_idf 分数的特征。
下面是对应于每个聚类中前 15 个单词的三个图,按照 TF-IDF 测量的相对重要性排序。
Figure 3: Cluster 0
Figure 4: Cluster 1
Figure 5: Cluster 2
好吧,那么这些数字想告诉我们什么呢?这里有什么有趣的特色吗?总的来说, 集群 0 似乎有不少可能相当重要的人的名字。我们可以立即开始查看来自莎莉、约翰和埃里克的电子邮件,看看是否有什么有趣的内容。 集群 1 似乎一般是关于具有主席、日历和时间等特征的会议。同样,这对于缩小我们想要进一步检查的电子邮件的范围非常有用。 Cluster 2 似乎有很多词语暗示这些电子邮件来自请求东西的人。虽然从表面上看,这并不立即有趣,但也值得进一步研究。下面是 Kmeans 类的完整 Python 代码。
Kmeans 类的完整代码
一些需要记住的事情
现在应该很清楚,k-means 是一个简单而强大的算法,它对于分析中可能出现的许多不同类型的问题非常有用。也就是说,对于你的特定问题来说,它可能并不总是最好的选择,如果你要使用它,你需要知道算法的一些假设。大概 k-means 最大的假设和限制就是它假设 **簇是球形的。如果事实并非如此,那么 k-means 可能不是最佳解决方案。k-means 算法的另一个限制是数据点被 【硬分配】 到一个聚类。换句话说,数据点要么在集群中,要么不在集群中。当然,我们对某些数据点在一个集群中比其他数据点更有信心?如果我们能以某种方式将这种信心融入到我们的结果中,不是更好吗?
幸运的是,我们可以使用另一种技术来解决这些问题。我们可以使用一种叫做 高斯混合建模或者GMM 的算法。这样做的好处是,我们以软分配结束,即每个数据点以一定的概率属于每个聚类。除此之外,GMM 还对聚类的方差做出了限制性稍小的假设。缺点是这是一个更复杂的算法,但这是我想在另一篇文章中进一步讨论的。
好了,就这样了,伙计们,感谢阅读。希望这已经让你很好地理解了 K 均值以及如何在 Python 中完全实现它。我们可以在代码中实现一些额外的功能,如 智能初始化(k-means++) 或算法的更好的收敛计算,但我在这里没有做这些。你们试一下怎么样?如果你想了解良好的编码实践,我认为一个很好的起点是 sklearn 的 GitHub。已经实现了大量的算法,并且它们都经过了数据科学社区的尝试和测试,所以我鼓励人们看一看,并尝试自己实现其中的一些算法。这是一种很好的学习方式。
链接到 Kaggle 内核:https://www . ka ggle . com/d foly 1/k-means-clustering-from-scratch
来源:Christopher m . Bishop 2006,模式识别与机器学习
来源: 机器学习的贝叶斯方法
注意:这篇文章中的一些链接是附属链接
K-Means 使用 Scikit-Learn & NLTK 对 Chardonnay 评论进行聚类
霞多丽是世界上最受欢迎的白葡萄酒。这种葡萄很容易种植,它以复杂和适应不同的技术和口味而闻名。例如,昨晚我尝了一种甜味的未发酵的夏敦埃酒。霞多丽到底有多受欢迎?正如 2018 年加州葡萄种植面积报告所述,在 176,092 英亩专用于白葡萄酒的总面积中,霞多丽消耗了一半以上,为 93,148 英亩!下一个最高的品种是法国科隆巴德,消耗 18246 英亩;相比之下微不足道。那是许多葡萄!
S 因为我熟悉 kaggle 上的葡萄酒评论数据集,所以我决定加载一个笔记本来分析夏敦埃酒。
聚类能帮助我们确定描述和评级之间的关系吗?
在本文中,我将展示如何使用 Scikit-Learn 和自然语言工具包来处理、分析和聚类 Chardonnay 数据。通过使用这些技术,我希望能看到评分高于平均水平的葡萄酒评论和评分低于平均水平的葡萄酒评论在主题或话题上是否有所不同。
导入依赖项和数据
因为这篇文章结合了几种技术来分析 Chardonnay 评论,所以我们有相当多的东西要导入。此外,我对数据集做了一些初步清理,删除了重复和空值,并将其存储在 SQLite 数据库中:
#import dependencies
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import refrom sklearn import preprocessing, decomposition, model_selection, metrics, pipeline
from sklearn.feature_extraction.text import TfidfVectorizer, CountVectorizer
from sklearn.cluster import KMeansimport nltk
from nltk.stem.wordnet import WordNetLemmatizer
from nltk.corpus import stopwordsimport sqlite3
from sqlite3 import Error#force output to display the full description
pd.set_option('display.max_colwidth', -1)#connect to database file
conn = sqlite3.connect('db\wine_data.sqlite')
c = conn.cursor()#create dataframe from sql query
df = pd.read_sql("Select country, description, rating, price, title, variety from wine_data where variety = 'Chardonnay'", conn)#display the top 3 rows
df.head(3)
特征工程和分析
从一开始,我就知道我想添加几个特性:首先,我将添加字数统计列来存储每个描述中的字数。其次,我将添加一个二进制字段来表示葡萄酒的评级是否高于平均水平。在我添加这些功能之前,我需要做一些分析来找到平均评级。
分析字数
分析字数可以帮助您决定是否要缩减数据集。例如,查看数据,我们看到一篇葡萄酒评论的最小字数是 3 个词。查看少于 15 个单词的评论,平均评分是 82 分,范围是 80-100 分。这告诉我,简短的评论可能与较低的评级有关。同样,当我观察分布的另一端时,我注意到较长的评论可能与较高的评级相关。
简短的评论可能与较低的评级相关联。更长的评论可能与更高的评级相关联。
#add a column for the word count
df['word_count'] = df['description'].apply(lambda x: len(str(x).split(" ")))print("Word Count Median: " + str(df['word_count'].median()))
print(df['word_count'].describe())x = df['word_count']
n_bins = 95plt.hist(x, bins=n_bins)
plt.xlabel('Number of Words in Description')
plt.ylabel('Frequency')
plt.show()
#word counts less than 15
wc15 = df.loc[df['word_count'] < 15]
print(wc15.rating.median())
print(wc15.rating.describe())#word counts greater than 70
wc70 = df.loc[df['word_count'] > 70]
print(wc70.rating.median())
print(wc70.rating.describe())#plot the counts
plt.figure(figsize=(14,4))
sns.countplot(x ='rating', data = wc70).set_title("Rating Counts")
数据可以可视化,帮助我们看到字数和评分之间的关系。
Rating Counts where Word_Count < 15
Rating Counts where Word_Count > 70
分析评级
因为我想看看描述是否可以用来区分葡萄酒是否高于平均评级,所以我必须找到平均评级。熊猫描述功能使统计数据的查找变得简单。看数据,我们得到的平均评分是 88。使用 list comprehension 很容易将二进制值列添加到数据框中。如果评分大于 88,我们的新列将为 1。如果等级为 88 或更低,值将为 0,因为葡萄酒并不比平均水平好。
如果评分大于 88,我们的新列将为 1。如果等级为 88 或更低,值将为 0,因为葡萄酒并不比平均水平好。
print("Number of Unique Ratings: " + str(len(df['rating'].unique())))print("Rating Median: " + str(df['rating'].median()))
print(df['rating'].describe())plt.figure(figsize=(14,4))
sns.countplot(x='rating', data=df).set_title("Rating Counts")
plt.show()#add column to flag records with rating greater than 88
df['above_avg'] = [1 if rating > 88 else 0 for rating in df['rating']]
Distribution of Chardonnay Ratings
自然语言处理
在对数据进行聚类之前,我使用了几种 NLP 技术,比如删除停用词、标点符号和特殊字符,以及对文本进行规范化。处理完文本后,我将使用 Scikit-Learn tf-idf 矢量器对文本进行矢量化。
清理文本
在聚类之前,我想删除停用词。停用词是常见的词,如“the”和“of”将它们从描述中移除可以突出更相关的常用词。我通过词频来判断是否应该将额外的词添加到停用词表中。此外,我使用正则表达式清理描述,删除标点符号、标签和特殊字符,然后对单词进行词汇化,将单词简化为词根形式,同时保持它是一个真实的单词。词条满足是一种规范化文本的技术:
#create a list of stop words
stop_words = set(stopwords.words("english"))#show how many words are in the list of stop words
print(len(stop_words))
#179#construct a new list to store the cleaned text
clean_desc = []
for w in range(len(df.description)):
desc = df['description'][w].lower()
#remove punctuation
desc = re.sub('[^a-zA-Z]', ' ', desc)
#remove tags
desc = re.sub("</?.*?>"," <> ",desc)
#remove special characters and digits
desc = re.sub("(\\d|\\W)+"," ",desc)
split_text = desc.split()
#Lemmatisation
lem = WordNetLemmatizer()
split_text = [lem.lemmatize(word) for word in split_text if not word in stop_words and len(word) >2]
split_text = " ".join(split_text)
clean_desc.append(split_text)
使用 TF-IDF 对文本进行矢量化
tfidf vector 将文本转换成一个向量空间。为了简化概念,假设你有两个句子:
狗是白色的,猫是黑色的
将句子转换为向量空间模型会以这样的方式转换它们,即查看所有句子中的单词,然后用数字表示句子中的单词。例如,如果单词在句子中,它就是 1。如果该单词不在句子中,则用 0 表示:
狗是白色的猫是黑色的狗是白色的猫是黑色的
TF-IDF 代表词频-逆文档频率。这是一种对单词值进行加权而不是简单计数的方法。它用于确定一个单词对集合文档中的文本有多重要。该功能对于搜索引擎和文本挖掘等信息检索非常有用。Scikit-Learn 中的tfidf 矢量器将一组原始文档转换成 TF-IDF 特征矩阵。它使用 fit_transform 方法返回矩阵。
#TF-IDF vectorizer
tfv = TfidfVectorizer(stop_words = stop_words, ngram_range = (1,1))#transform
vec_text = tfv.fit_transform(clean_desc)#returns a list of words.
words = tfv.get_feature_names()
基于 K-均值聚类的主题抽取
K-means 聚类是一种流行的无监督学习算法,可用于通过将相似的评论分组在一起并产生常用词列表来提取主题。我将试着把数据分成 21 组(n_clusters = 21 ),看看我是否能发现在高评分中常见的主题和在低评分中常见的主题。 Scikit-Learn 使 k-means 的应用变得简单。
#setup kmeans clustering
kmeans = KMeans(n_clusters = 21, n_init = 17, n_jobs = -1, tol = 0.01, max_iter = 200)#fit the data
kmeans.fit(vec_text)#this loop transforms the numbers back into words
common_words = kmeans.cluster_centers_.argsort()[:,-1:-11:-1]
for num, centroid in enumerate(common_words):
print(str(num) + ' : ' + ', '.join(words[word] for word in centroid))
将结果可视化
使用热图,我可以看到评级是如何聚集的。我还可以看到高于平均水平的评级与低于平均水平或低于平均水平的评级相比是否聚集在一起。
#add the cluster label to the data frame
df['cluster'] = kmeans.labels_clusters = df.groupby(['cluster', 'rating']).size()fig, ax1 = plt.subplots(figsize = (26, 15))
sns.heatmap(clusters.unstack(level = 'rating'), ax = ax1, cmap = 'Reds')ax1.set_xlabel('rating').set_size(18)
ax1.set_ylabel('cluster').set_size(18)clusters = df.groupby(['cluster', 'above_avg']).size()
fig2, ax2 = plt.subplots(figsize = (30, 15))
sns.heatmap(clusters.unstack(level = 'above_avg'), ax = ax2, cmap="Reds")ax2.set_xlabel('Above Average Rating').set_size(18)
ax2.set_ylabel('Cluster').set_size(18)
我可以通过分割数据框和绘制聚类数来查看分布情况!
#create dataframe of reviews not above average
not_above = df.loc[df['above_avg'] == 0]
not_above.describe()#create data frame of reviews above average
above_avg = df.loc[df['above_avg'] == 1]
above_avg.describe()#plot the counts
plt.figure(figsize=(14,4))
sns.countplot(x='cluster', data=not_above).set_title("Rating Counts")
plt.show()plt.figure(figsize=(14,4))
sns.countplot(x='cluster', data=above_avg).set_title("Rating Counts")
plt.show()
Not Above stats v.s. Above Average stats
最后的想法和笔记本
观察可视化结果,他们显示高于平均水平的评分更多地集中在 5、6 和 12。这意味着这些聚类中的单词在高于平均评级的葡萄酒评论中被普遍使用。需要更深入地查看聚类中的单词,因为仅查看前 10 个单词时很难区分显著差异。例如,“苹果”、“香气”和“味道”等词出现在几个分组中,这使得人们很难理解不同的主题。此外,有不同的算法可能在主题建模方面表现更好。
潜在狄利克雷分配(LDA) 是另一种流行的无监督学习算法,用于主题建模,其性能优于 K-means。希望我能有机会探索 LDA 并比较我的结果。
你可以从我的 github repo 下载我的笔记本:
此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…
github.com](https://github.com/bendgame/kmeansChardonnay)
谢谢大家!
- 如果你喜欢这个, 跟我上 Medium 了解更多
- 通过订阅 获得完全访问权限并帮助支持我的内容
- 我们来连线一下LinkedIn
- 用 Python 分析数据?查看我的 网站
k-均值聚类与数学
用于数据分析的常见无监督学习技术
Photo by Perry Grone on Unsplash
当我们处理大量数据时,将数据分成逻辑组并进行分析是有意义的。我们可以在 K-Means 等算法的帮助下,使用聚类将数据分组。
在这篇文章中,我将尝试解决
a.使聚集
b.k-均值和算法的工作原理。
c.选择正确的 K 值
使聚集
将对象组织成组的过程,使得同一组中的数据点与同一组中的数据点相似。聚类是对象的集合,其中这些对象与另一个聚类相似和不相似。
k 均值
K-Means 聚类是一种无监督学习。该算法的主要目标是在数据中寻找组,组的数量由 K 表示。这是一个迭代过程,其中每个数据点基于特征相似性被分配到 K 个组中的一个。
算法
K-Means 算法从 K 个质心的初始估计开始,这些质心是从数据集中随机选择的。该算法在两个步骤分配数据点和更新质心之间迭代。
数据分配
在该步骤中,基于平方欧几里德距离,将数据点分配给其最近的质心。让我们假设一个以 c 为质心的聚类,并根据 c,x 之间的距离将数据点 x 分配给该聚类。还有一些其他的距离度量,如曼哈顿、雅克卡和余弦,它们是根据适当的数据类型使用的。
质心更新
通过取分配给特定聚类的所有数据点的平均值来重新计算质心。
image by George Seif
让我们用下面的例子来完成上面的步骤。
- 考虑如下 4 个数据点 A、B、C、D
Observations
2.选择两个质心 AB 和 CD,计算如下
AB =,B 的平均值
CD =、D 的平均值
Two centroids AB, CD
3.计算所有数据点到质心 AB,CD 的平方欧几里得距离。例如,A(2,3)和 AB (4,2)之间的距离可以由 s =(2–4)+(3–2)给出。
A is very near to CD than AB
4.如果我们在图中观察,突出显示的(A,CD)之间的距离是 4,小于(AB,A)的距离 5。由于点 A 靠近 CD,我们可以将 A 移动到 CD 簇。
5.到目前为止已经形成了两个集群,让我们像步骤 2 一样重新计算质心,即 B,ACD。
ACD =、C、D 的平均值
B = B
New centroids B, ACD
6.我们知道 K-Means 是迭代过程,现在我们必须计算所有点(A,B,C,D)到新质心(B,ACD)的距离,类似于步骤 3。
Clusters B, ACD
7.在上图中,我们可以看到各自的聚类值最小,即 A 离聚类 B 太远而离聚类 ACD 近。所有数据点根据它们的最小距离被分配到聚类(B,ACD)。迭代过程到此结束。
8.总之,我们从两个质心开始,以两个集群结束,K=2。
选择 K
选择 K 值的一种方法是肘法。在此方法中,我们将对 K 值范围(K= 1 到 10)运行 K 均值聚类,并计算误差平方和(SSE)。SSE 计算为数据点与其聚类质心之间的平均距离。
然后为每个 K 的 SSE 值绘制一个折线图,如果折线图看起来像一只手臂,那么手臂上的肘部就是最佳的 K 值。
Choose the Best K
希望你喜欢!!请对任何疑问或建议发表评论。
用于无监督机器学习的 k-均值聚类
无监督学习的 Pythonic 指南
Photo by Ramón Salinero on Unsplash
与人类历史上的任何其他技术不同,人工智能(AI)和机器学习(ML)彻底改变了我们生活的方方面面,并扰乱了我们做生意的方式。这种破坏给专业人士和企业带来了许多挑战。在本文中,我将介绍一种最常用的机器学习方法, K-Means。
**首先:**到底什么是机器学习(ML)?!这是一种新的模式吗?
机器学习是一种科学方法,它利用统计方法和机器的计算能力将数据转换为人类或机器本身可以用来采取特定行动的智慧。“它是 人工智能 的一个分支,基于系统可以从数据中学习、识别模式并在最少人工干预的情况下做出决策的想法。” (SaS)
如果你认为人工智能是一种新的范式,你应该知道机器学习这个名字是亚瑟·塞缪尔在 1959 年创造的。然而,这发生在 20 世纪 50 年代艾伦·图灵的一个提议之后,他用“机器能思考吗?”机器能做我们(作为思维实体)能做的事情吗?,或者换句话说,“机器能学习吗?”
所以,ML 已经存在半个世纪了。然而,随着最近机器计算能力的进步,以及我们正在生成、收集和存储的大量数据,ML 已经成为许多行业的下一个大事件。
机器学习的主要领域有哪些?
ML 中有许多字段,但我们可以将三个主要字段命名为:
监督学习(SL): SL 是使用一组输入(预测器)和期望输出(目标)来建立和训练 ML 模型。许多回归(简单或多元)或分类模型都属于这一类。
无监督学习(UL): 当目标未知时,使用 UL,目标是推断数据中的模式或趋势,从而做出决策,或者有时将问题转化为 SL 问题(也称为迁移学习,TL )。这篇文章的重点是 UL 聚类,特别是 K-Means 方法。
强化学习(RL) : 这种范式比 SL 和 UL 更复杂,然而这篇文章提供了 RL 的一个简单而技术性的定义。一般来说,RL 关注的是“主体”(例如模型)如何在环境中采取行动,并且在每个步骤中试图最大化回报(例如优化函数)。RL 的一个很好的例子是使用遗传算法和蛮力的路由优化(在后面的文章中会有更多的介绍)。
阿卜杜勒·瓦希德的下图很好地展示了曼梯·里的这些主要领域。
From https://www.slideshare.net/awahid/big-data-and-machine-learning-for-businesses, Credit: Abdul Wahid
k-均值聚类,已定义
k-均值聚类是一种来自信号处理的方法,目的是将观测值放入 k 个聚类中,其中每个观测值属于一个具有最近均值的聚类。这些簇在数学上也被称为 Voronoi 细胞。
在进入 Python 代码的细节之前,让我们看一下 K-Means 聚类的基础。
K-Means 如何对观察值进行聚类?
聚类算法的主要输入是聚类的数量(这里称为 k )。 k 决定集群机制,以及集群如何形成。在你知道哪一个应该属于一个聚类之前,想出聚类的数量可能是具有挑战性的,尤其是因为你正在处理一个无监督的学习问题。
还有其他无监督学习方法来确定 K-Means 聚类方法的正确聚类数,包括 分层聚类 ,,但我们在本文中不涉及该主题。我们的假设是您知道集群的数量,或者对集群的正确数量有一个大致的概念。最好的方法是进行几次试错,以找到最佳的聚类数。
一旦知道了聚类的数量,就有三种不同的方法来指定聚类中心:
- 手动,
- 随机地,而且
- “k-在 SKLearn 中的意思是++
后者以一种智能的方式为 k-mean 聚类选择初始聚类中心以加速收敛。你可以在这里找到更多。
应当注意,初始聚类中心对最终聚类结果没有任何影响,原因将在下面解释。给定初始聚类中心,该算法重复以下步骤,直到它收敛:
Illustration of K-Means Algorithm, Wikipedia Creative Commons, credit: Chire
需要记住的一点是,K-Means 几乎总是收敛的,但不能保证找到最优解,因为它在局部最小值处终止循环,可能不会达到全局最小状态。
好吧!算法说够了。让我们进入令人兴奋的部分,也就是 Python 代码。
关于 K-均值数据缩放的注记
由于 K-Means 基于数据点到聚类中心的距离工作,因此将数据缩放到相同的比例对于结果的准确性至关重要。
Python 中的 K-Means
为此,我们将使用 SciKit Learn 库。你可以在这里阅读 K-Means 聚类包的文档。
让我们先导入包。
import numpy as np
import matplotlib.pyplot as pltfrom sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
为了说明这个算法是如何工作的,我们将使用sklearn.datasets.
中的make_blob
包。下面的代码片段将生成 5 个集群。在我们的聚类中,我们将不使用聚类名称(y)。
# Create 5 blobs of 2,000 random data
n_samples = 2000
random_state = 42
X, y = make_blobs(n_samples=n_samples,
random_state=random_state,
centers=5)
让我们可视化集群,看看他们在哪里。
# Plot the random blub dataplt.figure(figsize=(6, 6))plt.scatter(X[:, 0], X[:, 1], s=5)
plt.title(f"No Clusters Assigned")
观察这些斑点,我们可以看到我们有三个不同的“区域”,由 5 个斑点组成:
- 左下角有一个斑点,
- 在左上区域中有两个彼此大致邻近的斑点,并且
- 在中间右区有两个几乎重叠的斑点。
让我们看看 K-Means 聚类如何处理这个问题。我们将查看不同的集群编号,从 1 到 10。下面提供了代码,生成的图形放在下面的动画中。
# Plot the data and color code based on clusters# changing the number of clusters
for i in range(1,11):
plt.figure(figsize=(6, 6))
# Predicting the clusters
y_pred = KMeans(n_clusters=i, random_state=random_state).fit_predict(X)# plotting the clusters
plt.scatter(X[:, 0], X[:, 1], c=y_pred, s=5)
plt.title(f"Number of Clusters: {i}")plt.show();
动画情节是用Image.Io
包制作的。有关这方面的更多信息,请参考 Johannes Huessy 博客(点击此处)。
评估 K-Means 聚类算法
所以你已经完成了聚类,但是这个聚类有多好,你如何衡量算法的性能?
**惯性:我们在上一节中讨论了一个度量,即到聚类中心的距离的类内平方和。这就是所谓的 惯性 。该算法旨在选择使、惯性最小化的质心,其中、**可以被识别为内部一致性聚类如何的度量。
您可以使用下面的代码来获得集群的inertia
分数:
km = KMeans(n_clusters=i, random_state=random_state)
km.fit(X)
km.inertia_
下面的代码计算了我们之前所做的 10 个不同聚类数的inertia
分数,并将它们保存在一个列表中,我们将使用该列表进行绘制(稍后将详细介绍)。惯性分数对聚类数的作图称为“ 肘形曲线 ”。
**剪影评分:剪影评分是基于聚类(聚类中的点相对于彼此有多近)和 分离 (聚类相对于彼此有多远)的组合。
剪影得分在-1(聚类差)和+1(聚类优)之间。
惯性
*# Calculating the inertia and silhouette_score¶inertia = []
sil = []# changing the number of clusters
for k in range(2,11):
km = KMeans(n_clusters=k, random_state=random_state)
km.fit(X)
y_pred = km.predict(X)
inertia.append((k, km.inertia_))
sil.append((k, silhouette_score(X, y_pred)))*
现在我们有了惯性和轮廓分数,让我们绘制它们并评估聚类算法的性能。
*fig, ax = plt.subplots(1,2, figsize=(12,4))# Plotting Elbow Curve
x_iner = [x[0] for x in inertia]
y_iner = [x[1] for x in inertia]
ax[0].plot(x_iner, y_iner)
ax[0].set_xlabel('Number of Clusters')
ax[0].set_ylabel('Intertia')
ax[0].set_title('Elbow Curve')# Plotting Silhouetter Score
x_sil = [x[0] for x in sil]
y_sil = [x[1] for x in sil]
ax[1].plot(x_sil, y_sil)
ax[1].set_xlabel('Number of Clusters')
ax[1].set_ylabel('Silhouetter Score')
ax[1].set_title('Silhouetter Score Curve')*
你可以看到,当你增加集群的数量时,惯性得分总是下降。然而,肘曲线可以告诉你以上 4 个集群,惯性的变化并不显著。现在,让我们看看轮廓曲线。您可以看到,最大得分发生在 4 个聚类处(轮廓得分越高,聚类越好)。
将肘部曲线与轮廓得分曲线结合起来,可以提供对 K-Means 性能的宝贵见解。
K 均值的其他用例
K-Means 方法有很多用例,从图像矢量化到文本文档聚类。你可以在这里找到一些例子。
我希望您发现本指南有助于理解使用 Python 的 SkLearn 包的 K-Means 聚类方法。请继续关注更多类似的话题!
尼克·米奈博士 ( 领英简介 )是一位资深顾问和富有远见的数据科学家,代表了领导技能、世界级数据科学专业知识、商业敏锐度和领导组织变革能力的独特组合。他的使命是推进人工智能(AI)和机器学习在行业中的实践。
如何在 BigQuery ML 中做好 k-Means 聚类初始化
使用并行 k-Means++初始化选项
BigQuery ML 支持无监督学习—您可以应用 k-Means 算法将您的数据分组到聚类中。正如我在之前的博客文章中所描述的,你可以使用聚类来理解你的数据,以便做出数据驱动的决策。在 BigQuery 中,现在有一个更好的初始化算法可用于 k-Means,在这篇博客中,我将解释这个新的初始化算法做什么,以及为什么它是有益的。
BigQuery 中的 k-均值聚类
但首先,让我们从如何在 BigQuery ML 中使用 k-Means 开始。举个例子,让我们使用爱荷华州的公共酒类销售数据集,并根据 2018 年的销售特征对商店进行聚类。首先,我们使用以下方法提取每个商店的数据:
SELECT
store_number
, AVG(SAFE_DIVIDE(state_bottle_retail - state_bottle_cost, state_bottle_cost)) AS profitability
, SUM(bottles_sold) AS bottles_sold
, SUM(sale_dollars) AS sale_dollars
, SUM(volume_sold_liters) AS volume_sold
FROM `bigquery-public-data`.iowa_liquor_sales.sales
WHERE EXTRACT(YEAR from date) = 2018
GROUP BY store_number
这给了我们这样的数据:
Sales characteristics of liquor stores in Iowa
要基于商店对这些数据进行聚类,我们只需创建一个模型,注意从功能列表中排除 store_number:
CREATE OR REPLACE MODEL demos.iowa_store_clusters
OPTIONS(model_type='kmeans', num_clusters=4, standardize_features = true) ASWITH data AS (
SELECT
store_number
, AVG(SAFE_DIVIDE(state_bottle_retail - state_bottle_cost, state_bottle_cost)) AS profitability
, SUM(bottles_sold) AS bottles_sold
, SUM(sale_dollars) AS sale_dollars
, SUM(volume_sold_liters) AS volume_sold
FROM `bigquery-public-data.iowa_liquor_sales.sales`
WHERE EXTRACT(YEAR from date) = 2018
GROUP BY store_number
)SELECT * EXCEPT(store_number) FROM data
在选项中,我指定了所需的聚类数,并告诉算法标准化这些特征。这一点很重要,因为我们的功能范围变化很大(从盈利能力的 0–1 到销售额的 10E6)。默认情况下,BigQuery ML 对 k-Means 输入特性进行了标准化,但是加倍确保没有坏处!!
BigQuery 控制台中的 evaluation 选项卡向我们显示了生成的集群(您的结果可能会有所不同,原因我将在本文后面解释):
The four types of liquor stores in Iowa
集群之间的盈利能力没有变化(也许州法律规定了价格?).很明显,就销售额而言,集群#1 是高销量集群,集群#4 是下一层商店。分类#2 和分类#3 似乎具有相似的销售量,但是分类#3 中的销售包括较小的瓶子(因此,销售了更多的瓶子),这导致了更大的销售额。
该培训耗时约 30 秒,分七次迭代完成:
重复…
只是笑一笑,让我试着再做一次查询。这一次,大约花了一分钟:
结果有所不同,不如以前好:
原因是 K-Means 默认的初始化方法是在随机的起始点播种聚类。你得到的聚类质量取决于起点,在这种情况下,起点不如以前好。
为什么我们需要更好的初始化
具体来说,随机初始化会导致两个问题。如果初始种子恰好很好(见下面的绿框),收敛会很快。但是如果起点碰巧是坏的(见下面的红框),收敛可能需要更长的时间。
Convergence time depends on the starting point
其次,K-Means 很可能会陷入局部最小值,永远找不到好的解决方案(见下文,其中左上的聚类分成两个,右下的两个聚类合并成一个):
Bad initialization can also lead to k-Means being trapped in a local minimum
已经有很多关于如何分配初始起始种子的研究,使得它们以一种导致快速收敛并且不导致陷入局部最小值的方式覆盖输入空间。
k-表示++的意思
BigQuery 现在实现了并行 k-Means++算法。简单来说,算法首先选择一个种子点。然后,为了选择下一个种子点,它对这些点进行随机采样,距离现有种子点越远的点被选择的概率越高。其中 k-Means++简单地选择第一个这样的随机采样点(因此需要 k 遍数据),并行 k-Means++将这种选择并行化,基于加权函数对所选的点进行聚类,并在单次拍摄中完成这一操作。由 k-Means++选择的种子点(以及并行的 k-Means++)可以证明是接近最优的。
The parallel k-Means++ algorithm that you can tell BigQuery ML to use. The algorithm (and screenshot) is from a paper by Bahmani et. al: https://theory.stanford.edu/~sergei/papers/vldb12-kmpar.pdf
虽然初始化需要更长的时间,但收敛通常更快,结果也更好。在爱荷华商店数据上尝试:
CREATE OR REPLACE MODEL demos.iowa_store_clusters
OPTIONS(model_type='kmeans',
num_clusters = 4,
**kmeans_init_method = 'KMEANS++',**
standardize_features = true) ASWITH data AS (
SELECT
store_number
, AVG(SAFE_DIVIDE(state_bottle_retail - state_bottle_cost, state_bottle_cost)) AS profitability
, SUM(bottles_sold) AS bottles_sold
, SUM(sale_dollars) AS sale_dollars
, SUM(volume_sold_liters) AS volume_sold
FROM `bigquery-public-data.iowa_liquor_sales.sales`
WHERE EXTRACT(YEAR from date) = 2018
GROUP BY store_number
)SELECT * EXCEPT(store_number) FROM data
真的更好
我只用了三次迭代就实现了融合:
With k-Means++, convergence is twice as fast.
产生的集群甚至比我们之前的集群更好:
The four clusters now
请注意,在所有考虑的要素上,聚类之间的差异有多大,以及两个异常值存储是如何被划分到一个单独的聚类中的,无论它们是否影响其他聚类的聚类均值。这也体现在戴维斯-波尔丁指数中(现在是 0.6,而以前是 1.1)。
这也是相当可重复的——当我再次尝试时,我得到了类似的(不确切,因为随机种子)结果:
Similar results when I ran it again.
底线:使用k means _ init _ method = ’ k means++ '。尽情享受吧!
甲尚刘 (我母校的博士生!)在谷歌实习时,与吴家勋和邓一起实现了这个功能。实习生在谷歌做出惊人的工作— 申请 !
感谢 Jiaxun Wu 向我指出 BigQuery ML 的这一改进,并提供了两个初始化图,感谢 Amir Hormati 和 Abhishek Kashyap 审阅本文。
SAS 中的 k-均值聚类
什么是聚类?
**“**聚类是将数据集分成由相似数据点组成的组的过程”。聚类是一种无监督的机器学习,当您有未标记的数据时使用。
让我们理解在真实的场景中,
坐在餐馆里的一群食客。让我们假设餐馆里的两张桌子叫做 T1 和 T2。表 T1 中的人可能彼此相关,或者可能是一组家庭成员或同事或任何其他人。
Group of diners
同样,T2 餐桌上的人们可能是彼此相关的,或者可能是一组同事或任何东西。但是,当比较坐在 T1 桌的人和坐在 T2 桌的人时,他们是完全不同的,彼此没有任何联系。
集群也以同样的方式工作。一个群集中的数据点与另一个群集中的数据点完全不同。同一聚类中的所有点要么相同,要么彼此相关。
另一个很好的例子是网飞电影推荐。
Netflix movie recommendation
网飞根据用户的观看历史推荐电影。无论人们看什么;与之相关的类似电影也会上映。聚类算法生成所有这些推荐列表。
聚类可用于分割和许多其他应用。它有不同的技术。K -Means 聚类是最流行、最简单和最有趣的算法之一。
什么是 K 均值聚类?
K-Means 是一种聚类算法,其主要目标是将相似的元素或数据点分组到一个聚类中。K-means 中的“K”代表簇的个数。
K-means 聚类步骤:
距离度量将确定两个元素之间的相似性,并且它将影响聚类的形状。通常,欧几里德距离将用于 K-均值聚类
欧几里得距离是“普通的”直线。它是欧几里得空间中两点之间的距离。
K-Means 算法是如何工作的?
我们来看两个数据点。假设 K =2。然后,它将在数据中的任意位置取两个随机质心,并以此为基础在中间画一条线。一个质心用红色表示,另一个用黄色表示。那么所有数据都指向分类为黄色的黄色质心。所有数据都指向分类为红色的红色质心。这是第一个迭代步骤。
下一步,使用欧几里德方法计算从质心到数据点的距离。并且通过计算所有点的平均值,红色和黄色质心点都移动到新点中。
同样,它在新的质心点之间绘制一条新的线。自动地,所有落向红色质心的点将被识别为红色组,而黄色质心将被识别为黄色组。
同样的步骤将重复新的点,它将计算新的质心。我们可以清楚地看到数据点已经被移动到不同的组中。
它继续下去,直到质心运动变得几乎可以忽略不计。然后,它变成集群 1 和集群 2。这里,输出 Y 标签将给出 0 和 1。0 表示聚类 1,1 表示聚类 2。如果是三个集群,那么它给出 0,1,2。
SAS 中的 K-均值聚类
让我们看一个著名的虹膜数据集。使用 proc 方法检查数据集
/* Checking the contents of the datasets */**proc** **means** data=work.iris N Nmiss mean median max min;**run**;
它有 150 个观察值和 5 个变量。未检测到缺失值或异常值。我们将只使用四个变量,即萼片长度、萼片宽度、花瓣长度和花瓣宽度。“cm”中的数据集。“Target”变量可以删除,因为它是一个类别变量。
关于鸢尾花数据集的小介绍。这是一个多元数据集,由英国统计学家和生物学家 罗纳德·费雪在 1936 年为他的研究论文引入。下图是关于萼片和花瓣的。
在分析数据集之前先了解它会很有意思。
/* Dropping the variable target and stored the dataset in the name of IRIS1 */**data** iris1; set work.iris; drop target;**run**;
在运行聚类分析之前,我们需要将所有的分析变量(实数变量)标准化到平均值为零,标准差为一(转换为 z 分数)。在这里,我们的数据集已经标准化了。
/* Perfoming Cluster Analysis */ods graphics on;**proc** **cluster** data = iris1 method = centroid ccc print=**15** outtree=Tree;var sepal_length--petal_width;**run**;ods graphics off;
METHOD = > 规范决定了过程使用的聚类方法。这里,我们使用的是质心方法。
CCC——立方聚类准则——有助于找出最佳聚类点。
需要找出最佳的集群。
前三个特征值约占总方差的 99.48%,因此,建议采用三个聚类。但是,可以在 ccc 图中交叉检查。
如果我们从集群历史中看到,有 15 个观察值(如我们在代码中给出的= 15)
从上面的 CCC 图可以看出,肘在三点下降了。因此,最佳聚类将是 3。“在 Python 中的 Elbow 方法中可以找到最佳聚类”
为了将 150 个观察值中的每个观察值分成三组,我们可以使用 proc tree。ncl = 3(我们的最佳聚类是 3)。
/* Retaining 3 clusters */**proc** **tree** noprint ncl=**3** out=out;copy sepal_length--petal_width;**run**;
150 次观察分为三组。
使用 proc candisc 和 proc sgplot 创建散点图
/* To create a Scatterplot */**proc** **candisc** out = can;class cluster;var petal_width: sepal_length:;**run**;**proc** **sgplot** data = can;title "Cluster Analysis for IRIS datasets";scatter y = can2 x = can1 / group = cluster;**run**;
我们可以看到,我们的分析清楚地分为三类。聚类 1 是蓝色的,聚类 2 是红色的,聚类 3 是绿色的。
K-means 聚类的优缺点
优势:
1)实际上工作良好,即使一些假设被打破。
2)简单,易于实现。
3)易于解释聚类结果。
4)在计算成本方面快速有效。
劣势:
1)均匀效应通常产生具有相对均匀大小的聚类,即使输入数据具有不同的聚类大小。
2)不同的密度对于集群可能效果不佳。
3)对异常值敏感。
- K 值需要在 K-means 聚类之前知道。
我的 GIT 里有完整的 SAS 代码【https://github.com/sdhilip200/IRIS-datasets
如果您发现任何错误或需要改进的地方,请不吝赐教。
k-均值聚类:推荐系统的无监督学习
Your brain on Unsupervised Learning. Source: Pixabay.
在一般人工智能的意义上,无监督学习被称为最接近“实际”人工智能的东西,K-Means 聚类是其最简单但最强大的应用之一。
我在这里不是要讨论这些说法是真是假,因为我既不是专家也不是哲学家。然而,我会说,我经常惊讶于无监督学习技术,即使是最基本的,在数据中捕捉模式的能力有多强,而我本以为只有人才能发现这些模式。
今天我们将在我自己收集的数据集上应用无监督学习。这是一个专业魔术的数据库:我从mtgtop8.com 爬上来的聚会平台,如果你喜欢魔术,这是一个很棒的网站:聚会。
我从几年的比赛中收集了MTG top 8 数据,它们都可以在这个 GitHub 库中使用。
如果你不喜欢这个游戏,或者甚至你从来没有玩过它,不要担心:它不会太碍事,因为我将解释 K-means 聚类的理论方面,并向你展示如何使用 Dask 来应用它。如果你喜欢这个游戏,那么你会喜欢这些例子的。
k 均值聚类
我们今天要研究的算法叫做“K 均值聚类”。如果我们事先不知道如何分离数据,它提供了一种表征和分类数据的方法。
为什么我们需要无监督学习?
我说的无监督学习是什么意思?假设你有一组猫和狗的照片。你可以训练一个监督机器学习模型来将图片分类。
然而,想象一下,你有一个庞大而复杂的数据集,里面有你不太了解的东西。例如,你可能有关于不同行星产生的光谱的数据,并且正在寻找一种方法将它们分类。
再举一个例子,您可能有来自许多不同生物的大量遗传数据,并希望以直观的方式定义哪些属于同一属或科。
或者,在我们的情况下,我们可能有 777 种不同的魔法:收集牌,使用 600 多种不同的卡片(是的,专业元不是那么多样化),并希望训练一个机器学习模型,以便它了解哪些卡片可以很好地配合,哪些不能。
现在想象你必须做这个任务,你不知道如何玩这个游戏。如果有人发明了一种算法,将看起来相似的数据聚集在一起,而无需您提供“相似”的定义,这不是很好吗?这就是聚类,尤其是 k-means 聚类的意义所在。
现在完成了,我希望你有动力,因为是时候用一些理论弄脏我们的手了。
K-Means 聚类是如何工作的?
K-Means 聚类接收一个单一的超参数: k,,它指定了我们想要将我们的数据分成多少个聚类。
集群不一定有相同数量的实例。然而,它们应该各自表征我们数据的一个特定子集。我们将如何实现这一目标?让我们来了解一下!
首先,这个算法的输入需要是一组向量。也就是说,你的所有特征都应该是数字的,并且顺序相同。如果您有任何分类特征,我的建议是使用 one-hot encode:将每个分类变量转换成一个 n 元素的向量:每个可能的类别一个,除了给定类别的一个,所有的都设置为 0。
该算法将启动 k 个随机“质心”,即由数据集元素的维度定义的空间中的点,然后它将:
- 将每个元素指定给最靠近它的质心。
- 将质心重新映射到位于分配给它的所有元素的平均值上的点。
- 重复步骤 1 和 2,直到满足收敛(或停止条件,如对给定的 N 进行 N 次迭代)。
最后,每个元素将被分配给 k 个簇中的一个,使得同一簇中的所有元素都离它最近。
K-均值聚类的应用
像许多其他非监督学习算法一样,K-means 聚类如果用作一种为监督机器学习算法(例如,分类器)生成输入的方式,可以创造奇迹。
输入可以是给定实例属于哪个聚类的一次性编码,或者到每个聚类质心的 k 个距离。
然而,对于这个项目,我们将开发的是一个(有点初级的)推荐系统,给定一个实例,它将返回出现在同一个集群中的元素。
在 Python 中使用 Dask 的 K-means 聚类
定义了这个项目的概念后,现在让我们开始实践部分。代码可以在 Jupyter 笔记本的这个库上找到。
处理数据
我按照以下格式存储 MtgTop8 资料:
N card name
M another card name
777 年不同*。txt* 文件,其中每行指一张牌,第一个空格前的数字是该副牌中该牌的幻影数。
为了将它们转换成更易于管理的格式——我将为每副牌使用一个元组列表(Int,String),每个元组一张牌——我们将这样做:
这是现在一副牌的样子。
[(4, 'Ancient Ziggurat'), (4, 'Cavern of Souls'), (4, 'Horizon Canopy'), (1, 'Plains'), (2, 'Seachrome Coast'), (4, 'Unclaimed Territory'), (4, 'Champion of the Parish'), (1, 'Dark Confidant') ...]
其中每个元组代表一张牌(没错,那些都是真实的牌名),以及出现的次数。
因为我们希望将每一副牌映射到一个向量,所以直观地说
- 将它们转换成一个列表,整个数据集中每个不同的卡片都有一个元素。
- 将每个组件设置为相应牌的幻影数(所有组件对应于未出现在该副牌中的牌设置为 0)。
要做到这一点,让我们得到所有卡片组中出现的所有不同的卡片。
现在,让我们利用新发现的关于卡片名称的知识,把所有的卡片都变成美丽的、可消费的载体。
现在我们所有的牌都可以很容易地输入 Dask 的 K-Means 聚类算法,我们可以玩输出。
我们可以只使用“二进制”向量,如果卡片出现在卡片组中,则将分量设置为 1,如果没有出现,则设置为 0。我们以后也可以尝试一下,看看我们是否也能得到好的结果。
应用 K-均值聚类
既然我们的数据都被整齐地映射到向量空间,实际上使用 Dask 的 K-means 聚类是非常简单的。
其中最重要的部分是 n_clusters 参数,我把它任意设置为 8。
在现实生活中,你可能想尝试不同的价值观。对于这个特殊的情况,我知道 MtG 有 5 种不同的“颜色”的卡片。为了防止算法只根据颜色对卡片进行聚类(反正它根本没有这样做),我选择了一个大于 5 的数字。
该算法将标签作为 Dask 数组返回。我以后可能会写一篇关于如何使用它们的文章,但是现在我不想处理所有这些。此外,MtgTop8 数据集足够小,这并不重要,所以我决定将其转换回整数列表。告我吧。
探索性分析:让我们看看我们得到了什么
起初我想检查结果是否有意义。这是我第一次在这个数据集上使用 K-means 聚类,我想确保它学到了一些有价值的东西。所以我只是检查了每组牌中哪些牌最常用。至少对我来说,结果是令人震惊的。以下是我所做的检查。
如果您对结果感兴趣,我强烈建议您从 GitHub 项目下载笔记本并使用它,它真的很有趣!我只是不想将我的 M:tG 发现与本教程混在一起,这样那些对数据科学感兴趣但对游戏不感兴趣的读者就不会感到无聊。
使用 K-均值聚类的卡片推荐
现在我们已经完成了健全性检查,我们可以继续对我们生成的所有标签进行实际应用了。
我们可以有许多方法来解决推荐问题:给定一张牌,推荐与之相配的其他牌,除了这些牌出现在哪副牌中之外,不使用任何关于这些牌的数据(也就是说,不要作弊,不要询问更多关于这些牌的数据,如颜色、价格或专家的意见)。
请思考一下,您将如何使用聚类数据来生成建议?我相信你能想出一些主意。
如果你想出的不是我要做的,请在评论里告诉我!如果是团队合作,创意会更有趣,我真的很想看看我亲爱的读者们能想出什么。
最后,我是这样做的:
如你所见,对于这部分,我省略了一张牌在给定的牌组中出现的次数,只看了一张牌在给定的牌组中出现的相对次数。
然后,我返回具有最相似的相对幻影(由欧几里德距离定义)的牌。
如果你是一个魔术:收集玩家,尝试一下这段代码,看看结果,它会给出很好的(虽然有点保守)建议!
结论
K-Means 聚类允许我们在不真正了解一个领域的情况下接近它,并得出结论,甚至围绕它设计有用的应用程序。
它让我们通过学习数据中的潜在模式来做到这一点,只要求我们以正确的格式给它数据。
我鼓励您使用这里的代码,尝试使用不同的数据集创建自己的推荐系统,或者解决一些其他问题。如果有,请给我看看你的结果!我想看看你能想出什么。
将来,我想用非专业的套牌做同样的分析。这样,我可以为休闲玩家(比如我)制作一个推荐引擎。我认为如果它能与几乎任何卡一起工作,而不仅仅是 642,那将会很酷。
你可以在我的 个人网站 中看到我正在做的事情以及我最近的文章和笔记。
快乐编码。
原载于 2019 年 4 月 3 日www . data stuff . tech。