深度学习每周学习总结P4(猴痘识别)

  • 🍨 本文为🔗365天深度学习训练营 中的学习记录博客
  • 🍖 原作者:K同学啊 | 接辅导、项目定制

–来自百度网盘超级会员V5的分享

目录

    • 0. 总结
    • 1. 数据导入部分
    • 2. 划分数据集
    • 3. 模型构建部分
      • 3.1 模型构建
      • 3.2 公式推导
    • 4. 设置超参数
    • 5. 定义训练函数
    • 6. 定义测试函数
    • 7. 训练过程
    • 8. 结果可视化
    • 9.模型的保存及预测
      • 9.1 代码部分
      • 9.2 疑问解析

0. 总结

数据导入部分:本次数据导入没有使用torchvision自带的数据集,需要将原始数据进行处理包括数据导入,数据类型转换。

划分数据集:划定训练集测试集后,再使用torch.utils.data中的DataLoader()加载数据

模型构建部分:有两个部分一个初始化部分(init())列出了网络结构的所有层,比如卷积层池化层等。第二个部分是前向传播部分,定义了数据在各层的处理过程。

设置超参数:在这之前需要定义损失函数,学习率,以及根据学习率定义优化器(例如SGD随机梯度下降),用来在训练中更新参数,最小化损失函数。

定义训练函数:函数的传入的参数有四个,分别是设置好的DataLoader(),定义好的模型,损失函数,优化器。函数内部初始化损失准确率为0,接着开始循环,使用DataLoader()获取一个批次的数据,对这个批次的数据带入模型得到预测值,然后使用损失函数计算得到损失值。接下来就是进行反向传播以及使用优化器优化参数,梯度清零放在反向传播之前或者是使用优化器优化之后都是可以的,一般是默认放在反向传播之前。

定义测试函数:函数传入的参数相比训练函数少了优化器,只需传入设置好的DataLoader(),定义好的模型,损失函数。此外除了处理批次数据时无需再设置梯度清零、返向传播以及优化器优化参数,其余部分均和训练函数保持一致。

训练过程:定义训练次数,有几次就使用整个数据集进行几次训练,初始化四个空list分别存储每次训练及测试的准确率及损失。使用model.train()开启训练模式,调用训练函数得到准确率及损失。使用model.eval()将模型设置为评估模式,调用测试函数得到准确率及损失。接着就是将得到的训练及测试的准确率及损失存储到相应list中并合并打印出来,得到每一次整体训练后的准确率及损失。

结果可视化

模型的保存,调取及使用。在PyTorch中,通常使用 torch.save(model.state_dict(), ‘model.pth’) 保存模型的参数,使用 model.load_state_dict(torch.load(‘model.pth’)) 加载参数。

需要改进优化的地方:再保证整体流程没有问题的情况下,继续细化细节研究,比如一些函数的原理及作用,如何提升训练集准确率等问题。

1. 数据导入部分

import torch
import torch.nn as nn
import torchvision
from torchvision import transforms,datasets

import os,PIL,pathlib

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

device
device(type='cuda')
# 查看数据分类
import os,PIL,random,pathlib

data_dir = './data/mpox_recognize/'
data_dir = pathlib.Path(data_dir) # 使用pathlib.Path()函数将字符串类型的文件夹路径转换为pathlib.Path对象。

data_paths = list(data_dir.glob('*')) # 使用glob()方法获取data_dir路径下的所有文件路径,并以列表形式存储在data_paths中。
# classNames = [str(path).split('\\')[-1] for path in data_paths] # 通过split()函数对data_paths中的每个文件路径执行分割操作,获得各个文件所属的类别名称
# classNames = [str(path).split('\\')[2] for path in data_paths]
classNames = [path.parts[-1] for path in data_paths] # pathlib的.parts方法会返回路径各部分的一个元组
# classNames = [path.parts[2] for path in data_paths]
classNames
['Monkeypox', 'Others']
total_datadir = './data/mpox_recognize/'

# 关于transforms.Compose的更多介绍可以参考:https://blog.csdn.net/qq_38251616/article/details/124878863
train_transforms = transforms.Compose([
    transforms.Resize([224, 224]),  # 将输入图片resize成统一尺寸
    transforms.ToTensor(),          # 将PIL Image或numpy.ndarray转换为tensor,并归一化到[0,1]之间
    transforms.Normalize(           # 标准化处理-->转换为标准正太分布(高斯分布),使模型更容易收敛
        mean=[0.485, 0.456, 0.406], 
        std=[0.229, 0.224, 0.225])  # 其中 mean=[0.485,0.456,0.406]与std=[0.229,0.224,0.225] 从数据集中随机抽样计算得到的。
])

total_data = datasets.ImageFolder(total_datadir,transform=train_transforms)
total_data
Dataset ImageFolder
    Number of datapoints: 2142
    Root location: ./data/mpox_recognize/
    StandardTransform
Transform: Compose(
               Resize(size=[224, 224], interpolation=bilinear, max_size=None, antialias=warn)
               ToTensor()
               Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
           )

2. 划分数据集

# 划分数据集
train_size = int(0.8 * len(total_data))
test_size = len(total_data) - train_size
train_dataset,test_dataset = torch.utils.data.random_split(total_data,[train_size,test_size])
train_dataset,test_dataset
(<torch.utils.data.dataset.Subset at 0x24b70342d00>,
 <torch.utils.data.dataset.Subset at 0x24b70342a90>)
train_size,test_size
(1713, 429)
# 使用dataloader加载数据,并设置好基本的batch_size
batch_size = 32

train_dl = torch.utils.data.DataLoader(
    train_dataset,
    batch_size = batch_size,
    shuffle = True,
    num_workers = 1 # 用于数据加载的子进程数量。通常,将其设置为大于 0 的值可以加快数据加载速度,特别是当数据集很大时。默认值为 0,表示在主进程中加载数据。
)
test_dl = torch.utils.data.DataLoader(
    test_dataset,
    batch_size = batch_size,
    shuffle = True,
    num_workers = 1
)
for X,y in test_dl:
    print("Shape of X [N,C,H,W]: ",X.shape)
    print("Shape of y: ",y.shape,y.dtype)
    break
Shape of X [N,C,H,W]:  torch.Size([32, 3, 224, 224])
Shape of y:  torch.Size([32]) torch.int64

3. 模型构建部分

3.1 模型构建

import torch.nn.functional as F

class Network_bn(nn.Module):
    def __init__(self):
        super(Network_bn,self).__init__()
        self.conv1 = nn.Conv2d(in_channels = 3,out_channels = 12,kernel_size = 5,stride = 1,padding = 0)
        self.bn1 = nn.BatchNorm2d(12)
        self.conv2 = nn.Conv2d(in_channels = 12,out_channels = 12,kernel_size = 5,stride = 1,padding = 0)
        self.bn2 = nn.BatchNorm2d(12)
        self.pool = nn.MaxPool2d(2,2)
        self.conv3 = nn.Conv2d(in_channels = 12,out_channels = 24,kernel_size = 5,stride = 1,padding = 0)
        self.bn3 = nn.BatchNorm2d(24)
        self.conv4 = nn.Conv2d(in_channels = 24,out_channels = 24,kernel_size = 5,stride = 1,padding = 0)
        self.bn4 = nn.BatchNorm2d(24)
        self.dropout = nn.Dropout(p = 0.5)
        self.fc1 = nn.Linear(24*50*50,len(classNames))
    
    def forward(self,x):
        x = F.relu(self.bn1(self.conv1(x)))
        x = F.relu(self.bn2(self.conv2(x)))
        x = self.pool(x)
        x = F.relu(self.bn3(self.conv3(x)))
        x = F.relu(self.bn4(self.conv4(x)))
        x = self.pool(x)
        x = x.view(-1,24*50*50)
        x = F.relu(self.fc1(x))
        return x

print("Using {} device".format(device))

model = Network_bn().to(device)
model
Using cuda device





Network_bn(
  (conv1): Conv2d(3, 12, kernel_size=(5, 5), stride=(1, 1))
  (bn1): BatchNorm2d(12, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (conv2): Conv2d(12, 12, kernel_size=(5, 5), stride=(1, 1))
  (bn2): BatchNorm2d(12, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (pool): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  (conv3): Conv2d(12, 24, kernel_size=(5, 5), stride=(1, 1))
  (bn3): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (conv4): Conv2d(24, 24, kernel_size=(5, 5), stride=(1, 1))
  (bn4): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (dropout): Dropout(p=0.5, inplace=False)
  (fc1): Linear(in_features=60000, out_features=2, bias=True)
)

3.2 公式推导

3, 224, 224(输入数据)

-> 12, 220, 220(经过卷积层1)

-> 12, 216, 216(经过卷积层2)-> 12, 108, 108(经过池化层1)

-> 24, 104, 104(经过卷积层3)

-> 24, 100, 100(经过卷积层4)-> 24, 50, 50(经过池化层2)

-> 60000 -> num_classes(2)

计算公式:

卷积维度计算公式:

  • 高度方向: H o u t = ( H i n − K e r n e l _ s i z e + 2 × p a d d i n g ) s t r i d e + 1 H_{out} = \frac{\left(H_{in} - Kernel\_size + 2\times padding\right)}{stride} + 1 Hout=stride(HinKernel_size+2×padding)+1

  • 宽度方向: W o u t = ( W i n − K e r n e l _ s i z e + 2 × p a d d i n g ) s t r i d e + 1 W_{out} = \frac{\left(W_{in} - Kernel\_size + 2\times padding\right)}{stride} + 1 Wout=stride(WinKernel_size+2×padding)+1

  • 卷积层通道数变化:数据通道数为卷积层该卷积层定义的输出通道数,例如:self.conv1 = nn.Conv2d(3,64,kernel_size = 3)。在这个例子中,输出的通道数为64,这意味着卷积层使用了64个不同的卷积核,每个核都在输入数据上独立进行卷积运算,产生一个新的通道。需要注意,卷积操作不是在单独的通道上进行的,而是跨所有输入通道(本例中为3个通道)进行的,每个卷积核提供一个新的输出通道。

池化层计算公式:

  • 高度方向: H o u t = ( H i n + 2 × p a d d i n g H − d i l a t i o n H × ( k e r n e l _ s i z e H − 1 ) − 1 s t r i d e H + 1 ) H_{out} = \left(\frac{H_{in} + 2 \times padding_H - dilation_H \times (kernel\_size_H - 1) - 1}{stride_H} + 1 \right) Hout=(strideHHin+2×paddingHdilationH×(kernel_sizeH1)1+1)

  • 宽度方向: W o u t = ( W i n + 2 × p a d d i n g W − d i l a t i o n W × ( k e r n e l _ s i z e W − 1 ) − 1 s t r i d e W + 1 ) W_{out} = \left( \frac{W_{in} + 2 \times padding_W - dilation_W \times (kernel\_size_W - 1) - 1}{stride_W} + 1 \right) Wout=(strideWWin+2×paddingWdilationW×(kernel_sizeW1)1+1)

其中:

  • H i n H_{in} Hin W i n W_{in} Win 是输入的高度和宽度。
  • p a d d i n g H padding_H paddingH p a d d i n g W padding_W paddingW 是在高度和宽度方向上的填充量。
  • k e r n e l _ s i z e H kernel\_size_H kernel_sizeH k e r n e l _ s i z e W kernel\_size_W kernel_sizeW 是卷积核或池化核在高度和宽度方向上的大小。
  • s t r i d e H stride_H strideH s t r i d e W stride_W strideW 是在高度和宽度方向上的步长。
  • d i l a t i o n H dilation_H dilationH d i l a t i o n W dilation_W dilationW 是在高度和宽度方向上的膨胀系数。

请注意,这里的膨胀系数 $dilation \times (kernel_size - 1) $实际上表示核在膨胀后覆盖的区域大小。例如,一个 $3 \times 3 $ 的核,如果膨胀系数为2,则实际上它覆盖的区域大小为$ 5 \times 5 $(原始核大小加上膨胀引入的间隔)。

计算流程:

输入数据:( 3 ∗ 224 ∗ 224 3*224*224 3224224)

conv1计算:卷积核数12,输出的通道也为12。-> ( 12 ∗ 220 ∗ 220 ) (12*220*220) (12220220)
输出维度 = ( 224 − 5 + 2 × 0 ) 1 + 1 = 220 \text{输出维度} = \frac{\left(224 - 5 + 2 \times 0\right)}{1} + 1 = 220 输出维度=1(2245+2×0)+1=220

conv2计算:-> ( 12 ∗ 216 ∗ 216 ) (12*216*216) (12216216)
输出维度 = ( 220 − 5 + 2 × 0 ) 1 + 1 = 216 \text{输出维度} = \frac{\left(220 - 5 + 2 \times 0\right)}{1} + 1 = 216 输出维度=1(2205+2×0)+1=216

pool1计算:通道数不变,步长为2-> ( 12 ∗ 108 ∗ 108 ) (12*108*108) (12108108)
输出维度 = ( 216 + 2 × 0 − 1 × ( 2 − 1 ) − 1 2 + 1 ) = 107 + 1 = 108 \text{输出维度} = \left(\frac{216 + 2 \times 0 - 1 \times \left(2 - 1\right) - 1}{2} + 1 \right) = 107 +1 = 108 输出维度=(2216+2×01×(21)1+1)=107+1=108

conv3计算:-> ( 24 ∗ 104 ∗ 104 ) (24*104*104) (24104104)
输出维度 = ( 108 − 5 + 2 × 0 ) 1 + 1 = 104 \text{输出维度} = \frac{\left(108 - 5 + 2 \times 0\right)}{1} + 1 = 104 输出维度=1(1085+2×0)+1=104

conv4计算:-> ( 24 ∗ 100 ∗ 100 ) (24*100*100) (24100100)
输出维度 = ( 104 − 5 + 2 × 0 ) 1 + 1 = 100 \text{输出维度} = \frac{\left(104 - 5 + 2 \times 0\right)}{1} + 1 = 100 输出维度=1(1045+2×0)+1=100

pool2计算:-> ( 24 ∗ 50 ∗ 50 ) (24*50*50) (245050)
输出维度 = ( 100 + 2 × 0 − 1 × ( 2 − 1 ) − 1 2 + 1 ) = 49 + 1 = 50 \text{输出维度} = \left(\frac{100 + 2 \times 0 - 1 \times \left(2 - 1\right) - 1}{2} + 1 \right) = 49 +1 = 50 输出维度=(2100+2×01×(21)1+1)=49+1=50

flatten层:-> 60000 60000 60000

n u m _ c l a s s e s ( 2 ) num\_classes(2) num_classes(2)

4. 设置超参数

loss_fn = torch.nn.CrossEntropyLoss()
learn_rate = 1e-4
opt = torch.optim.SGD(model.parameters(),lr=learn_rate)

5. 定义训练函数

len(train_dl.dataset),len(train_dl),len(test_dl.dataset),len(test_dl)
(1713, 54, 429, 14)
# 训练循环
def train(dataloader,model,loss_fn,optimizer):
    size = len(dataloader.dataset) # 训练集的大小,一共1713张图片
    num_batches = len(dataloader) # 批次数目,54(1713/32)
    
    train_loss,train_acc = 0,0 # 初始化训练损失和正确率
    
    for X,y in dataloader: # 获取图片及其标签
        X,y = X.to(device),y.to(device)
        
        # 计算预测误差
        pred = model(X) # 网络输出
        loss = loss_fn(pred,y) # 计算网络输出和真实值之间的差距,targets为真实值,计算二者差值即为损失
        
        # 返乡传播
        optimizer.zero_grad() # grad属性归零
        loss.backward() # 反向传播
        optimizer.step() # 每一步自动更新
        
        # 记录acc与loss
        train_acc += (pred.argmax(1)==y).type(torch.float).sum().item()
        train_loss += loss.item()
        
    train_acc /= size
    train_loss /= num_batches
    
    return train_acc,train_loss

6. 定义测试函数

def test(dataloader,model,loss_fn):
    size = len(dataloader.dataset) # 测试集的大小,一共429张图片
    num_batches = len(dataloader) # 批次数目,14(429/32=13.4,向上取整)
    
    test_acc,test_loss = 0,0
    
    # 当不进行训练时,停止梯度更新,节省计算内存消耗
    with torch.no_grad():
        for X,y in dataloader:
            X,y = X.to(device),y.to(device)

            # 计算预测误差
            pred = model(X)
            loss = loss_fn(pred,y)
            
            # 记录acc与loss
            test_acc += (pred.argmax(1)==y).type(torch.float).sum().item()
            test_loss += loss.item()
    
    test_acc /= size
    test_loss /= num_batches
    
    return test_acc,test_loss

7. 训练过程

epochs = 20
train_acc = []
train_loss = []
test_acc = []
test_loss = []

for epoch in range(epochs):
    model.train()
    epoch_train_acc,epoch_train_loss = train(train_dl,model,loss_fn,opt)
    
    model.eval()
    epoch_test_acc,epoch_test_loss = test(test_dl,model,loss_fn)
    
    train_acc.append(epoch_train_acc)
    train_loss.append(epoch_train_loss)
    test_acc.append(epoch_test_acc)
    test_loss.append(epoch_test_loss)
    
    template = ('Epoch:{:2d},Train_acc:{:.1f}%,Train_loss:{:.3f},Test_acc:{:.1f}%,Test_loss:{:.3f}')
    print(template.format(epoch+1,epoch_train_acc*100,epoch_train_loss,epoch_test_acc*100,epoch_test_loss))
    
print('Done!')
Epoch: 1,Train_acc:57.0%,Train_loss:0.669,Test_acc:60.1%,Test_loss:0.661
Epoch: 2,Train_acc:65.8%,Train_loss:0.615,Test_acc:64.8%,Test_loss:0.618
Epoch: 3,Train_acc:70.1%,Train_loss:0.568,Test_acc:67.6%,Test_loss:0.594
Epoch: 4,Train_acc:74.1%,Train_loss:0.530,Test_acc:70.6%,Test_loss:0.589
Epoch: 5,Train_acc:76.3%,Train_loss:0.500,Test_acc:70.9%,Test_loss:0.561
Epoch: 6,Train_acc:78.6%,Train_loss:0.472,Test_acc:73.2%,Test_loss:0.532
Epoch: 7,Train_acc:81.1%,Train_loss:0.442,Test_acc:74.1%,Test_loss:0.518
Epoch: 8,Train_acc:82.2%,Train_loss:0.421,Test_acc:75.3%,Test_loss:0.516
Epoch: 9,Train_acc:83.1%,Train_loss:0.401,Test_acc:76.0%,Test_loss:0.497
Epoch:10,Train_acc:84.2%,Train_loss:0.388,Test_acc:77.6%,Test_loss:0.495
Epoch:11,Train_acc:85.6%,Train_loss:0.371,Test_acc:77.6%,Test_loss:0.478
Epoch:12,Train_acc:86.4%,Train_loss:0.363,Test_acc:78.6%,Test_loss:0.487
Epoch:13,Train_acc:87.9%,Train_loss:0.342,Test_acc:78.3%,Test_loss:0.476
Epoch:14,Train_acc:89.0%,Train_loss:0.331,Test_acc:80.2%,Test_loss:0.457
Epoch:15,Train_acc:89.8%,Train_loss:0.317,Test_acc:79.5%,Test_loss:0.480
Epoch:16,Train_acc:90.3%,Train_loss:0.313,Test_acc:80.9%,Test_loss:0.472
Epoch:17,Train_acc:90.7%,Train_loss:0.298,Test_acc:80.9%,Test_loss:0.442
Epoch:18,Train_acc:91.4%,Train_loss:0.289,Test_acc:82.1%,Test_loss:0.440
Epoch:19,Train_acc:91.1%,Train_loss:0.286,Test_acc:82.5%,Test_loss:0.429
Epoch:20,Train_acc:91.2%,Train_loss:0.277,Test_acc:81.6%,Test_loss:0.427
Done!

8. 结果可视化

import matplotlib.pyplot as plt
#隐藏警告
import warnings
warnings.filterwarnings("ignore")               #忽略警告信息
plt.rcParams['font.sans-serif']    = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False      # 用来正常显示负号
plt.rcParams['figure.dpi']         = 100        #分辨率

epochs_range = range(epochs)

plt.figure(figsize=(12, 3))
plt.subplot(1, 2, 1)

plt.plot(epochs_range, train_acc, label='Training Accuracy')
plt.plot(epochs_range, test_acc, label='Test Accuracy')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')

plt.subplot(1, 2, 2)
plt.plot(epochs_range, train_loss, label='Training Loss')
plt.plot(epochs_range, test_loss, label='Test Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')
plt.show()

在这里插入图片描述

9.模型的保存及预测

9.1 代码部分

# 模型保存
# torch.save(model.'mpox_rec_model.pth') # 保存整个模型

# 模型加载
# model2 = torch.load('mpox_rec_model.pth') 
# model2 = model2.to(device) # 理论上在哪里保存模型,加载模型也会优先在哪里,指定一下确保不会出错
# 状态字典保存
torch.save(model.state_dict(),'mpox_rec_model_state_dict.pth') # 仅保存状态字典

# 加载状态字典到模型
model2 = Network_bn().to(device) # 重新定义模型
model2.load_state_dict(torch.load('mpox_rec_model_state_dict.pth')) # 加载状态字典到模型
<All keys matched successfully>
# 指定路径图片预测
from PIL import Image
import torchvision.transforms as transforms

classes = list(total_data.class_to_idx) # classes = list(total_data.class_to_idx)

def predict_one_image(image_path,model,transform,classes):
    
    test_img = Image.open(image_path).convert('RGB')
    # plt.imshow(test_img) # 展示待预测的图片
    
    test_img = transform(test_img)
    img = test_img.to(device).unsqueeze(0)
    
    model.eval()
    output = model(img)
    print(output) # 观察模型预测结果的输出数据
    
    _,pred = torch.max(output,1)
    pred_class = classes[pred]
    print(f'预测结果是:{pred_class}')
# 预测训练集中的某张照片
predict_one_image(image_path='./data/mpox_recognize/Monkeypox/M01_01_00.jpg', 
                  model=model, 
                  transform=train_transforms, 
                  classes=classes)
tensor([[1.7220, 1.2390]], device='cuda:0', grad_fn=<ReluBackward0>)
预测结果是:Monkeypox

9.2 疑问解析

问题一:您好,请为我分析一下这段代码的含义,“classes = list (total_data.class_to_idx)”,其中total_data是使用torchvision.datasets.ImageFolder()处理得到的。请问具体的处理过程是怎样的?不同文件夹的名称处理后会自动作为分类处理吗?

问题解答:

您提供的代码行’ classes = list(total_data.class_to_idx) '通常用于PyTorch中加载和处理图像数据集的上下文中,特别是在使用"torchvision.datasets.ImageFolder"类时。让我们分解这个过程和具体的代码行来理解它的含义,以及它如何适应PyTorch图像数据处理的大背景。

理解“torchvision.datasets.ImageFolder”

"torchvision.datasets.ImageFolder"是PyTorch的torchvision包提供的一个实用程序类,旨在简化存储在磁盘目录结构中的图像数据的加载、转换和批处理。对于图像分类任务,它特别有用,因为您将数据集组织到子目录中,每个子目录以您希望模型学习的一个类命名。

目录结构

在深入研究代码之前,有必要了解预期的目录结构。假设您有一个包含三个类别的数据集:“猫”、“狗”和“鸟”。目录结构应该是这样的:

/path/to/data/
├── cats
│   ├── cat001.jpg
│   ├── cat002.jpg
│   └── ...
├── dogs
│   ├── dog001.jpg
│   ├── dog002.jpg
│   └── ...
└── birds
    ├── bird001.jpg
    ├── bird002.jpg
    └── ...

使用ImageFolder

当你实例化一个带有数据路径的’ ImageFolder '对象时,PyTorch会做以下操作:

  1. 扫描目录:递归扫描镜像文件的目录结构。
  2. 为类分配索引:每个子目录被视为一个单独的类,PyTorch自动为每个类分配索引。类名(子目录名)到它们分配的索引的映射存储在名为’class_to_idx '的字典属性中。
  3. 加载和转换图像:它提供了动态加载图像和应用任何指定转换(调整大小,规范化等)的机制。

分析特定的代码行

classes = list(total_data.class_to_idx)

鉴于上述背景:

  • ‘total_data’:这是’ ImageFolder '类的一个实例,它已经按照描述的方式处理了目录结构。

  • ‘total_data.class_to_idx’:这是一个字典,其中键是类名(派生自子目录的名称),值是它们对应的索引(整数)。索引是根据类名的排序顺序分配的。

  • ‘list(total_data.class_to_idx)’:此代码将’ class_to_idx '字典的键转换为列表。生成的“classes”列表包含按顺序排序的类名(子目录名)。此列表通常用于根据代码中其他地方的索引引用类名,特别是在解释模型的输出时。

总结:

因此,总而言之,您提供的代码提取并列出了“ImageFolder”自动识别和索引的类名(来自数据集中的子目录名)。“ImageFolder”的这个功能简化了加载图像数据进行分类的任务,确保每个类别,由一个文件夹表示,被自动视为一个单独的类。




本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/535553.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

HTTP请求报文介绍

本章简要介绍渗透测试员在攻击Web应⽤程序时可能遇到的关键技术。 将分析HTTP协议、服务器和客⼾端常⽤的技术以及⽤于在各种情形下呈现数据的编码⽅案。 这些技术⼤都简单易懂&#xff0c;掌握其相关特性对于向Web应⽤程序发动有效攻击极其重要。 1.1 HTTP协议概述介绍 HTT…

【学习笔记】R语言入门与数据分析1

数据分析 数据分析的过程&#xff1a; 数据采集 数据存储 数据分析 数据挖掘 数据可视化 进行决策 数据挖掘 数据量大 复杂度高&#xff0c;容忍一定的误差限 追求相关性而非因果性 数据可视化 直观明了 R语言介绍 R是免费的&#xff08;开源软件、扩展性好&#xff09;…

每天学点儿Python(6) -- 列表和枚举

列表是Python中内置的可变序列&#xff0c;类使用C/C中的数组&#xff0c;使用 [ ] 定义列表&#xff0c;列表中的元素与元素之间用英文逗号&#xff08; , &#xff09;分隔&#xff0c; 但是Python中列表可以存储任意类型的数据&#xff0c;且可以混存&#xff08;即类型可以…

Socks5代理IP使用教程

当我们在互联网上浏览网页、下载文件或者进行在线活动时&#xff0c;隐私和安全问题常常被提及。在这样的环境下&#xff0c;一个有效的解决方案是使用Sock5IP。本教程将向您介绍Sock5IP的使用方法&#xff0c;帮助您保护个人隐私并提升网络安全。 一、什么是Sock5IP&#xff1…

220 基于matlab的考虑直齿轮热弹耦合的动力学分析

基于matlab的考虑直齿轮热弹耦合的动力学分析&#xff0c;输入主动轮、从动轮各类参数&#xff0c;考虑润滑油温度、润滑油粘度系数等参数&#xff0c;输出接触压力、接触点速度、摩擦系数、对流传热系数等结果。程序已调通&#xff0c;可直接运行。 220直齿轮热弹耦合 接触压力…

医院手术麻醉信息管理系统源码 对接院内HIS、LIS、PACS

目录 ​移动手术工作站 主要解决的问题 主要硬件设备的对接 技术架构 手麻系统功能 手术进程 手术排班 手术记录 术前访视与评估 术中麻醉记录 麻醉总结 术后访视 模版配置 自动评分 文书模板 手麻系统的功能涵盖了麻醉临床业务管理、麻醉运营业务管理以及手术进…

三次 Bspline(B样条曲线) NURBS曲线的绘制 matlab

先来了解几个概念&#xff1a; 1.1 节点向量&#xff1a; B-Spline需要定义曲线的节点向量U&#xff0c;它可以对应到Bezier曲线的参数u。 其元素个数 (m1) 和曲线阶数 k 、控制点个数n满足&#xff1a;m1k1n1 如果U的每段的距离是相等&#xff0c;那么这个B-Spline就被称为均…

亚马逊云的账单申诉

亚马逊云科技申诉通常涉及几个步骤&#xff0c;目的是解决账单错误或申请费用调整。以下是一个基本的指南&#xff0c;可以帮助你开始处理账单问题&#xff1a; 1. 审核账单 在开始申诉之前&#xff0c;首先登录到亚马逊云科技管理控制台。 导航到“账单仪表板”以查看当前的…

模型训练-保存训练数据

1.目的 找到一个可运行的代码&#xff0c;可以每个epoch打印训练数据&#xff0c;但是不会保存。因为在改进模型需要这些训练数据进行对比&#xff0c;所以需要将每个epoch的训练数据保存下来&#xff0c;写到一个文件中。 2.解决方案 直接问ChatGPT&#xff0c;提示词如下&…

AtCoder ABC248 A-D题解

比赛链接:ABC348 Problem A: 签到。 #include <bits/stdc.h> using namespace std; int main(){int N;cin>>N;for(int i1;i<N;i){if(i%30)cout<<x<<endl;elsecout<<o<<endl;}return 0; } Problem B: 枚举即可。 #include <bit…

51蓝桥杯之DS18B20

DS18B20 基础知识 代码流程实现 将官方提供例程文件添加到工程中 添加onewire.c文件到keil4里面 一些代码补充知识 代码 #include "reg52.h" #include "onewire.h" #include "absacc.h" unsigned char num[10]{0xc0,0xf9,0xa4,0xb0,0x99,…

【域适应】基于深度域适应MMD损失的典型四分类任务实现

关于 MMD &#xff08;maximum mean discrepancy&#xff09;是用来衡量两组数据分布之间相似度的度量。一般地&#xff0c;如果两组数据分布相似&#xff0c;那么MMD 损失就相对较小&#xff0c;说明两组数据/特征处于相似的特征空间中。基于这个想法&#xff0c;对于源域和目…

24/04/11总结

IO流(First edition): IO流&#xff1a;用于读入写出文件中的数据 流的方向&#xff08;输入指拿出来,输出指写进去) 输入流:读取 输出流:写出 操作文件类型 字节流:所有类型文件 字符流:纯文本 字节流: InputStream的子类:FileInputStream:操作本地文件的字节输入流 OutputSt…

工作流引擎常见API(以camunda为例)

在Camunda中&#xff0c;API的继承关系主要体现在各个服务接口之间。以下是Camunda中一些常见服务接口的继承关系&#xff1a; ProcessEngineServices 接口&#xff1a; RepositoryService&#xff1a; 负责管理流程定义和部署。RuntimeService&#xff1a; 负责管理流程实例的…

2023年通用人工智能AGI等级保护白皮书

今天分享的是人工智能专题系列深度研究报告&#xff1a;《人工智能专题&#xff1a;2023年通用人工智能AGI等级保护白皮书》。 通用人工智能发展现状 本章主要介绍通用人工智能的基本情况&#xff0c;包括其发展历史、现状以及组成架构等内容。本文还将通过从技术角度出发来分…

PTA 应急救援站选址(floyd+打印路径)

大学城虎溪社区有很多居民小区&#xff0c;居民小区道路图是连通的。现要在该社区新建一个应急救援站&#xff0c;且该应急救援站要和某个小区建在一起。为了使应急救援最快速&#xff0c;经各部门商量决定&#xff1a;应急救援站建好后&#xff0c;离应急救援站最远的小区到应…

大话设计模式之命令模式

命令模式是一种行为型设计模式&#xff0c;它将请求或操作封装成一个对象&#xff0c;从而允许客户端参数化操作。这意味着客户端将一个请求封装为一个对象&#xff0c;这样可以将请求的参数化、队列化和记录日志&#xff0c;以及支持可撤销的操作。 命令模式主要由以下几个角…

kaggle 泰坦尼克号1(根据男女性存活率)

kaggle竞赛 泰坦尼克号 流程 下载kaggle数据集导入所要使用的包引入kaggle的数据集csv文件查看数据集的大小和长度去除冗余数据建立特征工程导出结果csv文件 1.下载kaggle数据集 2.导入所要使用的包 import pandas as pd import numpy as np import matplotlib.pyplot as …

leetcode328.奇偶链表

1. 题目描述 在线练习 2. 解题思路 这道题&#xff0c;官方给的是中等难度。其实是一道基础题&#xff0c;大家应该都可以写得出来。 题目中给的示例可以清楚的看到&#xff0c;合并前后的奇偶链的各自包含的节点的顺序是不变的&#xff0c;我们基本可以确定使用尾插法来合并…

Ansys Mechanical | 软件介绍:业界一流的有限元求解器

Ansys Mechanical 有限元分析软件 Ansys Mechanical 是业界一流的有限元求解器&#xff0c;具有结构、热学、声学、瞬态和非线性功能&#xff0c;可帮助改进建模。 ​ 软件概览 Ansys Mechanical 创建了一个使用有限元仿真分析软件&#xff08;FEA&#xff09;进行结构分析…