Python 机器学习在 Azure 上(第三部分):使用 Python 和 Azure ML Studio 创建 TensorFlow 模型





5.00/5 (2投票s)
如何在 Azure 机器学习工作区中使用 TensorFlow 模型进行训练。
在本系列文章中,我们将探讨在 Azure 上使用 Python 创建和使用机器学习模型的几种方法。在第一篇文章中,我们使用带 ML 扩展的 Visual Studio Code 在 Azure 上训练了 XGBoost 模型。然后,我们使用GitHub Codespaces和GitHub Actions在每次将更改推送到存储库后自动训练 PyTorch 模型。
在大多数实际的机器学习项目中,最终模型的实际训练需要漫长的实验阶段。此阶段高度交互,因此仅使用常规 Python 代码并不常见。最初,您主要会使用JupyterLab 上的 Jupyter notebook。本文将介绍如何在Azure Machine Learning工作区中使用TensorFlow模型进行训练。
您可以在GitHub上找到本文的示例代码。
必备组件
要按照本文中的示例进行操作,您需要一个网页浏览器和一个 Azure 订阅。如果您没有订阅,可以注册一个免费 Azure 帐户。
设置 Azure Machine Learning 工作区
如果您已按照前两篇文章中的示例进行操作,您应该已经创建了一个 **Azure: Machine Learning** 工作区。如果没有,您可以像创建任何其他 Azure 资源一样快速构建它。一种方法是登录Azure 门户,单击“**创建资源**”,然后在搜索框中键入“machine learning”。
从列表中选择“**Machine Learning**”并单击“**创建**”后,您需要输入工作区的详细信息。
您可以输入任何喜欢的名称,但在以下示例中,我们将资源组称为 azureml-rg,将工作区名称称为 demo-ws。满意后,单击“**审查 + 创建**”,然后在最终的向导屏幕上单击“**创建**”。几分钟后,您就可以访问新资源了。
其余时间我们将花费在 Azure Machine Learning Studio 中。要进入该界面,请在 Azure 门户中单击“**启动工作室**”或在浏览器中手动输入 ml.azure.com。然后,选择您的工作区。
准备 Azure ML Notebook
创建 notebook 最简单的方法是单击 Azure Machine Learning Studio 中“**Notebooks**”磁贴上的“**立即开始**”按钮。
在此之前,我们需要添加一个计算实例。没有它,我们仍然可以创建和编辑 notebook,但无法运行其代码。
继续操作,单击左侧菜单上的“**计算**”选项。
在这里,我们有四种选择
- 计算实例
- 计算群集
- 推理群集
- 已连接的计算机
计算实例是处理 notebook 的最佳选择。
创建新的计算实例时,我们需要提供其名称和虚拟机 (VM) 参数。您可能需要在此处发挥一点创意,因为它在您的 Azure 区域中必须是唯一的。如果您预计会有繁重的计算,可以考虑使用 GPU 的 VM。
与用于后台处理的计算群集不同,按需配置计算实例并在不使用时删除它不是自动的。最初,您大部分时间都在编写代码,而不是运行它。因此,GPU 也会空闲。
当计算实例运行时,您可以在“**计算实例**”选项卡上看到其状态。
从这里,我们可以启动 JupyterLab 或 Jupyter。选择您喜欢的任何选项。为了我们的目的,这无关紧要,所以我们继续使用 Jupyter。然而,对于更严肃的开发,JupyterLab 提供了许多有用的功能。
当 Jupyter 启动(应该只需要片刻),我们选择“**新建**”,然后选择“**Python 3.8 - Tensorflow**”内核。最终我们会得到一个新建的空 notebook。
让我们给它命名(例如,“aml-demo-tf-notebook”)。现在我们准备开始。
下载 MNIST 数据集
与本系列前两篇文章一样,我们首先下载 MNIST 手写数字数据集。我们将使用 Microsoft 的Azure Open Datasets作为来源。
import os
import urllib.request
DATA_FOLDER = os.path.join(os.getcwd(), 'datasets/mnist-data')
DATASET_BASE_URL = 'https://azureopendatastorage.blob.core.windows.net/mnist/'
os.makedirs(DATA_FOLDER, exist_ok=True)
urllib.request.urlretrieve(
os.path.join(DATASET_BASE_URL, 'train-images-idx3-ubyte.gz'),
filename=os.path.join(DATA_FOLDER, 'train-images.gz'))
urllib.request.urlretrieve(
os.path.join(DATASET_BASE_URL, 'train-labels-idx1-ubyte.gz'),
filename=os.path.join(DATA_FOLDER, 'train-labels.gz'))
urllib.request.urlretrieve(
os.path.join(DATASET_BASE_URL, 't10k-images-idx3-ubyte.gz'),
filename=os.path.join(DATA_FOLDER, 'test-images.gz'))
urllib.request.urlretrieve(
os.path.join(DATASET_BASE_URL, 't10k-labels-idx1-ubyte.gz'),
filename=os.path.join(DATA_FOLDER, 'test-labels.gz'))
执行此单元格后,数据集文件将准备就绪。
探索 MNIST 数据集
数据集已下载到我们的 ML 工作区后,我们就可以对其进行探索了。首先,我们需要加载它。此代码部分特定于数据集,在我们的例子中,是从Azure Open Datasets 示例借用的。如果您想使用自己的数据,则需要相应地更新或替换它。
import gzip
import struct
import numpy as np
def load_dataset(dataset_path):
def unpack_mnist_data(filename: str, label=False):
with gzip.open(filename) as gz:
struct.unpack('I', gz.read(4))
n_items = struct.unpack('>I', gz.read(4))
if not label:
n_rows = struct.unpack('>I', gz.read(4))[0]
n_cols = struct.unpack('>I', gz.read(4))[0]
res = np.frombuffer(gz.read(n_items[0] * n_rows * n_cols), dtype=np.uint8)
res = res.reshape(n_items[0], n_rows * n_cols) / 255.0
else:
res = np.frombuffer(gz.read(n_items[0]), dtype=np.uint8)
res = res.reshape(-1)
return res
X_train = unpack_mnist_data(os.path.join(dataset_path, 'train-images.gz'), False)
y_train = unpack_mnist_data(os.path.join(dataset_path, 'train-labels.gz'), True)
X_test = unpack_mnist_data(os.path.join(dataset_path, 'test-images.gz'), False)
y_test = unpack_mnist_data(os.path.join(dataset_path, 'test-labels.gz'), True)
return X_train.reshape(-1,28,28,1), y_train, X_test.reshape(-1,28,28,1), y_test
除了简单地加载数据之外,load_dataset
方法还会对像素值进行归一化(范围从 0-255 到 0-1),并将输出整形为 TensorFlow 框架期望的维度。
要加载我们的数据集,我们运行
X_train, y_train, X_test, y_test = load_dataset(DATA_FOLDER)
我们可以确认训练集中有预期的 60,000 个单色图像(每个 28 x 28 像素)。
让我们看看里面有什么
def show_images(images, labels):
images_cnt = len(images)
f, axarr = plt.subplots(nrows=1, ncols=images_cnt, figsize=(16,16))
for idx in range(images_cnt):
img = images[idx]
lab = labels[idx]
axarr[idx].imshow(img, cmap='gray_r')
axarr[idx].title.set_text(lab)
axarr[idx].axis('off')
plt.show()
show_images(X_train[:10], y_train[:10])
运行此单元格将显示训练集中的前十个带标签的图像。
定义模型
我们有了数据,现在可以开始处理模型了。为了使其符合目的,我们将创建一个简单的卷积神经网络 (CNN),该网络接受 28 x 28 矩阵,并为 10 个数字中的每一个返回概率分数。
import tensorflow as tf
def create_tf_model():
model = tf.keras.models.Sequential(
[
tf.keras.layers.Conv2D(filters=10, kernel_size=5, input_shape=(28,28,1), activation='relu'),
tf.keras.layers.MaxPool2D(pool_size=(2,2)),
tf.keras.layers.Conv2D(filters=20, kernel_size=5, activation='relu'),
tf.keras.layers.Dropout(rate=0.2),
tf.keras.layers.MaxPool2D(pool_size=(2,2)),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(320, activation='relu'),
tf.keras.layers.Dense(50, activation='relu'),
tf.keras.layers.Dropout(0.2),
tf.keras.layers.Dense(10, activation='relu')
]
)
return model
model = create_tf_model()
model.build()
使用 model.summary
方法,我们可以检查其层和参数数量。
训练模型
训练之前,我们必须使用选定的损失函数和优化器来编译我们的模型。
loss_fn = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)
model.compile(optimizer="adam", loss=loss_fn, metrics=[“accuracy”])
现在,我们可以开始训练了。如果我们想在 Azure ML 实验中保留训练历史记录,我们需要先处理好。
from azureml.core import Workspace, Experiment
import mlflow, mlflow.tensorflow
SUBSCRIPTION="<your-subscription-id>"
GROUP="azureml-rg"
WORKSPACE="demo-ws"
ws = Workspace(
subscription_id=SUBSCRIPTION,
resource_group=GROUP,
workspace_name=WORKSPACE,
)
experiment = Experiment(ws, "aml-demo-tf-notebook-training")
mlflow.set_tracking_uri(ws.get_mlflow_tracking_uri())
mlflow.start_run(experiment_id=experiment.id)
mlflow.tensorflow.autolog()
使用上面的代码,我们创建新的实验 (aml-demo-tf-notebook-training
),告知 MLflow 框架使用 Azure ML 工作区进行跟踪,启动新的运行,最后请求 MLflow 自动记录 TensorFlow 训练进度。此自动记录功能可确保模型参数和训练进度的跟踪,无需额外的手动步骤。
有了所有这些组件,我们终于可以开始训练了。为了确保运行之间的可重复结果,我们使用恒定的随机种子。
tf.random.set_seed(101)
model.fit(X_train, y_train, epochs=5)
mlflow.end_run()
我们的简单模型和相对简单的数据集,无论选择的计算实例 VM 的大小如何,都不应该花费太长时间。
由于我们的跟踪配置,我们可以使用机器学习 Studio 中的“**实验**”选项卡来检查其进度和指标(在训练期间和之后)。
如果训练模型花费的时间太长,可能是时候重新考虑计算 VM 的大小了。您可以随时返回机器学习 Studio 的“**计算**”部分来创建更强大的 VM 实例,然后重新运行 notebook。或者,您可以将训练代码保存在单独的文件中,并在计算群集上运行训练。后者使用 Visual Studio Code 会稍微容易一些,如前两篇文章所示。
评估和注册模型
训练后,我们可以检查我们的模型在之前未见过的测试数据上的表现。最简单的方法是使用模型的 evaluate 方法。
我们有 98% 的准确率。如果模型对我们来说足够好,我们可以保存它并注册以供将来使用。保存 TensorFlow 模型有多种选项。我们使用单文件 HDF5 格式,因为它具有可移植性。最后,保存模型后,我们可以将其注册到 **Azure: Machine Learning** 工作区。
from azureml.core.model import Model
model.save(‘mnist-tf-model.h5')
registered_model = Model.register(
workspace=ws,
model_name='mnist-tf-model',
model_path='mnist-tf-model.h5',
model_framework=Model.Framework.TENSORFLOW,
model_framework_version=tf.__version__)
训练好的模型现在可供将来使用。
使用保存的模型进行预测
要加载在 **Azure: Machine Learning** 工作区中注册的模型,我们使用以下代码。
aml_model = Model(workspace=ws, name='mnist-tf-model', version=registered_model.version)
downloaded_model_filename = aml_model.download(exist_ok=True)
downloaded_model = tf.keras.models.load_model(downloaded_model_filename)
如果您在训练后的另一个 notebook 会话中运行此代码,请确保提供正确的 version 参数值。
让我们看看我们加载了什么。
现在我们可以使用该模型进行预测了。
preds = downloaded_model.predict(X_test).argmax(axis=1)
我们可以快速检查它与真实值相比如何。
正如我们所见,前三个和最后三个预测值是正确的。
如果我们仍然对我们的模型没有信心,我们可以使用与之前相同的方法来查看为测试图像预测的标签。
show_images(X_test[:10], preds[:10])
现在,让我们使用完整的测试数据集来评估预测。我们可以再次使用 downloaded_model.evaluate
方法,但为了避免重新运行预测,我们也可以依赖 scikit-learn
方法。
from sklearn.metrics import accuracy_score
accuracy_score(y_test, preds)
我们应该得到与训练结束后直接获得的值相同的值,即 0.9864。
清理 Azure 资源
一旦您完成 notebook 的工作,请记住停止并删除您不再需要的资源。一种极端的方法是删除整个资源组 azureml-rg
。如果您想保留数据,至少应该做的是停止所有计算实例。
与我们在前几篇文章中使用的计算群集不同,计算实例不会在配置的非活动时段后自动停止。
摘要
在本系列文章中,您已经了解了我们可以通过多种不同的方式使用 Python 来创建和训练使用 Azure Machine Learning 的模型。这最后一个三部分系列的文章展示了如何使用 Azure ML notebook 训练 TensorFlow 模型。
在本文中,您体验了如何通过很小的努力就可以调整示例代码以处理您自己图像的任何图像分类任务。很可能,您会有不同数量的通道(MNIST 图像是单色的)和类别。在这种情况下,您必须相应地更改模型代码和 load_dataset
方法。
要了解开始使用 Azure Machine Learning 所需的所有内容,请查看快速入门:创建工作区资源。