当前位置:网站首页 > R语言数据分析 > 正文

resnet18网络结构分类(resnet200网络结构)



先看问题:

我手边有一数据集,然后我想分分类!~~·

咳咳,最近刚做了一个:训练集有1143张,分为5类,里面图片是打乱的。测试集有248张,想把它分分类看看咋样。

再看一下效果: 

这是经过100轮训练后准确率。(准确率最高也就72%左右,要想再升高就要改变数据集或者改网络了)

同时我们也将训练后的结果保存到了文件夹里。

经过网络训练后,最后的显示图:

预测第一张图属于第二类,它的确也确实属于第二类;但第二张图预测它是第二类,但是它事实上属于第四类。


① Prepare dataset   构建数据集

② Design model using Class   设计模型 

③ Construct loss and optimizer  构造损失函数和优化器

④ Training   训练

⑤ Prediction  预测结果(第五步可适当补充想生成的图像)

在写代码的时候,如果数据集都构建不好,后续都不用进行了。

接下来,我们简单说一下两种数据集构建代码。

(1) torchvision内置的数据集

这种就是最为简单的一种,可以直接调用的。如 MNIST、Fashion-MNIST、EMNIST、COCO、LSUN、ImageFolder、DatasetFolder、Imageenet-12、CIFAR、STL10 等。

下面简单以 CIFAR-10 为例:

a. 下载

CIFAR-10 and CIFAR-100 datasets (toronto.edu)

(下载解压后如下,并将文件夹放入一个新的文件夹 CIFAR 里,并将该文件夹放入另一个文件夹SH1中。)

大致构建如下:

b. 简单介绍 CIFAR-10 
c. 下载并配置数据集及加载器
 

1. trans = transforms.Compose([transforms.Resize((96, 96)), transforms.ToTensor()]): 这行代码创建了一个数据转换操作的组合 trans,其中包括将图像大小调整为 (96, 96) 并将其转换为张量的操作。

2. train_dataset = datasets.CIFAR10(root=r'D:SH1CIFAR', train=True, transform=trans): 这行代码创建了一个 CIFAR-10 数据集的训练集 train_dataset,指定了数据集的根目录和使用的数据转换操作。

3. test_dataset = datasets.CIFAR10(root=r'D:SH1CIFAR', train=False, transform=trans): 这行代码创建了一个 CIFAR-10 数据集的测试集 test_dataset,同样指定了数据集的根目录和使用的数据转换操作。

4. batch_size = 64: 这行代码定义了批量大小为 64。

5. train_loader = DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True): 这行代码创建了一个训练数据加载器 train_loader,用于加载训练数据集,指定了数据集、批量大小和是否打乱数据顺序。

6. test_loader = DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=True): 这行代码创建了一个测试数据加载器 test_loader,用于加载测试数据集,同样指定了数据集、批量大小和是否打乱数据顺序。

(2)我们自己手里的数据集

a. 整理标签

以上上周我们老师给我的数据集为例。老师给我的数据集里面包含训练集和测试集以及相应的标签。

但是标签里面的信息太多了,我只需要它的名称以及类别。

以Training_Labels为例,我只需要第一列 image 和 第二列 myopic_maculopathy_grade。

 

所以我通过上面的代码将第一列和第二列进行了提取,并且改成了:filename', 'label',生成了另外的标签。

同样以train_Labels为例:

b. 定义一个自定义数据集类 

我们要定义一个自定义数据集类 CustomDataset , 用于加载图像数据集并返回及其对应的标签。

 

1. class CustomDataset(Dataset)::定义了一个名为 CustomDataset 的类,该类继承自 Dataset 类,用于创建自定义数据集。

2. def __init__(self, csv_file, root_dir, transform=None)::定义了类的初始化方法,接受三个参数:csv_file 表示包含标签信息的 CSV 文件路径,root_dir 表示图像文件所在的根目录,transform 表示数据转换操作,默认为 None。

3. self.labels_df = pd.read_csv(csv_file): 从给定的 CSV 文件中读取标签信息并存储在 labels_df 中。

4. self.root_dir = root_dir:将图像文件的根目录路径存储在 root_dir 中。

5. self.transform = transform:存储数据转换操作,例如将图像转换为张量等。

6. def __len__(self)::定义了 __len__ 方法,返回数据集的长度,即标签信息的数量。

7. def __getitem__(self, idx)::定义了 __getitem__ 方法,用于获取数据集中特定索引 idx 处的图像及其标签。

8. img_name = os.path.join(self.root_dir, self.labels_df.iloc[idx, 0]):构建图像文件的完整路径。

9. try...except...:尝试打开图像文件,如果文件不存在则捕获 FileNotFoundError 异常并打印错误信息。

10. label = int(self.labels_df.iloc[idx, 1]):从标签数据中提取标签信息,转换为整数类型。

11. if self.transform::检查是否存在数据转换操作。

12. image = self.transform(image):如果存在数据转换操作,则对图像进行相应的转换。

13. return image, label:返回处理后的图像及其对应的标签。

c. 配置数据集及加载器
 

( 由于这个代码和下载并配置CIFAR-10数据集及加载器的代码差不多,刚才仔细讲过了,所以这里就不再讲一遍了)

我们用的是ResNet-18网络,要想更好的理解这个网络,我们需要了解一个知识点----残差块。

在 ResNet-18 中,残差块起着关键的作用,通过引入跳跃连接(skip connection)来缓解深层神经网络中的梯度消失问题,从而使得训练更深层的网络成为可能。具体来说:

1. 跳跃连接:在每个残差块中,通过将输入直接与输出相加(即跳跃连接),实现了从底层到顶层的直接信息传递。这种跳跃连接有助于梯度的流动,避免了梯度在深层网络中逐渐消失的问题。

2. 缓解梯度消失:由于跳跃连接的存在,即使在深层网络中,梯度可以通过跳跃连接直接传播到较浅层,从而减轻了梯度消失问题,使得网络更容易训练。

3. 增强网络性能:残差块的设计使得网络更加深层时仍能保持较好的性能,因为网络可以更好地学习残差(即残差块的输出与输入之间的差异),而不是直接学习原始特征。

了解后,我们要了解一下网络的结构图:

经典CNN网络:Resnet18网络结构输入和输出[通俗易懂]-腾讯云开发者社区-腾讯云 (tencent.com)

(网上有很多资料,我随便找了一个,应该还是比较容易的)

接下来,我们讲下代码:

(1) 残差块

 

1. class Residual(nn.Module)::定义了一个名为 Residual 的类,继承自 nn.Module 类,表示这是一个 PyTorch 模型。

2. def __init__(self, input_channels, num_channels, use_1x1conv=False, strides=1)::定义了类的初始化方法,接受输入通道数 input_channels、输出通道数 num_channels、是否使用 1x1 卷积 use_1x1conv 和步幅 strides 作为参数。

3. super().__init__():调用父类的初始化方法。

4. self.conv1 = nn.Conv2d(input_channels, num_channels, kernel_size=3, padding=1, stride=strides): 创建第一个卷积层,使用 3x3 的卷积核,填充为 1,步幅为 strides。

5. self.conv2 = nn.Conv2d(num_channels, num_channels, kernel_size=3, padding=1): 创建第二个卷积层,输入通道数为 num_channels,输出通道数为 num_channels,使用 3x3 的卷积核,填充为 1。

6. if use_1x1conv::检查是否使用 1x1 卷积。

7. self.conv3 = nn.Conv2d(input_channels, num_channels, kernel_size=1, stride=strides): 如果使用 1x1 卷积,创建一个 1x1 的卷积层。

8. self.bn1 = nn.BatchNorm2d(num_channels): 创建第一个批量归一化层。

9. self.bn2 = nn.BatchNorm2d(num_channels): 创建第二个批量归一化层。

10. def forward(self, X)::定义了前向传播方法,接受输入 X。

11. Y = F.relu(self.bn1(self.conv1(X))): 应用第一个卷积层、批量归一化和 ReLU 激活函数。

12. Y = self.bn2(self.conv2(Y)): 应用第二个卷积层和批量归一化。

13. if self.conv3::检查是否存在第三个卷积层。

14. X = self.conv3(X): 如果存在第三个卷积层,应用该卷积层。

15. Y += X: 将输入 X(或经过 1x1 卷积层的 X)加到 Y 上,实现残差连接。

16. return F.relu(Y): 返回经过激活函数处理后的输出 Y。

(2) ResNet-18 网络

 

(这段的讲解放在了代码里面)

 

1. lr = 0.001: 定义了学习率为 0.001,即优化器在更新模型参数时的步长大小。

2. optimizer = torch.optim.Adam(net.parameters(), lr=lr): 创建了一个 Adam 优化器,用于更新模型 net 中的参数。Adam 是一种常用的优化算法,通过调整学习率来最小化损失函数。

3. loss = nn.CrossEntropyLoss(): 创建了一个交叉熵损失函数,用于计算模型输出与真实标签之间的损失。交叉熵损失通常用于多分类问题,特别是在输出层使用 softmax 激活函数时。

 
 
 

附赠:用CIFAR-10数据集操作的代码(20轮,准确率大概在80%左右)

代码1和代码2都差不多,代码1和今天讲的差不多就改了一下数据集,代码2删减了一部分更改了一些,更为简单一点

代码1:

 

代码2:

到此这篇resnet18网络结构分类(resnet200网络结构)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!
                            

版权声明


相关文章:

  • ar是什么中文意思(ar是什么英文)2024-12-21 17:36:09
  • devicesupport客服(edition客服)2024-12-21 17:36:09
  • 连接redis(连接redis用什么包)2024-12-21 17:36:09
  • swagger无法访问(swagger-ui访问不到)2024-12-21 17:36:09
  • detr源码(dev源码)2024-12-21 17:36:09
  • edge损坏了怎么办(microsoft edge坏了怎么办)2024-12-21 17:36:09
  • qpainter(QPainter绘制图片)2024-12-21 17:36:09
  • tree安卓版下载(treearia下载)2024-12-21 17:36:09
  • rbac权限控制(rbac 权限)2024-12-21 17:36:09
  • docker开机启动(docker开机启动脚本)2024-12-21 17:36:09
  • 全屏图片