继二分类 后,通过学习 nn.CrossEntropyLoss()
、softmax()
、argmax()
,我尝试实现了下多分类模型基本工作流程。本博文主要用于整理个人的知识框架,希望也能帮到大家。如有不足,欢迎留言。🙏
运行环境:https://colab.google/
数据准备 准备数据集 1 2 3 4 5 6 7 import torchimport matplotlib.pyplot as pltfrom sklearn.datasets import make_blobsfrom sklearn.model_selection import train_test_splitX_blob, y_blob = make_blobs(n_samples = 1000 , n_features = 2 , centers = 4 , cluster_std = 1.5 , random_state = 666 )
make_blobs
make_blobs 是 Scikit-learn 中用于生成聚类算法测试数据的函数。它能够生成多类别的高斯分布数据集,用于模拟聚类算法的数据集。
n_samples:生成的样本总数,即生成的数据点个数;
n_features:生成的样本的特征数,即维度;
centers:生成的类别数,或者说簇的个数,即数据点围绕几个中心点分布;
random_state:随机数种子,用于控制生成的数据集的随机性,相同的随机数种子会生成相同的数据集;
cluster_std:用于生成聚类数据集时设置聚类的标准差,决定了数据点在每个聚类中的分布紧密程度。标准差越小,数据点越靠近聚类中心,聚类之间的距离越小。
1 2 3 X_blob = torch.from_numpy(X_blob).type (torch.float ) y_blob = torch.from_numpy(y_blob).type (torch.LongTensor)
划分数据集 1 X_blob_train, X_blob_test, y_blob_train, y_blob_test = train_test_split(X_blob, y_blob, test_size = 0.2 , random_state = 888 )
可视化 1 2 3 4 5 6 plt.figure(figsize = (10 , 7 )) plt.scatter(x = X_blob[:,0 ], y = X_blob[:,1 ], c = y_blob, cmap = plt.cm.RdYlBu) device = "cuda" if torch.cuda.is_available() else "cpu" -->如下图
建立模型 模型 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 from torch import nnclass BlobModel (nn.Module): def __init__ (self, input_features, output_features, hidden_units = 8 ): super ().__init__() self.linear_layer_stack = nn.Sequential( nn.Linear(in_features = input_features, out_features = hidden_units), nn.ReLU(), nn.Linear(in_features = hidden_units, out_features = output_features), ) def forward (self, x ): return self.linear_layer_stack(x)
hidden_units
def _init _(self, input_features, output_features, hidden_units = 8):
hidden_units相当于一个中介,进行模型内部的变量传递。
这个参数决定了神经网络的复杂度和性能,隐藏层中的神经元数量越多,神经网络就越复杂,可以学习更复杂的模式和特征。
self.linear_layer_stack = nn.Sequential()
将多个nn.Linear() 和 ReLU() 封装在函数内部。省去return时的嵌套处理
声明模型对象 1 2 3 4 5 6 model_multiclass = BlobModel(input_features = 2 , output_features = 4 ).to(device) torch.manual_seed(666 ) epochs = 500 X_blob_train, y_blob_train, X_blob_test, y_blob_test = X_blob_train.to(device), y_blob_train.to(device), X_blob_test.to(device), y_blob_test.to(device)
损失函数和优化器 1 2 3 4 5 loss_fn = nn.CrossEntropyLoss() optimizer = torch.optim.SGD(model_multiclass.parameters(), lr = 0.1 )
nn.CrossEntropyLoss()
nn.CrossEntropyLoss()
是PyTorch中用于计算交叉熵损失的函数。[^1]
通常用于训练分类模型时,计算预测类别概率与真实类别标签之间的差异。
H(p, q)
值越小,交叉熵也越小,q与p更为接近。
如下图所示:[^2]
训练模型 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 for epoch in range (epochs): model_multiclass.train() y_logits = model_multiclass(X_blob_train) y_pred = torch.softmax(y_logits, dim = 1 ).argmax(dim = 1 ) loss = loss_fn(y_logits, y_blob_train) acc = accuracy_fn(y_true = y_blob_train, y_pred = y_pred) optimizer.zero_grad() loss.backward() optimizer.step() model_multiclass.eval () with torch.inference_mode(): test_logits = model_multiclass(X_blob_test) test_pred = torch.softmax(test_logits, dim = 1 ).argmax(dim = 1 ) test_loss = loss_fn(test_logits, y_blob_test) test_acc = accuracy_fn(y_true = y_blob_test, y_pred = test_pred) print (f"Epoch:{epoch} | Loss:{loss:.4 f} , ACC:{acc:.2 f} % | Test Loss:{test_loss:.4 f} , Test acc:{test_acc:.2 f} %" )
softmax
Softmax
函数是一种常用的激活函数,通常用于神经网络模型中的多类别分类任务;
它将一个包含数字的向量转换为概率向量,其中每个值的概率与向量中每个值的相对大小成比例。该函数将返回一个 位于范围(0, 1)内 包含概率值的张量 y_pred_probs
,其中每一行的和都为 1。
在这个例子中,y_logits
是模型的输出,dim = 1 表示在第二个维度上进行 softmax 计算。
softmax 与 sigmoid 的区别
1 输入不同:
sigmoid 应用于二分类,输入的是一维数值;而 softmax 应用于多分类,输入的是二维数组
2 输出不同
sigmoid 输出一维数组,且数组元素位于 0 ~ 1 范围内;
softmax 输出二维数组,数组元素位于 0 ~ 1 范围内,元素含义表示 每个类别的概率,且每行和为1
argmax
函数用于返回 张量中指定维度上的最大值的索引 (即哪一类)
1 2 3 4 5 6 7 8 9 --> Epoch:492 | Loss:0.2597 , ACC:86.25 % | Test Loss:0.2141 , Test acc:91.00 % Epoch:493 | Loss:0.2592 , ACC:87.50 % | Test Loss:0.2080 , Test acc:92.50 % Epoch:494 | Loss:0.2593 , ACC:86.12 % | Test Loss:0.2136 , Test acc:91.50 % Epoch:495 | Loss:0.2589 , ACC:87.50 % | Test Loss:0.2078 , Test acc:92.50 % Epoch:496 | Loss:0.2589 , ACC:86.50 % | Test Loss:0.2132 , Test acc:91.50 % Epoch:497 | Loss:0.2585 , ACC:87.38 % | Test Loss:0.2077 , Test acc:92.50 % Epoch:498 | Loss:0.2585 , ACC:86.62 % | Test Loss:0.2128 , Test acc:91.50 % Epoch:499 | Loss:0.2582 , ACC:87.38 % | Test Loss:0.2075 , Test acc:92.50 %
发现 Test acc 达到最高后会下降
学习率太高,步子迈的太大,在最高值附近来回跳
注意:
这里不是过拟合,过拟合是指,模型在训练数据上表现良好,但在测试的数据上表现不佳。过拟合可能会导致模型无法泛化到新的数据集上,因为模型在训练数据集上学习到了噪声而不是信号。
reference [^1]: 维基百科 交叉熵 相关 [^2]: https://zhuanlan.zhihu.com/p/98785902 以及 评论区 杨子江 解答