1.1目标
在这个实验室里,你将探索一个使用神经网络进行多类分类的例子。
1.2工具
您将使用一些打印例程。这些存储在此目录中的lab_utils_multiclass_TF.py中。
import numpy as np
import matplotlib.pyplot as plt
%matplotlib widget
from sklearn.datasets import make_blobs
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
np.set_printoptions(precision=2)
from lab_utils_multiclass_TF import *
import logging
logging.getLogger("tensorflow").setLevel(logging.ERROR)
tf.autograph.set_verbosity(0)
2.0多类分类
神经网络通常用于对数据进行分类。例如神经网络:
- 拍摄照片并将照片中的主题分类为{狗、猫、马、其他}
- 取一个句子,对其成分的词性进行分类:{名词、动词、形容词等。}
这种类型的网络在其最后一层将具有多个单元。每个输出都与一个类别相关联。当输入示例应用于网络时,具有最高值的输出是预测的类别。如果将输出应用于softmax函数,则softmax的输出将提供输入在每个类别中的概率。
在这个实验室中,您将看到一个在Tensorflow中构建多类网络的示例。然后我们将看看神经网络是如何进行预测的。
让我们从创建一个四类数据集开始。
2.1准备和可视化我们的数据
我们将使用Scikit Learn 的 make_blobs函数制作一个具有4个类别的训练数据集,如下图所示。
# make 4-class dataset for classification
classes = 4
m = 100
centers = [[-5, 2], [-2, -2], [1, 2], [5, -2]]
std = 1.0
X_train, y_train = make_blobs(n_samples=m, centers=centers, cluster_std=std,random_state=30)
这段代码的含义是生成一个用于分类任务的数据集,具体解释如下:
classes = 4
:
- 定义了数据集中的类别数量为 4。
m = 100
:
- 定义了数据集中样本的总数为 100。
centers = [[-5, 2], [-2, -2], [1, 2], [5, -2]]
:
- 定义了每个类别的中心点坐标,这里有 4 个类别,分别对应 4 个中心点坐标。
std = 1.0
:
- 定义了数据集中样本点的标准差,即控制样本点在中心点附近的分布范围。
X_train, y_train = make_blobs(n_samples=m, centers=centers, cluster_std=std, random_state=30)
:
- 使用
make_blobs
函数生成符合设定参数的聚类数据。n_samples
参数指定了生成的样本数量为 m。centers
参数指定了每个类别的中心点坐标。cluster_std
参数指定了每个类别中样本点的标准差。random_state
参数是随机种子,通过设置相同的 random_state 参数,可以确保每次运行生成的随机结果是相同的,从而方便实验复现和结果验证。最终,X_train 是生成的特征数据,y_train 是对应的标签数据,用于训练一个分类模型。这段代码的目的是生成一个具有 4个类别的聚类数据集,用于进行分类模型的训练和评估。
plt_mc(X_train,y_train,classes, centers, std=std)
每个点表示一个训练示例。轴(x0,x1)是输入,颜色表示与示例相关联的类。一旦训练好,模型将呈现一个新的例子,(x0,x1),并将预测类别。
在生成时,该数据集代表了许多现实世界中的分类问题。有几个输入特性(x0,…,xn)和几个输出类别。该模型被训练为使用输入特征来预测正确的输出类别。
# show classes in data set
print(f"unique classes {np.unique(y_train)}")
# show how classes are represented
print(f"class representation {y_train[:10]}")
# show shapes of our dataset
print(f"shape of X_train: {X_train.shape}, shape of y_train: {y_train.shape}")
输出:
unique classes [0 1 2 3]
class representation [3 3 3 0 3 3 3 3 2 0]
shape of X_train: (100, 2), shape of y_train: (100,)
2.2模型
该实验室将使用如图所示的两层网络。与二进制分类网络不同,该网络有四个输出,每个类一个。给定一个输入示例,具有最高值的输出是输入的预测类。
以下是如何在Tensorflow中构建此网络的示例。请注意,输出层使用线性激活,而不是softmax激活。虽然可以在输出层中包括softmax,但如果在训练期间将线性输出传递给损失函数,则在数值上更稳定。如果该模型用于预测概率,则可以在该点应用softmax。
tf.random.set_seed(1234) # applied to achieve consistent results
model = Sequential(
[
Dense(2, activation = 'relu', name = "L1"),
Dense(4, activation = 'linear', name = "L2")
]
)
下面的语句编译和训练网络。将from_logits=True设置为损失函数的参数指定输出激活是线性的,而不是softmax。
model.compile(
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
optimizer=tf.keras.optimizers.Adam(0.01),
)
model.fit(
X_train,y_train,
epochs=200
)
通过训练模型,我们可以看到模型是如何对训练数据进行分类的。
plt_cat_mc(X_train, y_train, model, classes)
上面,决策边界显示了模型是如何划分输入空间的。这个非常简单的模型对训练数据进行分类没有问题。它是如何做到这一点的?让我们更详细地了解网络。
下面,我们将从模型中提取训练后的权重,并使用它来绘制每个网络单元的函数。再往下看,对结果有更详细的解释。你不需要知道这些细节就可以成功地使用神经网络,但它可能有助于获得更多关于层如何组合来解决分类问题的直觉。
# gather the trained parameters from the first layer
l1 = model.get_layer("L1")
W1,b1 = l1.get_weights()
# plot the function of the first layer
plt_layer_relu(X_train, y_train.reshape(-1,), W1, b1, classes)
有点看不懂,为啥会输出这样的结果???
继续往下看有解释
# gather the trained parameters from the output layer
l2 = model.get_layer("L2")
W2, b2 = l2.get_weights()
# create the 'new features', the training examples after L1 transformation
Xl2 = np.zeros_like(X_train)
Xl2 = np.maximum(0, np.dot(X_train,W1) + b1)
plt_output_layer_linear(Xl2, y_train.reshape(-1,), W2, b2, classes,
x0_rng = (-0.25,np.amax(Xl2[:,0])), x1_rng = (-0.25,np.amax(Xl2[:,1])))
有点看不懂,为啥会输出这样的结果???
继续往下看有解释
解释
Layer 1
这些图显示了网络第一层中单元0和1的功能。输入为(𝑥0,𝑥1)在轴上。该单元的输出由背景的颜色表示。这由每个图形右侧的颜色栏指示。请注意,由于这些单元使用ReLu,因此输出不一定在0和1之间,并且在这种情况下,在其峰值处大于20。该图中的轮廓线展示出了输出之间的过渡点,𝑎1𝑗为零且非零。回想ReLu的图形:图形中的等高线是ReLu中的拐点。
Layer1 Unit 0 已将类0和1与类2和3分离。线左侧的点(类0和1)将输出零,而右侧的点将输出大于零的值。
Layer1 Unit 1 将0和2类与1和3类分开。线上方的点(类0和2)将输出零,而下方的点将输出大于零的值。让我们在下一层中看看结果如何!
第2层,输出层
这些图中的点是由第一层翻译的训练示例。一种方法是,第一层创建了一组新的特征,供第二层进行评估。这些图中的轴是上一层的输出𝑎[1]0和𝑎[1]1。如上所述:
- 类别0(蓝色)有a[1]0=0,a[1]1=0
- 类别1(绿色)有a[1]0=0,a[1]1>0
- 类别2(橙色)有a[1]0>0,a[1]1=0
- 类别3(紫色)有a[1]0>0,a[1]1>0
同样,背景颜色的强度表示最高值。
- Layer1 Unit 0 将为(0,0)附近的值生成其最大值,其中类0(蓝色)已映射。
- Layer1 Unit 1 在左上角产生其最高值,选择类别1(绿色)。
- Layer1 Unit 2 的目标是3级(橙色)所在的右下角。
- Layer1 Unit 3 在右上角产生其最高值,选择我们的最终类别(紫色)。
从图表中不明显的另一个方面是,这些值在神经元之间进行了协调。在神经网络中,对于某个特定类别的数据点,在输出层中与该类别对应的神经元应该具有最大的输出值,并且这个输出值应该是该类别所有数据点的神经元输出值中最高的。这是通过作为损失函数(稀疏类别交叉熵)一部分的隐含softmax函数来实现的。与其他激活功能不同,softmax适用于所有输出。
你可以在不知道每个单元的细节的情况下成功地使用神经网络。希望这个例子能提供一些关于引擎盖下发生的事情的直觉。
祝贺
您已经学会了构建和操作用于多类分类的神经网络。
1 ↩︎