1
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 多分类问题
神经网络通常用于对数据进行分类。例如神经网络:
拍摄照片并将照片中的主题分类为 {狗,猫,马,其他}
拿一个句子来说,并对其元素的“词性”进行分类:{名词、动词、形容词}等。
这种类型的网络在其最后一层中将有多个单元。每个输出都与一个类别相关联。当输入示例应用于网络时,具有最高值的输出是预测的类别。如果将输出应用于 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)
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}")
2.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)
在上面,决策边界显示了模型如何划分输入空间。这个非常简单的模型在对训练数据进行分类时没有遇到任何问题。它是如何做到这一点的?让我们更详细地看一下网络。
Layer1
下面,我们将从模型中提取经过训练的权重,并使用它来绘制每个网络单元的函数。再往下,对结果有更详细的解释。您无需了解这些详细信息即可成功使用神经网络,但对各层如何组合以解决分类问题有更多的直觉可能会有所帮助。
# 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)
上面这些图显示了网络第一层中单元 0 和 1 的功能。输入为 (x0,x1) 在轴上。单元的输出由背景的颜色表示。这由每个图表右侧的颜色条表示。请注意,由于这些单元使用 ReLu,因此输出不一定介于 0 和 1 之间,在本例中,其峰值大于 20。此图中的等值线显示了输出之间的过渡点
为零和非零。回想一下 ReLu 的图形:Image 图形中的等值线是 ReLu 中的拐点。
单元 0 已将类 0 和 1 与类 2 和 3 分开。行左侧的点(类 0 和 1)将输出零,而右侧的点将输出大于零的值。
单元 1 已将 0 类和 2 类与类 1 和 3 分开。线上方的点(类 0 和 2 )将输出零,而下方的点将输出大于零的值。让我们看看下一层是如何实现的!
Layer2
# 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])))
这些图中的点是第一层翻译的训练示例。一种思考方式是,第一层创建了一组新的特征,供第二层评估。这些图中的轴是前一层的输出,和。如上所述,0 类和 1 类(绿色和蓝色)具有=0而 1 类和 2 类(蓝色和绿色)有=0。同样,背景颜色的强度表示最高值。
单元 0 将生成 (0,0) 附近的值的最大值,其中已映射类 0(蓝色)。
单元 1 在选择类 1(绿色)的左上角产生其最高值。
单元 2 面向 3 类(橙色)所在的右下角。
单元 3 在右上角产生最高值,选择我们的最终类别(紫色)。
从图表中不明显的另一个方面是,这些值在单元之间得到了协调。对于一个单位来说,仅仅为它所选择的类别产生最大值是不够的,它还必须是该类别中所有单位中点的最高值。这是通过隐含的 softmax 函数完成的,该函数是损失函数 (SparseCategoricalCrossEntropy) 的一部分。与其他激活函数不同,softmax 适用于所有输出。
您可以在知道每个单元详细信息的情况下成功使用神经网络。