Microsoft 认知工具包 - 快速指南


Microsoft 认知工具包 (CNTK) - 简介

在本章中,我们将了解什么是 CNTK、它的特性、1.0 版本和 2.0 版本之间的区别以及 2.7 版本的重要亮点。

什么是微软认知工具包 (CNTK)?

微软认知工具包(CNTK),以前称为计算网络工具包,是一个免费、易于使用、开源、商业级的工具包,使我们能够训练深度学习算法,像人脑一样学习。它使我们能够创建一些流行的深度学习系统,例如前馈神经网络时间序列预测系统和卷积神经网络(CNN)图像分类器

为了获得最佳性能,其框架函数是用 C++ 编写的。虽然我们可以使用C++调用它的函数,但最常用的方法是使用Python程序。

CNTK的特点

以下是最新版本的 Microsoft CNTK 中提供的一些特性和功能:

内置组件

  • CNTK 具有高度优化的内置组件,可以处理来自 Python、C++ 或 BrainScript 的多维密集或稀疏数据。

  • 我们可以通过注意力机制实现 CNN、FNN、RNN、Batch Normalization 和 Sequence-to-Sequence。

  • 它为我们提供了从 Python 在 GPU 上添加新的用户定义核心组件的功能。

  • 它还提供自动超参数调整。

  • 我们可以实施强化学习、生成对抗网络 (GAN)、监督学习和无监督学习。

  • 对于海量数据集,CNTK内置了优化的阅读器。

有效利用资源

  • CNTK 通过 1 位 SGD 在多个 GPU/机器上为我们提供高精度的并行性。

  • 为了适应 GPU 内存中最大的模型,它提供了内存共享和其他内置方法。

轻松表达我们自己的网络

  • CNTK 拥有完整的 API,可用于定义您自己的网络、学习者、读者、Python、C++ 和 BrainScript 的培训和评估。

  • 使用 CNTK,我们可以轻松地使用 Python、C++、C# 或 BrainScript 评估模型。

  • 它提供高级和低级 API。

  • 根据我们的数据,它可以自动形成推论。

  • 它具有完全优化的符号循环神经网络 (RNN) 循环。

测量模型性能

  • CNTK 提供了各种组件来衡量您构建的神经网络的性能。

  • 从您的模型和关联的优化器生成日志数据,我们可以用它来监控训练过程。

1.0 版与 2.0 版

下表比较了 CNTK 1.0 和 2.0 版本:

1.0版本 2.0版本
它于 2016 年发布。 它是对 1.0 版本的重大重写,于 2017 年 6 月发布。
它使用一种名为 BrainScript 的专有脚本语言。 其框架功能可以使用C++、Python调用。我们可以轻松地用 C# 或 Java 加载我们的模块。2.0 版也支持 BrainScript。
它可以在 Windows 和 Linux 系统上运行,但不能直接在 Mac OS 上运行。 它还可以在 Windows(Win 8.1、Win 10、Server 2012 R2 及更高版本)和 Linux 系统上运行,但不能直接在 Mac OS 上运行。

2.7 版本的重要亮点

2.7 版是 Microsoft Cognitive Toolkit 的最后一个主要发布版本。它完全支持 ONNX 1.4.1。以下是 CNTK 最后发布版本的一些重要亮点。

  • 完全支持 ONNX 1.4.1。

  • 支持 Windows 和 Linux 系统的 CUDA 10。

  • 它支持 ONNX 导出中的高级循环神经网络 (RNN) 循环。

  • 它可以以 ONNX 格式导出超过 2GB 的模型。

  • 它支持 BrainScript 脚本语言的训练动作中的 FP16。

Microsoft 认知工具包 (CNTK) - 入门

在这里,我们将了解CNTK在Windows和Linux上的安装。此外,本章还介绍了安装 CNTK 软件包、安装 Anaconda 的步骤、CNTK 文件、目录结构和 CNTK 库组织。

先决条件

为了安装 CNTK,我们必须在计算机上安装 Python。您可以访问链接https://www.python.org/downloads/并选择适合您操作系统的最新版本,即 Windows 和 Linux/Unix。关于Python的基础教程,可以参考链接https://www.tutorialspoint.com/python3/index.htm

Python 下载

CNTK 支持 Windows 和 Linux,因此我们将介绍它们。

在 Windows 上安装

为了在 Windows 上运行 CNTK,我们将使用Anaconda 版本的 Python。我们知道,Anaconda 是 Python 的重新发行版。它包括ScipyScikit-learn等附加包,CNTK 使用它们来执行各种有用的计算。

因此,首先让我们看看在您的计算机上安装 Anaconda 的步骤 -

步骤1 -首先从公共网站https://www.anaconda.com/distribution/下载安装文件。

步骤 2 - 下载安装文件后,开始安装并按照链接https://docs.anaconda.com/anaconda/install/中的说明进行操作。

步骤 3 - 安装后,Anaconda 还将安装一些其他实用程序,这些实用程序将自动将所有 Anaconda 可执行文件包含在您的计算机 PATH 变量中。我们可以从这个提示符管理我们的Python环境,可以安装包并运行Python脚本。

安装 CNTK 包

Anaconda 安装完成后,您可以使用以下命令通过 pip 可执行文件使用最常见的方式安装 CNTK 包 -

pip install cntk

还有多种其他方法可以在您的计算机上安装认知工具包。Microsoft 有一套简洁的文档,详细解释了其他安装方法。请点击链接 https://docs.microsoft.com/en-us/cognitive-toolkit/Setup-CNTK-on-your-machine

在 Linux 上安装

CNTK 在 Linux 上的安装与在 Windows 上的安装有点不同。在这里,对于 Linux,我们将使用 Anaconda 来安装 CNTK,但我们将在 Linux 上使用基于终端的安装程序,而不是 Anaconda 的图形安装程序。虽然安装程序适用于几乎所有 Linux 发行版,但我们将描述限制为 Ubuntu。

因此,首先让我们看看在您的计算机上安装 Anaconda 的步骤 -

安装Anaconda的步骤

步骤 1 - 在安装 Anaconda 之前,请确保系统完全是最新的。要进行检查,首先在终端内执行以下两个命令 -

sudo apt update
sudo apt upgrade

步骤 2 - 计算机更新后,从公共网站https://www.anaconda.com/distribution/获取最新 Anaconda 安装文件的 URL。

步骤 3 - 复制 URL 后,打开终端窗口并执行以下命令 -

wget -0 anaconda-installer.sh url SHAPE \* MERGEFORMAT 
     y

	
	
	             f
 
 
      x
	  
|                     }

url占位符替换为从 Anaconda 网站复制的 URL。

步骤 4 - 接下来,借助以下命令,我们可以安装 Anaconda -

sh ./anaconda-installer.sh

上面的命令默认会在我们的主目录中安装Anaconda3 。

安装 CNTK 包

Anaconda 安装完成后,您可以使用以下命令通过 pip 可执行文件使用最常见的方式安装 CNTK 包 -

pip install cntk

检查 CNTK 文件和目录结构

一旦 CNTK 作为 Python 包安装,我们就可以检查它的文件和目录结构。它位于C:\Users\\Anaconda3\Lib\site-packages\cntk,如下截图所示。

文件和目录结构

验证 CNTK 安装

一旦 CNTK 作为 Python 包安装,您应该验证 CNTK 是否已正确安装。在 Anaconda 命令 shell 中,输入ipython 启动 Python 解释器。然后,通过输入以下命令导入CNTK 。

import cntk as c

导入后,使用以下命令检查其版本 -

print(c.__version__)

解释器将响应已安装的 CNTK 版本。如果没有响应,则说明安装有问题。

CNTK图书馆组织

CNTK 从技术上讲是一个 python 包,分为 13 个高级子包和 8 个较小的子包。下表列出了 10 个最常用的软件包:

先生编号 包名称和描述
1

cntk.io

包含读取数据的函数。例如:next_minibatch()

2

cntk层

包含用于创建神经网络的高级函数。例如:密集()

3

CNTK学习者

包含训练功能。例如:sgd()

4

CNTK.损失

包含测量训练误差的函数。例如:squared_error()

5

cntk.metrics

包含测量模型误差的函数。例如:分类错误

6

cntk操作程序

包含用于创建神经网络的低级函数。例如:tanh()

7

CNTK.随机数

包含生成随机数的函数。例如:正常()

8

cntk火车

包含训练功能。例如:train_minibatch()

9

cntk.初始化程序

包含模型参数初始值设定项。例如:normal()uniform()

10

cntk.变量

包含低级构造。例如:参数()变量()

Microsoft 认知工具包 (CNTK) - CPU 和 GPU

Microsoft Cognitive Toolkit 提供两种不同的构建版本,即仅 CPU 和仅 GPU。

仅 CPU 构建版本

CNTK 的纯 CPU 版本使用优化的英特尔 MKLML,其中 MKLML 是 MKL(数学内核库)的子集,并与英特尔 MKL-DNN 一起发布,作为 MKL-DNN 的英特尔 MKL 终止版本。

仅 GPU 构建版本

另一方面,CNTK 的纯 GPU 构建版本使用高度优化的 NVIDIA 库,例如CUBcuDNN。它支持跨多个 GPU 和多台机器的分布式训练。为了在 CNTK 中进行更快的分布式训练,GPU 构建版本还包括 -

  • MSR 开发的 1 位量化 SGD。

  • 块动量 SGD 并行训练算法。

在 Windows 上使用 CNTK 启用 GPU

在上一节中,我们了解了如何安装 CNTK 的基本版本以与 CPU 一起使用。现在让我们讨论如何安装 CNTK 以与 GPU 一起使用。但是,在深入研究之前,首先您应该有一个受支持的显卡。

目前CNTK支持至少支持CUDA 3.0的NVIDIA显卡。为了确保这一点,您可以在 https://developer.nvidia.com/cuda-gpus检查您的 GPU 是否支持 CUDA。

那么,让我们看看在 Windows 操作系统上使用 CNTK 启用 GPU 的步骤 -

步骤 1 - 根据您使用的显卡,首先您需要为您的显卡安装最新的 GeForce 或 Quadro 驱动程序。

步骤 2 - 下载驱动程序后,您需要从 NVIDIA 网站https://developer.nvidia.com/cuda-90-download-archive?target_os=Windows&target_arch=x86_64安装适用于 Windows 的 CUDA 工具包版本 9.0 。安装后,运行安装程序并按照说明进行操作。

步骤 3 - 接下来,您需要从 NVIDIA 网站https://developer.nvidia.com/rdp/form/cudnn-download-survey安装 cuDNN 二进制文件。使用 CUDA 9.0 版本,cuDNN 7.4.1 运行良好。基本上,cuDNN 是 CUDA 之上的一层,由 CNTK 使用。

步骤 4 - 下载 cuDNN 二进制文件后,您需要将 zip 文件解压到 CUDA 工具包安装的根文件夹中。

步骤 5 - 这是最后一步,将启用 CNTK 内的 GPU 使用。在 Windows 操作系统的 Anaconda 提示符下执行以下命令 -

pip install cntk-gpu

在 Linux 上使用 CNTK 启用 GPU

让我们看看如何在 Linux 操作系统上使用 CNTK 启用 GPU -

下载 CUDA 工具包

首先,您需要从 NVIDIA 网站https://developer.nvidia.com/cuda-90-download-archive?target_os=Linux&target_arch=x86_64&target_distro=Ubuntu&target_version=1604&target_type =runfilelocal安装 CUDA 工具包。

运行安装程序

现在,一旦磁盘上有二进制文件,请通过打开终端并执行以下命令和屏幕上的说明来运行安装程序 -

sh cuda_9.0.176_384.81_linux-run

修改 Bash 配置文件脚本

在 Linux 计算机上安装 CUDA 工具包后,您需要修改 BASH 配置文件脚本。为此,首先在文本编辑器中打开 $HOME/ .bashrc 文件。现在,在脚本的末尾,包含以下行 -

export PATH=/usr/local/cuda-9.0/bin${PATH:+:${PATH}}
export LD_LIBRARY_PATH=/usr/local/cuda-9.0/lib64\
${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
Installing

安装 cuDNN 库

最后我们需要安装 cuDNN 二进制文件。可以从 NVIDIA 网站https://developer.nvidia.com/rdp/form/cudnn-download-survey下载。使用 CUDA 9.0 版本,cuDNN 7.4.1 运行良好。基本上,cuDNN 是 CUDA 之上的一层,由 CNTK 使用。

下载 Linux 版本后,使用以下命令将其解压到/usr/local/cuda-9.0文件夹 -

tar xvzf -C /usr/local/cuda-9.0/ cudnn-9.0-linux-x64-v7.4.1.5.tgz

根据需要更改文件名的路径。

CNTK-序列分类

在本章中,我们将详细了解CNTK中的序列及其分类。

张量

CNTK 工作的概念是张量。基本上,CNTK 输入、输出以及参数被组织为张量,通常被认为是广义矩阵。每个张量都有一个等级-

  • 阶为 0 的张量是标量。

  • 1 阶张量是一个向量。

  • 2 阶张量是矩阵。

这里,这些不同的维度被称为轴。

静态轴和动态轴

顾名思义,静态轴在网络的整个生命周期中具有相同的长度。另一方面,动态轴的长度可能因实例而异。事实上,在呈现每个小批量之前,它们的长度通常是未知的。

动态轴与静态轴类似,因为它们还定义了张量中包含的数字的有意义的分组。

例子

为了更清楚地说明这一点,让我们看看 CNTK 中如何表示小批量的短视频剪辑。假设视频片段的分辨率均为640 * 480。并且片段也是彩色拍摄的,通常采用三通道编码。这进一步意味着我们的小批量具有以下内容 -

  • 3 个静态轴,长度分别为 640、480 和 3。

  • 两个动态轴;视频和小批量轴的长度。

这意味着如果一个小批量有 16 个视频,每个视频长 240 帧,则将表示为16*240*3*640*480张量。

在 CNTK 中处理序列

让我们首先了解长短期记忆网络来理解 CNTK 中的序列。

长短期记忆网络 (LSTM)

长短期记忆网络

长短期记忆 (LSTM) 网络由 Hochreiter 和 Schmidhuber 提出。它解决了让基本循环层长期记住事物的问题。LSTM 的架构如上图所示。正如我们所看到的,它有输入神经元、记忆细胞和输出神经元。为了解决梯度消失问题,长期短期记忆网络使用显式记忆单元(存储先前的值)和以下门 -

  • 忘记门- 顾名思义,它告诉存储单元忘记以前的值。存储单元存储这些值,直到门(即“忘记门”)告诉它忘记它们。

  • 输入门- 顾名思义,它向单元添加新的东西。

  • 输出门- 顾名思义,输出门决定何时将向量从单元传递到下一个隐藏状态。

在 CNTK 中使用序列非常容易。让我们借助以下示例来看看它 -

import sys
import os
from cntk import Trainer, Axis
from cntk.io import MinibatchSource, CTFDeserializer, StreamDef, StreamDefs,\
   INFINITELY_REPEAT
from cntk.learners import sgd, learning_parameter_schedule_per_sample
from cntk import input_variable, cross_entropy_with_softmax, \
   classification_error, sequence
from cntk.logging import ProgressPrinter
from cntk.layers import Sequential, Embedding, Recurrence, LSTM, Dense
def create_reader(path, is_training, input_dim, label_dim):
   return MinibatchSource(CTFDeserializer(path, StreamDefs(
      features=StreamDef(field='x', shape=input_dim, is_sparse=True),
      labels=StreamDef(field='y', shape=label_dim, is_sparse=False)
   )), randomize=is_training,
   max_sweeps=INFINITELY_REPEAT if is_training else 1)
def LSTM_sequence_classifier_net(input, num_output_classes, embedding_dim,
LSTM_dim, cell_dim):
   lstm_classifier = Sequential([Embedding(embedding_dim),
      Recurrence(LSTM(LSTM_dim, cell_dim)),
      sequence.last,
      Dense(num_output_classes)])
return lstm_classifier(input)
def train_sequence_classifier():
   input_dim = 2000
   cell_dim = 25
   hidden_dim = 25
   embedding_dim = 50
   num_output_classes = 5
   features = sequence.input_variable(shape=input_dim, is_sparse=True)
   label = input_variable(num_output_classes)
   classifier_output = LSTM_sequence_classifier_net(
   features, num_output_classes, embedding_dim, hidden_dim, cell_dim)
   ce = cross_entropy_with_softmax(classifier_output, label)
   pe =      classification_error(classifier_output, label)
   rel_path = ("../../../Tests/EndToEndTests/Text/" +
      "SequenceClassification/Data/Train.ctf")
   path = os.path.join(os.path.dirname(os.path.abspath(__file__)), rel_path)
   reader = create_reader(path, True, input_dim, num_output_classes)
input_map = {
   features: reader.streams.features,
   label: reader.streams.labels
}
lr_per_sample = learning_parameter_schedule_per_sample(0.0005)
progress_printer = ProgressPrinter(0)
trainer = Trainer(classifier_output, (ce, pe),
sgd(classifier_output.parameters, lr=lr_per_sample),progress_printer)
minibatch_size = 200
for i in range(255):
   mb = reader.next_minibatch(minibatch_size, input_map=input_map)
trainer.train_minibatch(mb)
   evaluation_average = float(trainer.previous_minibatch_evaluation_average)
   loss_average = float(trainer.previous_minibatch_loss_average)
return evaluation_average, loss_average
if __name__ == '__main__':
   error, _ = train_sequence_classifier()
   print(" error: %f" % error)
average  since  average  since  examples
loss     last   metric   last
------------------------------------------------------
1.61    1.61    0.886     0.886     44
1.61     1.6    0.714     0.629    133
 1.6    1.59     0.56     0.448    316
1.57    1.55    0.479      0.41    682
1.53     1.5    0.464     0.449   1379
1.46     1.4    0.453     0.441   2813
1.37    1.28     0.45     0.447   5679
 1.3    1.23    0.448     0.447  11365

error: 0.333333

上述程序的详细解释将在下一节中介绍,特别是当我们构建循环神经网络时。

CNTK - 逻辑回归模型

本章讨论在 CNTK 中构建逻辑回归模型。

逻辑回归模型基础知识

逻辑回归是最简单的机器学习技术之一,是一种专门用于二元分类的技术。换句话说,在要预测的变量值可以是两个分类值之一的情况下创建预测模型。逻辑回归最简单的例子之一是根据人的年龄、声音、头发等来预测人是男性还是女性。

例子

让我们借助另一个例子从数学上理解逻辑回归的概念 -

假设,我们想要预测贷款申请的信用度;根据申请人的债务、收入信用评级,0 表示拒绝,1 表示批准。我们用 X1 表示债务,用 X2 表示收入,用 X3 表示信用评级。

在逻辑回归中,我们为每个特征确定一个权重值(用w表示)和一个偏差值(用b表示) 。

现在假设,

X1 = 3.0
X2 = -2.0
X3 = 1.0

假设我们确定权重和偏差如下 -

W1 = 0.65, W2 = 1.75, W3 = 2.05 and b = 0.33

现在,为了预测类别,我们需要应用以下公式 -

Z = (X1*W1)+(X2*W2)+(X3+W3)+b
i.e. Z = (3.0)*(0.65) + (-2.0)*(1.75) + (1.0)*(2.05) + 0.33
= 0.83

接下来,我们需要计算P = 1.0/(1.0 + exp(-Z))。这里,exp()函数是欧拉数。

P = 1.0/(1.0 + exp(-0.83)
= 0.6963

P 值可以解释为类别为 1 的概率。如果 P < 0.5,则预测为类别 = 0,否则预测 (P >= 0.5) 为类别 = 1。

为了确定权重和偏差的值,我们必须获得一组具有已知输入预测变量值和已知正确类别标签值的训练数据。之后,我们可以使用一种算法,通常是梯度下降,来找到权重和偏差的值。

LR模型实现示例

对于这个 LR 模型,我们将使用以下数据集 -

1.0, 2.0, 0
3.0, 4.0, 0
5.0, 2.0, 0
6.0, 3.0, 0
8.0, 1.0, 0
9.0, 2.0, 0
1.0, 4.0, 1
2.0, 5.0, 1
4.0, 6.0, 1
6.0, 5.0, 1
7.0, 3.0, 1
8.0, 5.0, 1

要在 CNTK 中启动 LR 模型实现,我们需要首先导入以下包 -

import numpy as np
import cntk as C

该程序的结构如下: main() 函数 -

def main():
print("Using CNTK version = " + str(C.__version__) + "\n")

现在,我们需要将训练数据加载到内存中,如下所示 -

data_file = ".\\dataLRmodel.txt"
print("Loading data from " + data_file + "\n")
features_mat = np.loadtxt(data_file, dtype=np.float32, delimiter=",", skiprows=0, usecols=[0,1])
labels_mat = np.loadtxt(data_file, dtype=np.float32, delimiter=",", skiprows=0, usecols=[2], ndmin=2)

现在,我们将创建一个训练程序,该程序创建与训练数据兼容的逻辑回归模型 -

features_dim = 2
labels_dim = 1
X = C.ops.input_variable(features_dim, np.float32)
y = C.input_variable(labels_dim, np.float32)
W = C.parameter(shape=(features_dim, 1)) # trainable cntk.Parameter
b = C.parameter(shape=(labels_dim))
z = C.times(X, W) + b
p = 1.0 / (1.0 + C.exp(-z))
model = p

现在,我们需要创建 Lerner 和 trainer,如下所示 -

ce_error = C.binary_cross_entropy(model, y) # CE a bit more principled for LR
fixed_lr = 0.010
learner = C.sgd(model.parameters, fixed_lr)
trainer = C.Trainer(model, (ce_error), [learner])
max_iterations = 4000

LR模型训练

一旦我们创建了 LR 模型,接下来就该开始训练过程了 -

np.random.seed(4)
N = len(features_mat)
for i in range(0, max_iterations):
row = np.random.choice(N,1) # pick a random row from training items
trainer.train_minibatch({ X: features_mat[row], y: labels_mat[row] })
if i % 1000 == 0 and i > 0:
mcee = trainer.previous_minibatch_loss_average
print(str(i) + " Cross-entropy error on curr item = %0.4f " % mcee)

现在,借助以下代码,我们可以打印模型权重和偏差 -

np.set_printoptions(precision=4, suppress=True)
print("Model weights: ")
print(W.value)
print("Model bias:")
print(b.value)
print("")
if __name__ == "__main__":
main()

训练逻辑回归模型 - 完整示例

import numpy as np
import cntk as C
   def main():
print("Using CNTK version = " + str(C.__version__) + "\n")
data_file = ".\\dataLRmodel.txt" # provide the name and the location of data file
print("Loading data from " + data_file + "\n")
features_mat = np.loadtxt(data_file, dtype=np.float32, delimiter=",", skiprows=0, usecols=[0,1])
labels_mat = np.loadtxt(data_file, dtype=np.float32, delimiter=",", skiprows=0, usecols=[2], ndmin=2)
features_dim = 2
labels_dim = 1
X = C.ops.input_variable(features_dim, np.float32)
y = C.input_variable(labels_dim, np.float32)
W = C.parameter(shape=(features_dim, 1)) # trainable cntk.Parameter
b = C.parameter(shape=(labels_dim))
z = C.times(X, W) + b
p = 1.0 / (1.0 + C.exp(-z))
model = p
ce_error = C.binary_cross_entropy(model, y) # CE a bit more principled for LR
fixed_lr = 0.010
learner = C.sgd(model.parameters, fixed_lr)
trainer = C.Trainer(model, (ce_error), [learner])
max_iterations = 4000
np.random.seed(4)
N = len(features_mat)
for i in range(0, max_iterations):
row = np.random.choice(N,1) # pick a random row from training items
trainer.train_minibatch({ X: features_mat[row], y: labels_mat[row] })
if i % 1000 == 0 and i > 0:
mcee = trainer.previous_minibatch_loss_average
print(str(i) + " Cross-entropy error on curr item = %0.4f " % mcee)
np.set_printoptions(precision=4, suppress=True)
print("Model weights: ")
print(W.value)
print("Model bias:")
print(b.value)
if __name__ == "__main__":
  main()

输出

Using CNTK version = 2.7
1000 cross entropy error on curr item = 0.1941
2000 cross entropy error on curr item = 0.1746
3000 cross entropy error on curr item = 0.0563
Model weights:
[-0.2049]
   [0.9666]]
Model bias:
[-2.2846]

使用经过训练的 LR 模型进行预测

一旦 LR 模型经过训练,我们就可以使用它进行预测,如下所示 -

首先,我们的评估程序导入 numpy 包并将训练数据加载到特征矩阵和类标签矩阵中,其方式与我们上面实现的训练程序相同 -

import numpy as np
def main():
data_file = ".\\dataLRmodel.txt" # provide the name and the location of data file
features_mat = np.loadtxt(data_file, dtype=np.float32, delimiter=",",
skiprows=0, usecols=(0,1))
labels_mat = np.loadtxt(data_file, dtype=np.float32, delimiter=",",
skiprows=0, usecols=[2], ndmin=2)

接下来,是时候设置由我们的训练计划确定的权重和偏差的值了 -

print("Setting weights and bias values \n")
weights = np.array([0.0925, 1.1722], dtype=np.float32)
bias = np.array([-4.5400], dtype=np.float32)
N = len(features_mat)
features_dim = 2

接下来,我们的评估程序将通过遍历每个训练项目来计算逻辑回归概率,如下所示 -

print("item pred_prob pred_label act_label result")
for i in range(0, N): # each item
   x = features_mat[i]
   z = 0.0
   for j in range(0, features_dim):
   z += x[j] * weights[j]
   z += bias[0]
   pred_prob = 1.0 / (1.0 + np.exp(-z))
  pred_label = 0 if pred_prob < 0.5 else 1
   act_label = labels_mat[i]
   pred_str = ‘correct’ if np.absolute(pred_label - act_label) < 1.0e-5 \
    else ‘WRONG’
  print("%2d %0.4f %0.0f %0.0f %s" % \ (i, pred_prob, pred_label, act_label, pred_str))

现在让我们演示如何进行预测 -

x = np.array([9.5, 4.5], dtype=np.float32)
print("\nPredicting class for age, education = ")
print(x)
z = 0.0
for j in range(0, features_dim):
z += x[j] * weights[j]
z += bias[0]
p = 1.0 / (1.0 + np.exp(-z))
print("Predicted p = " + str(p))
if p < 0.5: print("Predicted class = 0")
else: print("Predicted class = 1")

完整的预测评估方案

import numpy as np
def main():
data_file = ".\\dataLRmodel.txt" # provide the name and the location of data file
features_mat = np.loadtxt(data_file, dtype=np.float32, delimiter=",",
skiprows=0, usecols=(0,1))
labels_mat = np.loadtxt(data_file, dtype=np.float32, delimiter=",",
skiprows=0, usecols=[2], ndmin=2)
print("Setting weights and bias values \n")
weights = np.array([0.0925, 1.1722], dtype=np.float32)
bias = np.array([-4.5400], dtype=np.float32)
N = len(features_mat)
features_dim = 2
print("item pred_prob pred_label act_label result")
for i in range(0, N): # each item
   x = features_mat[i]
   z = 0.0
   for j in range(0, features_dim):
     z += x[j] * weights[j]
   z += bias[0]
   pred_prob = 1.0 / (1.0 + np.exp(-z))
   pred_label = 0 if pred_prob < 0.5 else 1
   act_label = labels_mat[i]
   pred_str = ‘correct’ if np.absolute(pred_label - act_label) < 1.0e-5 \
     else ‘WRONG’
  print("%2d %0.4f %0.0f %0.0f %s" % \ (i, pred_prob, pred_label, act_label, pred_str))
x = np.array([9.5, 4.5], dtype=np.float32)
print("\nPredicting class for age, education = ")
print(x)
z = 0.0
for j in range(0, features_dim):
   z += x[j] * weights[j]
z += bias[0]
p = 1.0 / (1.0 + np.exp(-z))
print("Predicted p = " + str(p))
if p < 0.5: print("Predicted class = 0")
else: print("Predicted class = 1")
if __name__ == "__main__":
  main()

输出

设置权重和偏差值。

Item  pred_prob  pred_label  act_label  result
0   0.3640         0             0     correct
1   0.7254         1             0      WRONG
2   0.2019         0             0     correct
3   0.3562         0             0     correct
4   0.0493         0             0     correct
5   0.1005         0             0     correct
6   0.7892         1             1     correct
7   0.8564         1             1     correct
8   0.9654         1             1     correct
9   0.7587         1             1     correct
10  0.3040         0             1      WRONG
11  0.7129         1             1     correct
Predicting class for age, education =
[9.5 4.5]
Predicting p = 0.526487952
Predicting class = 1

CNTK - 神经网络 (NN) 概念

本章讨论与 CNTK 相关的神经网络概念。

众所周知,神经网络使用多层神经元来构建。但是,问题是在 CNTK 中我们如何对神经网络的各层进行建模?这可以借助层模块中定义的层函数来完成。

图层功能

实际上,在 CNTK 中,使用层具有独特的函数式编程感觉。图层函数看起来像常规函数,它生成具有一组预定义参数的数学函数。让我们看看如何借助图层函数创建最基本的图层类型 Dense。

例子

在以下基本步骤的帮助下,我们可以创建最基本的图层类型 -

步骤 1 - 首先,我们需要从 CNTK 的层包中导入 Dense 层函数。

from cntk.layers import Dense

步骤 2 - 接下来,我们需要从 CNTK 根包导入 input_variable 函数。

from cntk import input_variable

步骤 3 - 现在,我们需要使用 input_variable 函数创建一个新的输入变量。我们还需要提供其尺寸。

feature = input_variable(100)

步骤 4 - 最后,我们将使用 Dense 函数创建一个新层,并提供我们想要的神经元数量。

layer = Dense(40)(feature)

现在,我们可以调用配置的 Dense 层函数将 Dense 层连接到输入。

完整的实现示例

from cntk.layers import Dense
from cntk import input_variable
feature= input_variable(100)
layer = Dense(40)(feature)

自定义图层

正如我们所看到的,CNTK 为我们提供了一组非常好的构建神经网络的默认值。根据我们选择的激活函数和其他设置,神经网络的Behave和性能会有所不同。这是另一种非常有用的词干算法。这就是原因,了解我们可以配置什么是有好处的。

配置密集层的步骤

神经网络中的每一层都有其独特的配置选项,当我们谈论密集层时,我们需要定义以下重要设置 -

  • shape - 顾名思义,它定义了该层的输出形状,进一步确定了该层中神经元的数量。

  • 激活- 它定义了该层的激活函数,因此它可以转换输入数据。

  • init - 它定义该层的初始化函数。当我们开始训练神经网络时,它将初始化该层的参数。

让我们看看我们可以配置密集层的步骤-

Step1 - 首先,我们需要从 CNTK 的层包中导入Dense层函数。

from cntk.layers import Dense

Step2 - 接下来从 CNTK ops 包中,我们需要导入sigmoid 运算符。它将用于配置为激活函数。

from cntk.ops import sigmoid

Step3 - 现在,从初始化程序包中,我们需要导入glorot_uniform初始化程序。

from cntk.initializer import glorot_uniform

Step4 - 最后,我们将使用 Dense 函数创建一个新层,并提供神经元数量作为第一个参数。另外,提供sigmoid运算符作为激活函数,并提供glorot_uniform作为该层的初始化函数。

layer = Dense(50, activation = sigmoid, init = glorot_uniform)

完整的实施示例 -

from cntk.layers import Dense
from cntk.ops import sigmoid
from cntk.initializer import glorot_uniform
layer = Dense(50, activation = sigmoid, init = glorot_uniform)

优化参数

到目前为止,我们已经了解了如何创建神经网络的结构以及如何配置各种设置。在这里,我们将看到如何优化神经网络的参数。借助学习器训练器这两个组件的组合,我们可以优化神经网络的参数。

训练器组件

用于优化神经网络参数的第一个组件是训练器组件。它基本上实现了反向传播过程。如果我们谈论它的工作原理,它会通过神经网络传递数据以获得预测。

之后,它使用另一个称为学习器的组件来获取神经网络中参数的新值。一旦获得新值,它就会应用这些新值并重复该过程,直到满足退出标准。

学习者部分

用于优化神经网络参数的第二个组件是学习器组件,它基本上负责执行梯度下降算法。

CNTK 库中包含的学习者

以下是 CNTK 库中包含的一些有趣学习者的列表 -

  • 随机梯度下降(SGD) - 该学习器代表基本的随机梯度下降,没有任何额外的内容。

  • 动量随机梯度下降 (MomentumSGD) - 通过 SGD,该学习器应用动量来克服局部最大值问题。

  • RMSProp - 为了控制下降率,该学习器使用衰减学习率。

  • Adam - 为了随着时间的推移降低下降率,该学习者使用衰减动量。

  • Adagrad - 对于频繁出现和不经常出现的特征,该学习器使用不同的学习率。

CNTK - 创建第一个神经网络

本章将详细介绍在 CNTK 中创建神经网络。

构建网络结构

为了应用 CNTK 概念来构建我们的第一个神经网络,我们将使用神经网络根据萼片宽度和长度以及花瓣宽度和长度的物理特性对鸢尾花的种类进行分类。我们将使用鸢尾花数据集来描述不同品种鸢尾花的物理特性 -

  • 萼片长度
  • 萼片宽度
  • 花瓣长度
  • 花瓣宽度
  • ie 类山鸢尾或杂色鸢尾或维吉尼亚鸢尾

在这里,我们将构建一个称为前馈神经网络的常规神经网络。让我们看看构建神经网络结构的实现步骤 -

步骤 1 - 首先,我们将从 CNTK 库导入必要的组件,例如层类型、激活函数以及允许我们为神经网络定义输入变量的函数。

from cntk import default_options, input_variable
from cntk.layers import Dense, Sequential
from cntk.ops import log_softmax, relu

步骤 2 - 之后,我们将使用顺序函数创建模型。创建后,我们将为它提供我们想要的层。在这里,我们将在神经网络中创建两个不同的层;一个有四个神经元,另一个有三个神经元。

model = Sequential([Dense(4, activation=relu), Dense(3, activation=log_sogtmax)])

步骤 3 - 最后,为了编译神经网络,我们将网络绑定到输入变量。它有一个包含四个神经元的输入层和一个包含三个神经元的输出层。

feature= input_variable(4)
z = model(feature)

应用激活函数

有很多激活函数可供选择,选择正确的激活函数肯定会对我们的深度学习模型的表现产生很大的影响。

在输出层

在输出层选择激活函数将取决于我们要用模型解决的问题类型。

  • 对于回归问题,我们应该在输出层使用线性激活函数。

  • 对于二元分类问题,我们应该在输出层使用sigmoid 激活函数。

  • 对于多类分类问题,我们应该在输出层使用softmax激活函数。

  • 在这里,我们将构建一个模型来预测这三个类别之一。这意味着我们需要在输出层使用softmax激活函数

在隐藏层

在隐藏层选择激活函数需要进行一些实验来监控性能,以了解哪种激活函数效果良好。

  • 在分类问题中,我们需要预测样本属于特定类别的概率。这就是为什么我们需要一个为我们提供概率值的激活函数。为了达到这个目标,sigmoid激活函数可以帮助我们。

  • 与 sigmoid 函数相关的主要问题之一是梯度消失问题。为了克服这个问题,我们可以使用ReLU 激活函数,将所有负值转换为零,并作为正值的直通滤波器。

选择损失函数

一旦我们有了神经网络模型的结构,我们就必须对其进行优化。为了优化我们需要一个损失函数与激活函数不同,我们可供选择的损失函数非常少。然而,损失函数的选择取决于我们要用模型解决的问题类型。

例如,在分类问题中,我们应该使用可以衡量预测类与实际类之间差异的损失函数。

损失函数

对于分类问题,我们将使用神经网络模型来解决,分类交叉熵损失函数是最佳候选。在 CNTK 中,它被实现为cross_entropy_with_softmax,可以从cntk.losses包导入,如下所示:

label= input_variable(3)
loss = cross_entropy_with_softmax(z, label)

指标

有了神经网络模型的结构和要应用的损失函数,我们就具备了开始制定优化深度学习模型的方法的所有要素。但是,在深入研究这一点之前,我们应该了解指标。

cntk.metrics

CNTK 有一个名为cntk.metrics的包,我们可以从中导入我们要使用的指标。当我们构建分类模型时,我们将使用分类错误矩阵,该矩阵将生成 0 到 1 之间的数字。0 到 1 之间的数字表示正确预测的样本的百分比 -

首先,我们需要从cntk.metrics包导入指标-

from cntk.metrics import classification_error
error_rate = classification_error(z, label)

上面的函数实际上需要神经网络的输出和期望的标签作为输入。

CNTK - 训练神经网络

在这里,我们将了解如何在 CNTK 中训练神经网络。

在 CNTK 中训练模型

在上一节中,我们定义了深度学习模型的所有组件。现在是时候训练它了。正如我们之前讨论的,我们可以结合使用learnertrainer在 CNTK 中训练 NN 模型。

选择学习者并设置培训

在本节中,我们将定义学习者。CNTK 提供了多种学习器可供选择。对于我们在前面部分中定义的模型,我们将使用随机梯度下降(SGD)学习器

为了训练神经网络,让我们在以下步骤的帮助下配置学习器训练器-

步骤 1 - 首先,我们需要从cntk.lerners包中导入sgd函数。

from cntk.learners import sgd

步骤 2 - 接下来,我们需要从cntk.train .trainer 包中导入Trainer函数。

from cntk.train.trainer import Trainer

步骤 3 - 现在,我们需要创建一个学习者它可以通过调用sgd函数并提供模型参数和学习率值来创建。

learner = sgd(z.parametrs, 0.01)

步骤 4 - 最后,我们需要初始化训练器。必须提供网络、损失度量的组合以及学习器

trainer = Trainer(z, (loss, error_rate), [learner])

控制优化速度的学习率应该是 0.1 到 0.001 之间的小数字。

选择学习者并设置培训 - 完整示例

from cntk.learners import sgd
from cntk.train.trainer import Trainer
learner = sgd(z.parametrs, 0.01)
trainer = Trainer(z, (loss, error_rate), [learner])

将数据输入训练器

一旦我们选择并配置了训练器,就可以加载数据集了。我们已将iris数据集保存为 . CSV文件,我们将使用名为pandas的数据整理包来加载数据集。

从 .CSV 文件加载数据集的步骤

步骤 1 - 首先,我们需要导入pandas包。

from import pandas as pd

步骤 2 - 现在,我们需要调用名为read_csv的函数来从磁盘加载 .csv 文件。

df_source = pd.read_csv(‘iris.csv’, names = [‘sepal_length’, ‘sepal_width’, 
‘petal_length’, ‘petal_width’, index_col=False)

加载数据集后,我们需要将其拆分为一组特征和一个标签。

将数据集拆分为特征和标签的步骤

步骤 1 - 首先,我们需要从数据集中选择所有行和前四列。可以使用iloc函数来完成。

x = df_source.iloc[:, :4].values

步骤 2 - 接下来我们需要从 iris 数据集中选择物种列。我们将使用values属性来访问底层的numpy数组。

x = df_source[‘species’].values

将物种列编码为数字向量表示的步骤

正如我们之前讨论的,我们的模型基于分类,它需要数字输入值。因此,这里我们需要将物种列编码为数字向量表示。让我们看看执行步骤 -

步骤 1 - 首先,我们需要创建一个列表表达式来迭代数组中的所有元素。然后在 label_mapping 字典中查找每个值。

label_mapping = {‘Iris-Setosa’ : 0, ‘Iris-Versicolor’ : 1, ‘Iris-Virginica’ : 2}

步骤 2 - 接下来,将转换后的数值转换为 one-hot 编码向量。我们将使用one_hot函数,如下所示 -

def one_hot(index, length):
result = np.zeros(length)
result[index] = 1
return result

步骤 3 - 最后,我们需要将转换后的列表转换为numpy数组。

y = np.array([one_hot(label_mapping[v], 3) for v in y])

检测过度拟合的步骤

当您的模型记住样本但无法从训练样本中推断出规则时,这种情况就是过度拟合。借助以下步骤,我们可以检测模型的过度拟合 -

步骤 1 - 首先,从sklearn包中,从model_selection模块导入train_test_split函数。

from sklearn.model_selection import train_test_split

步骤 2 - 接下来,我们需要使用特征 x 和标签 y 调用 train_test_split 函数,如下 -

x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0-2, 
stratify=y)

我们将 test_size 指定为 0.2,以留出总数据的 20%。

label_mapping = {‘Iris-Setosa’ : 0, ‘Iris-Versicolor’ : 1, ‘Iris-Virginica’ : 2}

将训练集和验证集提供给我们的模型的步骤

步骤 1 - 为了训练我们的模型,首先,我们将调用train_minibatch方法。然后给它一个字典,将输入数据映射到我们用来定义神经网络及其相关损失函数的输入变量。

trainer.train_minibatch({ features: X_train, label: y_train})

步骤 2 - 接下来,使用以下 for 循环调用train_minibatch -

for _epoch in range(10):
trainer.train_minbatch ({ feature: X_train, label: y_train})
print(‘Loss: {}, Acc: {}’.format(
trainer.previous_minibatch_loss_average,
trainer.previous_minibatch_evaluation_average))

将数据输入训练器 - 完整示例

from import pandas as pd
df_source = pd.read_csv(‘iris.csv’, names = [‘sepal_length’, ‘sepal_width’, ‘petal_length’, ‘petal_width’, index_col=False)
x = df_source.iloc[:, :4].values
x = df_source[‘species’].values
label_mapping = {‘Iris-Setosa’ : 0, ‘Iris-Versicolor’ : 1, ‘Iris-Virginica’ : 2}
def one_hot(index, length):
result = np.zeros(length)
result[index] = 1
return result
y = np.array([one_hot(label_mapping[v], 3) for v in y])
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0-2, stratify=y)
label_mapping = {‘Iris-Setosa’ : 0, ‘Iris-Versicolor’ : 1, ‘Iris-Virginica’ : 2}
trainer.train_minibatch({ features: X_train, label: y_train})
for _epoch in range(10):
trainer.train_minbatch ({ feature: X_train, label: y_train})
print(‘Loss: {}, Acc: {}’.format(
trainer.previous_minibatch_loss_average,
trainer.previous_minibatch_evaluation_average))

衡量神经网络的性能

为了优化我们的神经网络模型,每当我们通过训练器传递数据时,它都会通过我们为训练器配置的指标来衡量模型的性能。训练期间神经网络模型性能的这种衡量是在训练数据上进行的。但另一方面,为了对模型性能进行全面分析,我们还需要使用测试数据。

因此,为了使用测试数据测量模型的性能,我们可以在训练器上调用test_minibatch方法,如下所示 -

trainer.test_minibatch({ features: X_test, label: y_test})

使用 NN 进行预测

一旦训练了深度学习模型,最重要的是使用它进行预测。为了从上面训练的神经网络进行预测,我们可以遵循给定的步骤 -

步骤 1 - 首先,我们需要使用以下函数从测试集中选择一个随机项目 -

np.random.choice

步骤2 - 接下来,我们需要使用sample_index从测试集中选择样本数据。

步骤 3 - 现在,为了将 NN 的数字输出转换为实际标签,请创建一个反向映射。

步骤 4 - 现在,使用选定的样本数据。通过调用 NN z 作为函数来进行预测。

步骤 5 - 现在,一旦获得预测输出,就将具有最高值的神经元的索引作为预测值。可以通过使用numpy包中的np.argmax函数来完成。

步骤 6 - 最后,使用inverted_mapping将索引值转换为真实标签。

使用 NN 进行预测 - 完整示例

sample_index = np.random.choice(X_test.shape[0])
sample = X_test[sample_index]
inverted_mapping = {
   1:’Iris-setosa’,
   2:’Iris-versicolor’,
   3:’Iris-virginica’
}
prediction = z(sample)
predicted_label = inverted_mapping[np.argmax(prediction)]
print(predicted_label)

输出

训练上述深度学习模型并运行后,您将得到以下输出 -

Iris-versicolor

CNTK - 内存中和大型数据集

在本章中,我们将学习如何使用 CNTK 中的内存数据集和大型数据集。

使用小内存数据集进行训练

当我们谈论将数据输入 CNTK 训练器时,可以有很多方法,但这取决于数据集的大小和数据的格式。数据集可以是内存中的小型数据集,也可以是大型数据集。

在本节中,我们将使用内存数据集。为此,我们将使用以下两个框架 -

  • 麻木
  • pandas

使用 Numpy 数组

在这里,我们将使用 CNTK 中基于 numpy 的随机生成的数据集。在此示例中,我们将模拟二元分类问题的数据。假设我们有一组具有 4 个特征的观察结果,并希望使用深度学习模型预测两个可能的标签。

实施例

为此,首先我们必须生成一组标签,其中包含我们想要预测的标签的单热向量表示。可以通过以下步骤来完成 -

步骤 1 - 导入numpy包如下 -

import numpy as np
num_samples = 20000

步骤 2 - 接下来,使用np.eye函数生成标签映射,如下 -

label_mapping = np.eye(2)

步骤 3 - 现在通过使用np.random.choice函数,收集 20000 个随机样本,如下所示 -

y = label_mapping[np.random.choice(2,num_samples)].astype(np.float32)

步骤 4 - 现在最后通过使用 np.random.random 函数,生成随机浮点值数组,如下 -

x = np.random.random(size=(num_samples, 4)).astype(np.float32)

一旦我们生成了一个随机浮点值数组,我们需要将它们转换为 32 位浮点数,以便它可以匹配 CNTK 期望的格式。让我们按照以下步骤来执行此操作 -

步骤 5 - 从 cntk.layers 模块导入密集层和顺序层函数,如下 -

from cntk.layers import Dense, Sequential

步骤 6 - 现在,我们需要导入网络中各层的激活函数。让我们导入sigmoid作为激活函数 -

from cntk import input_variable, default_options
from cntk.ops import sigmoid

步骤 7 - 现在,我们需要导入损失函数来训练网络。让我们导入binary_cross_entropy作为损失函数 -

from cntk.losses import binary_cross_entropy

步骤 8 - 接下来,我们需要定义网络的默认选项。在这里,我们将提供sigmoid激活函数作为默认设置。此外,使用顺序层函数创建模型,如下所示 -

with default_options(activation=sigmoid):
model = Sequential([Dense(6),Dense(2)])

步骤 9 - 接下来,使用 4 个输入特征初始化input_variable作为网络的输入。

features = input_variable(4)

步骤 10 - 现在,为了完成它,我们需要将特征变量连接到神经网络。

z = model(features)

所以,现在我们有了一个神经网络,在以下步骤的帮助下,让我们使用内存数据集训练它 -

步骤 11 - 为了训练这个神经网络,首先我们需要从cntk.learners模块导入学习器。我们将导入sgd learner,如下所示 -

from cntk.learners import sgd

步骤 12 - 与此同时,还从cntk.logging模块导入ProgressPrinter 。

from cntk.logging import ProgressPrinter
progress_writer = ProgressPrinter(0)

步骤 13 - 接下来,为标签定义一个新的输入变量,如下 -

labels = input_variable(2)

步骤 14 - 为了训练 NN 模型,接下来,我们需要使用binary_cross_entropy函数定义损失。另外,提供模型 z 和标签变量。

loss = binary_cross_entropy(z, labels)

步骤 15 - 接下来,初始化sgd学习器,如下所示 -

learner = sgd(z.parameters, lr=0.1)

步骤 16 - 最后,调用损失函数的训练方法。另外,为其提供输入数据、sgd学习器和Progress_printer。 -

training_summary=loss.train((x,y),parameter_learners=[learner],callbacks=[progress_writer])

完整的实现示例

import numpy as np
num_samples = 20000
label_mapping = np.eye(2)
y = label_mapping[np.random.choice(2,num_samples)].astype(np.float32)
x = np.random.random(size=(num_samples, 4)).astype(np.float32)
from cntk.layers import Dense, Sequential
from cntk import input_variable, default_options
from cntk.ops import sigmoid
from cntk.losses import binary_cross_entropy
with default_options(activation=sigmoid):
   model = Sequential([Dense(6),Dense(2)])
features = input_variable(4)
z = model(features)
from cntk.learners import sgd
from cntk.logging import ProgressPrinter
progress_writer = ProgressPrinter(0)
labels = input_variable(2)
loss = binary_cross_entropy(z, labels)
learner = sgd(z.parameters, lr=0.1)
training_summary=loss.train((x,y),parameter_learners=[learner],callbacks=[progress_writer])

输出

Build info:
     Built time: *** ** **** 21:40:10
     Last modified date: *** *** ** 21:08:46 2019
     Build type: Release
     Build target: CPU-only
     With ASGD: yes
     Math lib: mkl
     Build Branch: HEAD
     Build SHA1:ae9c9c7c5f9e6072cc9c94c254f816dbdc1c5be6 (modified)
     MPI distribution: Microsoft MPI
     MPI version: 7.0.12437.6
-------------------------------------------------------------------
average   since   average   since examples
loss      last    metric    last
------------------------------------------------------
Learning rate per minibatch: 0.1
1.52      1.52      0         0     32
1.51      1.51      0         0     96
1.48      1.46      0         0    224
1.45      1.42      0         0    480
1.42       1.4      0         0    992
1.41      1.39      0         0   2016
1.4       1.39      0         0   4064
1.39      1.39      0         0   8160
1.39      1.39      0         0  16352

使用 Pandas 数据框

Numpy 数组所能包含的内容非常有限,也是最基本的数据存储方式之一。例如,单个 n 维数组可以包含单个数据类型的数据。但另一方面,对于许多现实世界的情况,我们需要一个可以处理单个数据集中多个数据类型的库。

名为 Pandas 的 Python 库之一可以更轻松地处理此类数据集。它引入了 DataFrame (DF) 的概念,并允许我们从 d 加载数据集