为了充分利用 Python 在 JMP 中的强大功能,我们面临着如何将 Python 的灵活性与 JMP 直观且交互式的用户体验相结合的挑战。在 JMP 18 之前,我们通过一种变通方法来实现这一点——在服务器上运行 Python 来绕过 JMP 繁琐的 Python 集成。然而,JMP 18 的发布重新引入了 Python 集成,简化了这一过程。
基于我们最初让 JMP 用户无需编程专业知识即可利用 Python 的理念,我们开发了 JMPyFacade (JMPy)。该工具提供了一个与 JMP 类似的熟悉界面,用户可以通过动态生成的用户界面执行预定义的 Python 服务,同时抽象化底层 Python 和 JSL 代码。
本次演讲将探讨 JMPyFacade 的技术架构,并演示它如何有效地弥合 JMP 和 Python 之间的鸿沟。与会者将学习如何在 JMP 中利用 Python 进行高效且引人入胜的数据分析。
大家好,欢迎观看我的海报展示,主题是“JMP与Python的无缝衔接,打造引人入胜的分析体验”。我叫Jarmo Hirvonen,在芬兰的Murata公司工作。在这张海报中,我将解释为什么要在JMP中使用Python,或者说为什么要将Python集成到JMP中。关于集成,需要注意一些事项,以及我和我的同事Eero在芬兰Murata公司开发的一个利用此集成的应用程序。首先,让我们来探讨一下为什么要在JMP中使用这项功能。
JMP是一款可视化程度高、交互性强且分析能力出色的工具。另一方面,Python基本上是许多数据相关任务的事实标准编程语言。它拥有许多非常成熟的库,而且贵公司可能已经拥有自己的Python开发能力。
我从两个角度来看这个问题。首先,我们的一些首批用户将能够使用JMP本身不具备的功能,例如一些机器学习模型(比如Torch),其次,他们还可以访问JMP原本无法使用的文件类型。
例如,Parquet 文件就是一个例子,你可以用 Python 打开它们,然后通过集成导入到 JMP 中。这样,Python 用户就可以访问 JMP 的可视化和交互式工具,可以直接在 JMP 中使用,也可以通过 Python 端以某种集成方式使用。当然,JMP 还提供了一些独有的分析功能。关于 JMP 和 Python 的集成,需要注意的是,Python 是随 JMP 18 一起安装的。
每个 JMP 实例首次加载时速度会比较慢。也就是说,场地首次加载到 JMP 实例中需要一些时间,但下次加载时,如果您不完全关闭 JMP,速度就会快很多。如果您只是进行一些非常小的操作,则可能需要考虑这一点。尝试仅使用 JSL 编写代码可能更值得,因为它速度更快。
数据包管理和安装有时会引发一些问题,虽然有相关的文档,但解决起来可能有点麻烦。您只有一个环境,所以如果您习惯使用虚拟环境,目前无法在作业集成中实现。您需要对 JSL 和 Python 数据类型转换有一定的了解,相关文档可以在某个网页上找到。作用域可能会让人困惑,或者说有点让人摸不着头脑。Python 基本上是全局作用域,根据您命名变量的方式,它们可能会在不同的脚本之间相互干扰。
最后,我认为,Python 调试和开发最大的问题之一在于它可能会让人感到有些恼火,而且很难进入工作状态。这主要是因为你无法像在 JMP 中那样重置 Python 或重启内核,最终陷入一种“开发循环”。比如,你用 Python 开发,然后想要测试,这时你又怀疑某些变量需要清理,例如。
目前唯一的方法是关闭 JMP 实例,重新运行 JMP,然后重新加载所有内容,之后才能测试代码。这不是一个循环,它基本上在这里就中断了,你必须从头开始重新执行整个流程。这会打断流程,令人沮丧。你可以通过编写 Python 代码的方式来稍微缓解这个问题。
接下来谈谈我们的应用,那么 JMPyFacade 是什么呢?首先,它的名字来源于它将复杂的 JMP 和 Python 代码封装在一个与 JMP 非常相似、非常熟悉的用户界面之后。它添加了版本控制功能,使 JMP 用户能够访问预先设定的 Python 功能。我们称这些功能为“服务”。这些服务涵盖了从非常简单的数据集创建到更复杂的学习模型等各种功能。[听不清 00:04:34]
我们希望让 JMP 用户能够在几乎不知情的情况下使用 Python 功能。之前我们也做过类似的事情,但当时我们是通过服务器绕过 JMP 的 Python 集成,因为之前的集成使用起来比较复杂。现在有了 JMP 18,我们可以使用原生集成,而且效果非常好。
当用户运行应用程序时,流程如下:首先运行插件,然后检查数据是否已更新。如果数据未更新,则进行更新,用户需要重新运行插件。如果仍然找不到更新,则会在 JMP 中初始化 LS Python。此步骤的主要目的是更新订单。如果用户没有运行此步骤,则运行类似这样的应用程序可能会导致一些问题(例如,如果订单不存在)。
完成这些初始化后,我们会检查数据包管理系统,看看是否有需要更新的数据包。如果需要更新,我们会进行更新;如果没有需要更新的数据包,则继续执行后续步骤。我们会检查用户是否打开了表格。如果没有打开表格,我们会关闭插件并通知用户,请先打开表格再运行此程序。目前这样做是因为我们基本上只支持单个静态表格。
然后,当用户打开一个表格并想要进行分析时,我们需要导入相应的包。如果出现问题,程序会停止运行并显示日志,说明哪里出了问题。如果导入成功,我们会初始化用户界面,创建用户界面,用户就可以开始使用该工具了。如果用户界面已经存在于 JMP 实例中,我们会直接将其显示在前台,而无需进行任何初始化操作。
简单介绍一下它的工作原理:我们在后台使用了数据类型、JMP 类,然后在 Python 端使用了 Pydantic 包来创建我们使用的模型,并进行类型验证和数据验证。
这里我们以 HDBSCAN 为例,例如这里的 features 参数,它是一个字符串列表,字段长度至少为 1,并使用 JSON Schema,其中包含数值列。当 JMP 接收到此参数时,它会创建相应的类,因此您会看到一个按钮、一个列列表框,用户必须输入一个数值(至少需要一个数值列才能正常工作),并且针对不同类型的数据(例如整数、数字框、布尔值复选框等)使用不同的元素。
当用户准备运行服务时,他们填写相应的列,点击“运行服务”按钮。此时,JMP 代码会创建一个数据子集,其中包含这些列,并提取未被排除的列。然后,当调用 Python 函数时,会使用这些未被排除的列。这样做可以简化 Python 端的管理,因此我们采用了这种方式。
Python 会运行其算法,并将值更新到子集中。当子集和 Python 返回一些值后,JMP 就知道“好了,现在可以更新原始表了”。它会更新原始表,关闭子集,然后为原始表创建一些表脚本和列属性。基本上,每次用户运行服务时,如果需要创建列,它都会向表中创建新列。
接下来是一些使用示例,这是一个基本示例。用户运行该插件,它会检查版本控制系统。在本例中,用户希望通过该插件运行 tSNE,因此他们从左侧选择 tSNE,输入列,并查阅文档。这是 tSNE 的官方文档,例如,如果他们想了解它的工作原理、功能和参数。当用户准备好运行服务时,他们单击“运行服务”按钮,新列将添加到 JMP 表中,现在他们只需像使用普通的 JMP 按钮一样操作这些新列即可。
然后我们还会查看报告脚本,在本例中它只包含输入参数。这里有一些更复杂、更繁琐或更全面的示例。本次演示采用的是交互模式。在我看来,这是我们这里最好的功能之一。这些功能不会总是创建新列,而是更新静态列,并且当用户在用户界面中更改任何值时,它们会立即重新运行其算法(Python 算法)。例如,您可以使用此功能导出数据分析或微调算法。
在这里,用户只需点击键盘上的向上箭头,Python 算法就会不断重新运行,聚类结果也会根据用户更新的值而改变。这里视图越多,组件就越会变化,因此根据你输入的值,你会得到完全不同的聚类结果。你可以在这里交互式地修改值,找出在这种情况下最佳的值,然后回到 Python 中使用这些值。
然后我们有一个特征重要性服务,它利用多种算法,并使用 Shapley 值来确定哪些特征对于建模或预测最为重要。我们运行模型,得到 Shapley 值(听不清 00:10:32),以及我们所选算法的排名。在本例中,我们选择了 RGBM、XGBoost 和 AdaBoost。用户可以从这里复制粘贴这些值,然后在 JMP 中使用这些列开始建模。
最后,我们来谈谈这个工具的未来发展方向:增加对动态表格的支持(目前我们只有一个静态表格)、更多服务、图像分析以及我们自定义的机器学习模型。改进交互性,使 Python 可以直接创建或更新图形脚本。支持导出和导入 Python 模型。利用 JMP 强大的 DOE 功能进行参数微调。创建管道,以便按顺序运行多个服务。改进我们现有的动态功能,并根据 JMP19 的更新内容进行一些可能的重构,从而进一步完善该工具。此外,我们还可以讨论开源该工具,让更多人参与到工具的开发中来。谢谢。