基于机器学习Tensor处理问题与MNIST

发布于:2025-07-27 ⋅ 阅读:(19) ⋅ 点赞:(0)

问题

1.问题1:为什么需要if __name__ == '__main__':?

2.问题2: 如果tensor有多个值比如x,如何转移x到cpu上

3.问题3: 探索其他指标的实现方法,例如precision, recall, f1-score?

方法

问题1:为什么需要if __name__ == '__main__':?

if__name__ == '__main__':的作用一个python文件通常有两种使用方法,第一是作为脚本直接执行,第二是 import 到其他的 python 脚本中被调用(模块重用)执行。因此 if __name__ == 'main': 的作用就是控制这两种情况执行代码的过程,在 if __name__ == 'main': 下的代码只有在第一种情况下(即文件作为脚本直接执行)才会被执行,而 import 到其他脚本中是不会被执行的。__name__ == '__main__' 就表示在当前文件中,可以在if __name__ == '__main__':条件下写入测试代码,如此可以避免测试代码在模块被导入后执行。

问题2: 如果tensor有多个值比如x,如何转移x到cpu

Tensor的含义Tensor,又名张量。如果一个物理量,在物体的某个位置上只是一个单值,那么就是普通的标量,比如密度。如果它在同一个位置、从不同的方向上看,有不同的值,而且这个数恰好可以用矩阵乘观察方向来算出来,就是张量。几何代数中定义的张量是基于向量和矩阵的推广,通俗一点理解的话,我们可以将标量视为零阶张量,矢量视为一阶张量,那么矩阵就是二阶张量。Tensor转换Torch定义了七种CPU tensor类型和八种GPU tensor类型。从工程角度来讲,可简单地认为它就是一个数组,且支持高效的科学计算。它可以是一个数(标量)、一维数组(向量)、二维数组(矩阵)和更高维的数组(高阶数据)。Tensor可以存放在不同的device(cpu/gpu):cpu –> gpu,使用data.cuda()。gpu –> cpu,使用data.cpu()。

例如

import torch

# 创建一个张量

tensor = torch.randn(3, 3)  # 一个3x3的随机张量

# 将张量移动到 CPU

tensor_on_cpu = tensor.to('cpu')

# 检查移动后的设备

print(tensor_on_cpu.device)

问题3: 探索其他指标的实现方法,例如precision, recall, f1-score?

1.精确度(Precision):精确度是指被分类为正类别的样本中实际为正类别的比例。精确度可用于衡量模型在正类别上的准确性。

2.召回率(Recall):召回率是指实际为正类别的样本中被正确分类为正类别的比例。召回率可用于衡量模型对正类别样本的覆盖程度。

例如

from sklearn.metrics import precision_score, recall_score, f1_score

true_labels = [1, 0, 1, 1, 0, 0]

predicted_labels = [1, 1, 1, 0, 0, 1]

precision = precision_score(true_labels, predicted_labels, average='weighted')

recall = recall_score(true_labels, predicted_labels, average='weighted')

f1 = f1_score(true_labels, predicted_labels, average='weighted')

print(f'Precision: {precision}')

print(f'Recall: {recall}')

print(f'F1 Score: {f1}')

import torch
import matplotlib.pyplot as plt
from torch.optim import SGD
from torch import nn
from torchvision import datasets
from torchvision.transforms import ToTensor
from torch.utils.data import DataLoader
#问题1:为什么需要if __name__ == '__main__':??
if __name__ == '__main__':
    device = (
    'cuda'
    if torch.cuda.is_available()
    else 'cpu'
)
    print(device)
    train_ds = datasets.MNIST(
        root='data', # 数据集下载的路径
        download=True,
        train=True, # True表示训练集 False表示测试集
        transform=ToTensor(), # ToTensor()对象, 转换
    )
    test_ds = datasets.MNIST(
        root='data',
        download=True,
        train=False,
        transform=ToTensor(),
    )
    batch_size = 256
    train_dataloader = DataLoader(
        dataset=train_ds, # 对哪个数据集进行切分
        batch_size=batch_size, 
        num_workers=8,
    )
    test_dataloader = DataLoader(
        dataset=test_ds,
        batch_size=batch_size,
        num_workers=8, # 可选参数,
    )
    class MyNet(nn.Module):
        def __init__(self):
            super().__init__()
            self.fc1 = nn.Linear(
                in_features= 784, # 前一层的神经元个数
                out_features= 512, # 当前层的神经元个数
            )
            self.fc2 = nn.Linear(
                in_features=512,
                out_features=10,
            )
        def forward(self, x):
            x = torch.flatten(x, start_dim=1)  # 向上方向键 [32, 784]
            x = self.fc1(x)
            out = self.fc2(x)
            return out
    net = MyNet().to(device)
    loss_fn = nn.CrossEntropyLoss()
    optimizer = SGD(net.parameters(), lr=1e-3)
    losses = []
    def train(dataloader, net, loss_fn, optimizer):
        batch_num = len(dataloader)
        net.train() 
        for batch_index, (X,y) in enumerate(dataloader):
            X, y = X.to(device), y.to(device)
            pred = net(X)
            loss = loss_fn(pred, y)
            loss.backward()
            optimizer.step()
            optimizer.zero_grad()
            losses.append(loss.item())
            if batch_index % 100 == 0:
                print(f'[{batch_index+1:>3d}/{batch_num}] loss: {loss.item()}')
    epoch_num = 1
    for t in range(epoch_num):
        print(f'Epoch {t+1}/{epoch_num}')
        train(train_dataloader, net, loss_fn, optimizer)       
    # 测试网络
    def test(dataloader, net, loss_fn):
        size = len(dataloader.dataset)
        correct = 0
        net.eval() 
        for batch_idx, (X,y) in enumerate(dataloader):
            X,y = X.to(device), y.to(device) 
            pred = net(X)
            batch_correct = (pred.argmax(1) == y).type(torch.float).sum().item()
            correct += batch_correct
#问题2: 如果tensor的shape不是1,那么怎么转移到CPU呢?
        acc = correct / size
        print(f'Accurac: {acc}')
        # 问题3: 探索其他指标的实现方法,例如precision, recall, f1-score
    test(test_dataloader, net, loss_fn)

输出:

结语

本次对实验中出现if __name__ == '__main__'报错的相关问题,知道了该代码只有在py文件作为脚本直接执行时才会被执行,而 import 到其他脚本中是不会被执行的,所以在调用脚本时需要输入调用。对于tensor转移到CPU上运行,对于单个张量可直接进行转移,多个张量可采用循环或列表推导式。关于提升MNIST数据集的准确率涉及到使用更复杂的模型、调整超参数、数据增强等方法。了解如何在 PyTorch 中实现训练和测试循环,包括使用交叉熵损失函数和随机梯度下降(SGD)优化器;如何在测试阶段计算准确率,并进一步学习如何计算其他指标,如精确度、召回率和 F1 分数,以综合评估模型性能。


网站公告

今日签到

点亮在社区的每一天
去签到