前言
前面我们搭建的无论是分类还是回归都只能预测一个标签,这显然效果很局限。下面我们想做到下面这两种效果:
- 多输出预测(回归):例如训练网络拟合北东天坐标转机体坐标的关系,输入是三坐标,输出也是三坐标
- 多标签分类:例如,输入图像数据,训练网络判断图片里面有猫,有狗,还是只有其中一种这样
【注】:在介绍pytorch的内置损失函数博客中已经介绍了pytorch的损失函数是支持这个功能的。
一、多输出预测(回归)
1 坐标数据生成
# 本示例演示如何使用 PyTorch 实现多标签回归模型。
import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
# 构建数据集
# 假设您有一些经纬高度和对应的地心地固坐标的数据
# 这里只是一个示例,您需要根据实际情况准备您自己的数据集
X = np.random.rand(100, 3) # 100个样本,每个样本有3个特征(经度、纬度、高度)
y = np.random.rand(100, 3) # 每个样本有3个目标值(地心地固坐标)
print('y:\n',y)

2 网络搭建训练预测
# 转换数据为 PyTorch 的 Tensor 类型
X_tensor = torch.tensor(X, dtype=torch.float32)
y_tensor = torch.tensor(y, dtype=torch.float32)
# 定义模型
class MultiLabelRegressionModel(nn.Module):
def __init__(self, input_size, output_size):
super(MultiLabelRegressionModel, self).__init__()
self.fc = nn.Linear(input_size, output_size)
def forward(self, x):
out = self.fc(x)
return out
# 初始化模型
input_size = 3 # 输入特征的数量
output_size = 3 # 输出目标值的数量
model = MultiLabelRegressionModel(input_size, output_size)
# 定义损失函数和优化器
criterion = nn.MSELoss() # 均方误差损失函数
optimizer = optim.SGD(model.parameters(), lr=0.01) # 随机梯度下降优化器
# 训练模型
num_epochs = 100
for epoch in range(num_epochs):
# Forward pass
outputs = model(X_tensor)
loss = criterion(outputs, y_tensor)
# Backward pass and optimization
optimizer.zero_grad()
loss.backward()
optimizer.step()
if (epoch+1) % 10 == 0:
print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')
# 测试模型
with torch.no_grad():
predicted = model(X_tensor).detach().numpy()
print("Predicted Values:")
print(predicted)
输出:

二、多标签分类
1 多标签数据生成
# 多标签分类示例: 在多标签分类任务中,每个样本可以属于多个类别。例如,一个图片分类任务中,一张图片可能同时包含猫、狗和鸟等多种物体。这种情况下,每个样本的标签可以用一个多维张量表示,其中每个元素代表一个类别,如果样本属于该类别则为1,否则为0。用pytorch搭建这个网络(给出生成的数据);显然这是多个二分类问题,最后层用sigmoid函数
import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
# 生成示例数据
num_samples_train = 1000
num_samples_test = 200
num_classes = 5
# 随机生成多标签分类示例数据
labels_multi_train = np.random.randint(2, size=(num_samples_train, num_classes))
print(f'labels_multi_train:\n{labels_multi_train}')
# 这里标签可以是多个类别,所以是一个二维数组,每一行代表一个样本,每一列代表一个类别,如果该样本属于该类别则为1,否则为0;因为损失函数不同,和多分类不同,这里就不用非要是一维数组了,二维数组才能够表示多标签分类的情况(与demo224)进行对比----后面demo223,224,225都要总结一下写到博客里
labels_multi_test = np.random.randint(2, size=(num_samples_test, num_classes))
features_train = torch.randn(num_samples_train, 3) # 假设有3个特征
print(f'features_train:\n{features_train}')
features_test = torch.randn(num_samples_test, 3)
print(f'features_test:\n{features_test}')


2 网络搭建训练
# 定义多标签分类网络
class MultiLabelClassifier(nn.Module):
def __init__(self, input_size, output_size):
super(MultiLabelClassifier, self).__init__()
self.fc = nn.Linear(input_size, output_size)
self.sigmoid = nn.Sigmoid() # 用于多标签分类任务的激活函数
def forward(self, x):
x = self.fc(x)
x = self.sigmoid(x)
return x
# 初始化网络和损失函数
model = MultiLabelClassifier(input_size=3, output_size=num_classes)
criterion = nn.BCELoss() # 二分类交叉熵损失函数
# torch.nn.BCEWithLogitsLoss() # BCELoss的改进版,将sigmoid和BCELoss合并到一起,可以提高数值稳定性,如果要用最后一层不要加sigmoid,输出值直接用线性输出,这个损失函数会自动加sigmoid进行优化,但最后的predict的时候要手动加sigmoid在判断概率选择类别。
optimizer = optim.Adam(model.parameters(), lr=0.01)
# 将示例数据转换为张量
features_train_tensor = features_train
labels_train_tensor = torch.tensor(labels_multi_train, dtype=torch.float32)
features_test_tensor = features_test
labels_test_tensor = torch.tensor(labels_multi_test, dtype=torch.float32)
# 训练模型
num_epochs = 50
for epoch in range(num_epochs):
# Forward pass
outputs = model(features_train_tensor)
loss = criterion(outputs, labels_train_tensor)
# Backward pass and optimization
optimizer.zero_grad()
loss.backward()
optimizer.step()
if (epoch+1) % 10 == 0:
print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')
print("训练完成!")
# 测试模型
with torch.no_grad():
model.eval()
outputs_test = model(features_test_tensor)
predicted_labels = (outputs_test > 0.5).float()
print(f'预测标签: {predicted_labels[0:5, :]}')
# 计算准确率
accuracy = (predicted_labels == labels_test_tensor).all(dim=1).float().mean().item()
print(f'模型准确率: {accuracy:.4f}')

总结
以上都只构建了一层网络,所以效果很差,这里只是做一个简单的记录而已。
1102

被折叠的 条评论
为什么被折叠?



