Microsoft 和 Anaconda 新的 **Excel 中的 Python** 集成让您能够访问用于数据科学和机器学习的整个 Python 生态系统。由于直接连接到 Anaconda Distribution,我们可以直接在 Excel 工作簿中利用 NumPy、pandas、Seaborn 和 scikit-learn 等软件包的内置功能。这篇文章将解释一个简单的用例,用于在 Excel 中创建您的第一个机器学习实验。我们将展示机器学习实验中执行的一些最常见步骤(例如,数据分区、特征分析),并将常见的 Python 任务转换为 Excel 工作簿。
注意:要重现这篇文章中的示例,请 安装 Excel 中的 Python 试用版。
入门:数据集
使用 Excel 中的 Python 创建您的第一个机器学习实验非常容易!您只需要安装了新的 **Excel 中的 Python** 集成的 Excel。您 **不需要** 在您的计算机上安装 Python,也 **不需要** 设置包含特定软件包的特殊环境。嵌入在 Excel 单元格中的所有 Python 代码将自动提交并在 Microsoft Azure 云上托管的沙盒环境中运行。该环境由 **Anaconda** 提供,让您立即访问最流行的数据科学和机器学习 Python 堆栈。
让我们从打开一个名为 My first Machine Learning Experiment.xlsx 的新的空白 Excel 工作簿开始。
为了熟悉新的 Excel 中的 Python 集成,我们将首先编写一些简单的 Python 代码来显示有关 Python 环境的信息。
显示 Python 环境信息
在左上角单元格 (A1) 中,让我们创建一个标题,用于显示单元格 A2 中的内容。例如,“**Python 环境信息**”。
现在让我们转到另一个单元格(例如,B1)并键入“=PY”以创建第一个 **Python 单元格**。或者,您可以使用 Ctrl+Shift+Alt+P 键盘快捷键。现在让我们编写以下 Python 代码
import joblib
import sklearn
import numpy as np
import pandas as pd
import sys
env_info_details= f"""
Python: {sys.version[:6]} # we will just retain version number info
numpy: {np.__version__}
pandas: {pd.__version__}
scikit-learn: {sklearn.__version__}
Available CPUs: {joblib.cpu_count()}
"""
env_info_details
在代码中,我们正在收集有关我们正在运行的 Python 版本以及环境中可用的 NumPy、pandas 和 scikit-learn 软件包的版本以及可用内核总数的信息。为简单起见,我们将此信息存储在 env_info_details 变量中,该变量被定义为一个多行 f-字符串变量,以加快格式化速度。
如果我们通过按 Ctrl+Enter 提交代码,我们将触发代码执行。应该会生成以下输出
Python 3.9.10
numpy: 1.23.5
pandas: 1.5.3
scikit-learn: 1.2.1
Available CPUs: 1
💡 注意 1:如果 Python 输出没有在多行上以格式化方式显示,这是因为 Excel 单元格格式规则没有设置为允许文本“换行”。这是因为单元格格式和 Python 生成输出是 Excel 中的两个独立概念。换句话说,Excel 单元格格式属性始终会覆盖任何 Python 格式。
💡注意 2:您可能已经注意到,我们没有使用 Python print 函数来生成单元格的输出,而是返回了 env_info_details 字符串变量。这是因为在 Excel 中使用 Python print 函数仅限于诊断信息(可通过公式 > Python > 诊断访问)。相反,如果我们返回一个字符串(即 str 对象)作为单元格的结果,该对象将被转换为 Excel 输出并显示。而这正是我们使用第一个 Python 代码段所做的事情。
从我们的第一个示例中,我们可以看到我们的环境正在运行 Python 3.9 和 scikit-learn==1.2.1(有关此版本的更多信息,请参阅相应的 发行说明)。
加载机器学习数据集
现在让我们专注于将在整个实验中使用的数据集。我们将使用一个经典的数据集,即 鸢尾花数据集。这可能是机器学习文献中最著名的数据库之一,它被广泛用作机器学习实验的参考示例。因此,该数据集已自动集成到许多机器学习库和工具中。scikit-learn 在其数据集包中提供了对该 数据集 的访问权限:sklearn.datasets.load_iris。
如果您不熟悉该数据集:我们将使用 150 个鸢尾花样本的集合,每个样本都以一组四个不同的特征为特征,即萼片长度、萼片宽度、花瓣长度和花瓣宽度。每个鸢尾花样本都属于一个物种:山鸢尾、变色鸢尾或维吉尼亚鸢尾。机器学习任务是自动对所有鸢尾花样本进行分类。
与我们对 Python 环境所做的类似,现在让我们收集有关 scikit-learn 中可用的数据集的信息。让我们在新建的 **Python 单元格** 中编写以下代码。
在我的示例中,我将写在单元格 D1 中,但请随时根据需要组织您的电子表格内容。
from sklearn.datasets import load_iris
iris = load_iris(as_frame=True)
X = iris.data
y = iris.target
ds_info_details = f"""
{X.shape[0]} samples
{X.shape[1]} features
{y.values.ndim} target
"""
ds_info_details
您应该会看到以下输出
150 samples
4 features
1 target
很好!现在让我们直接在 Excel 中查看这些数据!
在我们之前的代码段中,我们创建了 Python 对象,它们持有对 特征 和 目标 的引用,即 X 和 y 变量,它们都是 pandas.DataFrame 对象。然后,我们可以在新的工作表中引用相同的变量,并生成我们的数据分区。
**Excel 中的 Python** 集成具有 DataFrame 对象的内置功能,这些功能可以轻松地显示在多个单元格中(在 Excel 术语中称为“溢出”)。
实际上,如果我们转到一个空单元格(例如,A3)并创建一个新的 Python 公式(即 =PY),该公式只包含对 X 变量的引用,然后按 Ctrl+Enter 运行,整个数据集将显示出来
类似地,我们可以通过键入以下 Python 公式将相应的目标显示在特征旁边(例如,在 E3 单元格中,以避免重叠)
y.to_frame()
您可以在下图中看到最终的输出。
太棒了!🎉
现在,我们将数据集直接通过 Python 集成到我们的 Excel 工作簿中!这是将 Python 代码 **和** 数据集成到 Excel 中的一大优势:我们可以将代码 **和** 数据集成到 Excel 中。
值得强调的是,这篇文章中探讨的所有内容都可以类似地应用于 Excel 中已有的任何数据集。
在继续下一节之前,让我们首先将当前工作表重命名为更有意义的名称,例如,数据集。在 Excel 工作簿中工作时,我们可以将实验更好地组织到多个电子表格中,每个电子表格专门用于实验中的一个步骤。
步骤 1:数据分区
现在机器学习实验真正开始了。首先,您将从 **数据分区** 开始。我们将从原始数据集中创建两个不同的数据分区,用于训练和测试我们的机器学习模型。
因此,让我们在工作簿中创建一个名为步骤 1 - 数据分区的新的电子表格。
为了创建我们的 训练 和 测试 数据分区,我们可以使用 scikit-learn 中包含的 train_test_split 实用程序函数,与我们在 Jupyter 笔记本中运行代码时所做的类似。类似于笔记本,底层执行模型假设每个单元格之间共享一个全局命名空间。特别是在 Excel 工作簿中,这假定执行顺序从第一个工作表的左上角单元格开始,并以 行优先 方式进行。这意味着在单元格中定义的任何变量、函数或 Python 对象也可以从执行顺序中的所有后续单元格中访问和使用。
在上一节中,我们创建了对 特征 和 目标 数据的引用,它们由 X 和 y 变量作为 pandas.DataFrames 表示。然后,我们可以在新的工作表中引用相同的变量,并生成我们的数据分区。
让我们创建一个新的 Python 单元格(例如,在 A2 中),我们将在其中添加以下代码
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y,
random_state=12345,
stratify=y)
X_train
现在,我们的命名空间包含四个新变量:X_train、y_train、X_test 和 y_test,分别保存着训练和测试的特征和目标的引用。当前单元格只返回将被泄露到相邻单元格的 X_train DataFrame。现在,我们可以像上一节中那样,以类似的方式填充其他数据,以可视化整个数据集,如下所示
y_train.to_frame() # e.g., in cell E2
X_test # e.g., in cell G2
y_test.to_frame() # e.g., in cell K2
由于固定随机种子(即,random_state=12345)和用于 test_size=0.25 的默认值,您应该获得完全相同的结果,在训练和测试分区中分别总共 112 个和 38 个样本。
步骤 2:特征分析
现在,让我们通过可视化训练和测试分区中特征的成对分布来探索我们的数据。
让我们从创建一个新电子表格开始,使用与上一节相同的约定命名:步骤 2 - 特征分析。这样,我们将保持工作簿井井有条,每个步骤都有一个单独的电子表格来进行我们的实验。
为了快速生成和可视化特征的成对分布,我们可以使用 seaborn.pairplot 函数。我们已经将数据存储在 DataFrame 的形式中,因此我们只需要将特征和相应的目标组合在一起,因为 pairplot 函数期望一个单独的 DataFrame 对象。此外,我们可能需要重复相同的操作来可视化训练和测试数据的特征分布。因此,编写一个可以多次调用不同数据的函数是明智之举。
现在,让我们在一个新的 Python 单元格(例如,在 A1 中)中创建一个新的 Python 单元格,其中包含以下代码
import seaborn as sns
from matplotlib import pyplot as plt
def feature_plot(X, y, title):
as_df = X.join(y) # join features, and targets
pplot = sns.pairplot(as_df, hue="target", markers=["o", "s", "D"],
diag_kind="hist", palette="tab10")
pplot.fig.suptitle(title, y=1.04)
return pplot
# merely return to have a label as cell output
"feature_plot function definition"
您可能已经注意到,在 feature_plot 函数定义之后,我们正在定义一个 Python 字符串,即“feature_plot 函数定义”。这是一个有用的技巧,用于标记不产生任何直接输出的 Python 单元格的内容。此单元格只是定义了稍后将在其他公式中重用的 Python 函数。
现在,让我们在一个新的 Python 单元格(例如,在 B1 中)中调用新的 feature_plot 函数,用于训练数据
feature_plot(X_train, y_train, title="Training Set - Feature Plot")
默认情况下,图像将自动嵌入到当前单元格中。此时,您有两个选择:
- 您可以将图像保留在当前单元格中,这意味着您需要增加其宽度和高度才能正确地可视化它;
- 或者,您可以从当前单元格中分离图像并将其拖动到工作表周围,就像您通常对使用 Excel 生成的标准图像所做的那样。
⚠️ 注意:如果您从当前单元格中分离图像,用于生成它的所有 Python 代码都将丢失,因为该对象不再存在于 Python 单元格中了。在撰写本文时,此行为似乎仅限于具有图像作为输出的单元格。
出于这个原因,选项 1 是推荐的,并将贯穿本文始终。
在我们的案例中,这不会是什么大问题,因为我们唯一编写的 Python 代码是函数调用。因此,这里的一般教训是:当您的 Python 单元格预期根据其输出生成图像时,最好将单元格中的代码限制为仅仅用于生成图形的函数调用,该函数已在其他地方定义!
这是您的工作簿中最终特征图的样子。这些图特别有信息量,因为它们允许我们定性地评估每一对特征在两个分区中分离三个类别时的信息量。事实上,一些特征似乎特别有效地区分了各种鸢尾花物种(例如,萼片长度与花瓣宽度,训练集数据的右上角),而其他对则不太有用(例如,萼片宽度与萼片长度)。在这种情况下,一种可能性是尝试使用 降维方法在低维空间(例如,在 2D 中)工作。
主成分分析 (PCA)
降维最流行的方法之一是 主成分分析 (PCA),其目标是找到连续的正交分量(即,维度)来解释最大量的方差。让我们尝试使用我们的鸢尾花数据在 Excel 中使用 PCA。
这次,我们还将尝试一些新东西:让我们在一个新的 Python 单元格(例如,E1 中)中编写我们的代码,并将它的输出设置为 Python 对象(而不是默认的“Excel 值”)。我们将在稍后讨论此选择的含义。现在,让我们关注要包含的代码片段
from sklearn.decomposition import PCA
pca = PCA(n_components=2)
pca.fit(X_train)
pca
代码本身非常简单:我们首先创建一个新的 PCA 模型,将模型拟合到训练数据,然后将(训练好的)PCA 模型实例作为单元格输出返回。通过这样做,我们可以随时通过简单地引用 Excel 单元格来引用模型实例。(这在后面的步骤中将很有用,当我们想直接访问 PCA 模型以缩放数据时)。
现在,让我们在一个新的 Python 单元格中创建一些实用函数来缩放数据并生成图
def scale_data(X, y):
"""Utility function to scale data, and join them into a unique data frame"""
X_scaled = pca.transform(X) # X_scaled is a numpy array
X_scaled_df = pd.DataFrame(X_scaled, columns=["x1", "x2"])
X_scaled_df["target"] = y.values
return X_scaled_df
def plot_pca_components(X, y, title):
"""Utility function to visualize PCA components"""
X_scaled_df = scale_data(X, y)
pca_plot = sns.relplot(data=X_scaled_df, x="x1", y="x2",
hue="target", palette="tab10")
pca_plot.fig.suptitle(title, y=1.04)
return pca_plot
"plot_pca_components and scale_data function definitions"
第一个函数只是缩放数据并将其作为 pandas.DataFrame 返回,以更好地与 Seaborn 集成,将特征和目标堆叠在一起。生成的 DataFrame 将在 plot_pca_components 函数中用于生成传递数据的 relplot。
我们将对 (X_train, y_train) 和 (X_test, y_test) 对调用后一个函数,分别可视化训练和测试数据集的 PCA 分量(在 2D 中)。
完整的电子表格应该与下图所示类似。正如预期的那样,在低维数据上工作可能有助于分类模型。
步骤 3:探索性聚类
缩放数据后,PCA 有助于更好地理解数据。让我们看看聚类算法(例如,k 均值)如何将我们(缩放后的)数据进行分区,以及这些分区如何映射到实际的预期类别(即,鸢尾花物种)。
让我们创建一个新的电子表格,名为步骤 3 - 探索性聚类。
首先,我们需要生成一个新的 k 均值实例,该实例将在使用 PCA 算法预先缩放的数据上进行训练。为了避免重复代码和浪费计算,我们可以通过直接引用具有“Python 对象”输出的 Python 单元格,直接访问上一张电子表格中训练好的 PCA 模型。为此,我们将使用特殊的 xl() Python 函数。
让我们创建一个新的 Python 单元格,并将它的输出设置为Python 对象
from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters=3, n_init="auto")
pca_model = xl("'Step 2 - Feature Analysis'!E1") # reference the trained pca model
X_train_scaled = pca_model.transform(X_train)
kmeans.fit(X_train_scaled)
kmeans
使用与 PCA 模型相同的“技巧”,我们将返回训练好的 k 均值聚类模型实例,以便稍后直接访问。
现在,让我们在一个新的 Python 单元格中定义我们的函数,以可视化聚类分区
def visualize_kmeans_clustering(X, y, title):
cluster = xl("A1")
X_scaled = scale_data(X, y)
features = X_scaled[["x1", "x2"]]
y_cluster = cluster.predict(features.values)
X_scaled["cluster"] = y_cluster
cluster_plot = sns.relplot(data=X_scaled, x="x1", y="x2",
hue="target", style="cluster", palette="tab10")
cluster_plot.fig.suptitle(title, y=1.04)
return cluster_plot
"visualize_kmeans_clustering function definition" # as cell output
值得注意的是,我们正在引用集群实例,通过 xl() 选择器函数(第 2 行:cluster = xl(“A1”))选择上一个单元格。此外,我们正在重用上一节中定义的实用程序 scale_data 函数,使用 PCA 缩放数据并将结果作为数据帧获取,准备与 Seaborn 一起使用。
为了最终可视化我们的聚类结果,我们将再次依赖于 seaborn.relplot 函数,但这次使用了一个额外的技巧。每个元素(点)的颜色将由实际的预期类别决定(即,hue=”target”),而标记将根据集群标签分配(即,style=”cluster”)。这样,我们将能够定性地评估集群标签和预期类别之间存在多少同质性。
为了验证这一点,让我们在两个新的 Python 单元格中调用 visualize_kmeans_clustering 函数,在显示图像作为单元格内容时使用上述“捕捉”。在下图中,聚类执行得相当成功,在类别 1 和 2 中的一些样本周围有一些混淆——即“维吉尼亚”和“维多利亚”。
步骤 4:鸢尾花分类
我们终于到达了我们简单的机器学习实验的最后一步,在这个步骤中,我们将训练一个分类模型并生成一个分类报告。
让我们从创建一个新的电子表格开始,名为步骤 4 - 鸢尾花分类,来处理我们实验的最后代码段。
此时,我们已经拥有了训练分类模型所需的一切
- 我们有训练和测试分区,即 (X_train,y_train) 和 (X_test, y_test);
- 我们有权访问经过训练的降维模型,即 PCA;
- 我们有权访问可以用于进一步检查数据的实用程序函数。
为了生成信息丰富的分类报告,我们应该包括分类指标的值(在这种情况下,accuracy_score 就足够了),以及相应的 混淆矩阵。
让我们创建一个新的 Python 单元格,其中包含以下代码
from sklearn.metrics import ConfusionMatrixDisplay
from sklearn.linear_model import LogisticRegression
classifier = LogisticRegression(C=1e5).fit(X_train, y_train)
class_names = iris.target_names
disp = ConfusionMatrixDisplay.from_estimator(
classifier,
X_test,
y_test,
display_labels=class_names,
cmap=plt.cm.Blues,
)
disp.ax_.set_title("Confusion Matrix (All features)")
disp
分类模型是 LogisticRegression,考虑到手头的数据,该模型应该能够很好地工作。为了显示我们的混淆矩阵,我们使用 scikit-learn 中的 ConfusionMatrixDisplay 实用程序类,该类能够在给定训练好的分类器的情况下生成矩阵。
训练好分类器后,在其他单元格中打印分数结果就像在模型实例上调用 score 方法一样简单,无论是对于训练数据还是测试数据:
f"Accuracy Score on Training Set (all features): {classifier.score(X_train, y_train):.2f}"
f"Accuracy Score on Test Set (all features): {classifier.score(X_test, y_test):.2f}"
作为练习,您可以尝试将 X_train 数据替换为使用 PCA 的 2D 缩放版本,看看这会如何改变性能。
结论
在这篇博文中,我们探讨了 Excel 中新的Python 集成如何使您能够使用 Python 在 Excel 工作簿中构建完整的机器学习实验。我们处理了机器学习实验的多个步骤(从数据分区到最终的分类报告),利用与Anaconda Distribution 的内置集成,该集成提供了对用于数据科学和机器学习的流行工具和库的直接访问——例如 pandas、scikit-learn 和 Seaborn。
本文中创建的工作簿的最终版本可 在此处获得。免责声明:截至本文发表时,Microsoft Excel 中的 Python 集成处于测试版阶段。功能和函数可能会发生变化。 如果您在这页上发现错误,请随时联系我们。
作者简介
Valerio Maggio 是 Anaconda 的研究员和数据科学家倡导者。他还是一名开源贡献者,也是 Python 社区的积极成员。在过去的 12 年中,他为许多国际会议和社区聚会做出了贡献并自愿参加,例如 PyCon 意大利、PyData、EuroPython 和 EuroSciPy。