当前位置: 首页 > news >正文

深度学习笔记:入门

1.数据处理

1.1 自己实现一个数据集类

主要目的让他成为一个Dataset的类即可,有没有里面的操作无所谓

包含了加载和处理这些图片所需的所有信息和指令,也即管理数据的数据员,继承Dataset, 是一个数据集管理员,专门为模型的训练和验证服务

#定义数据集类
class CustomDataset(Dataset):def __init__(self, csv_file, root_dir, transform=None, is_test = False):super().__init__()self.data = csv_fileself.root_dir = root_dirself.transform = transformself.is_test = is_testdef classes(self):return self.data.iloc[:, 1].unique().tolist() #取csv_file数据中的第二列(索引为 1),这通常是存放标签的列。unique()去除重复项,tolist()将结果转换成一个列表。def __len__(self):return len(self.data)#获取单个数据样本def __getitem__(self, idx):img_path = os.path.join(self.root_dir, self.data.iloc[idx, 0])image = Image.open(img_path)if self.transform:image = self.transform(image)if self.is_test:return imagelabel = self.data.iloc[idx, 2]label = torch.tensor(label)return image, label

1.2 定义一个加载数据的函数

1.读入文件目录的文件csv格式

2.对数据进行一些变换

3.并且把训练数据集按9:1分成训练和测试集,并且进行随机划分

4.将自定义的CustomDataset数据集类按照batch_size用DataLoader加载进来,加载后进行合并成一个数据加载器dataloaders

#加载数据集和数据增强,数据处理
def load_dataset(batch_size, img_size):train_transforms = transforms.Compose([transforms.Resize(img_size),#将所有图片调整到统一的尺寸transforms.RandomHorizontalFlip(),#以 50% 的概率对图片进行随机水平翻转transforms.RandomVerticalFlip(),#以 50% 的概率对图片进行随机垂直翻转transforms.ToTensor(),#从 PIL 格式转换成 PyTorch 的 Tensor 格式,并把像素值从 0-255 缩放到 0-1 之间])test_transforms = transforms.Compose([transforms.Resize(img_size),transforms.ToTensor(),])#读取数据集root_folder = "/kaggle/input/classify-leaves"train_csv = pd.read_csv("/kaggle/input/classify-leaves/train.csv")test_csv = pd.read_csv("/kaggle/input/classify-leaves/test.csv")#标签编码,str到intleaves_labels = train_csv.iloc[:, 1].unique()#找出所有不重复的类别名称n_classes = len(leaves_labels)class_to_num = dict(zip(leaves_labels, range(n_classes))) #创建从“文字”到“数字”的映射字典train_csv['labelEncoded'] = train_csv.iloc[:, 1].map(class_to_num)#应用映射,生成新的数字标签列full_dataset = CustomDataset(train_csv, root_folder, transform=train_transforms)predict_dataset = CustomDataset(test_csv, root_folder, transform=test_transforms, is_test=True)#分开数据集train_size = int(0.9*len(full_dataset))test_size = len(full_dataset) - train_sizetrain_dataset, test_dataset = torch.utils.data.random_split(full_dataset, [train_size, test_size])#随机划分#数据加载train_dataloader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)test_dataloader = DataLoader(test_dataset, batch_size = batch_size, shuffle=True)dataloaders = {'train':train_dataloader, 'test':test_dataloader}print(f"train_size:{train_size},test_size:{test_size}")print(full_dataset.classes)return dataloaders, full_dataset.classes, predict_dataset

可选:用matlab打印一些图片来看文件是否是正确的读取了

自己写一个函数想啥时候打印就打印来看

#健全性检查
import  matplotlib.pyplot as plt
def display_data(dataloader, class_names):#获取一个batch的图像和标签从数据加载器images, labels = next(iter(dataloader["train"]))#展示前5张图片fig, axes = plt.subplots(1, 5, figsize=(15, 3))#创建一个包含 1行5列 子图的网格for i in range(5):axes[i].imshow(images[i].permute(1, 2, 0)) #改变维度顺序(C,H,W)到(H,W,C)axes[i].set_title(class_names[labels[i]])axes[i].axis('off')#关闭坐标轴的显示plt.show()

2.网络模块:这里使用resnet18

2.1resnet残差块

自己实现,继承nn.Module模块,一个残差块两个卷积层

import torch
from torch import nn
from torch.nn import functional as F#残差块
class Residual(nn.Module):def __int__(self, input_channels, num_channels, use_1x1conv=False, strides=1):super().__init__()self.conv1 = nn.Conv2d(input_channels, num_channels, kernel_size=3, padding=1, stride=strides)self.conv2 = nn.Conv2d(num_channels, num_channels, kernel_size=3, padding=1)if use_1x1conv:self.conv3 = nn.Conv2d(input_channels, num_channels, kernel_size=1, stride=strides)else:self.conv3 = Noneself.bn1 = nn.BatchNorm2d(num_channels)self.bn2 = nn.BatchNorm2d(num_channels)def forward(self, x):y = F.relu(self.bn1(self.conv1(x)))y = self.bn2(self.conv2(y))if self.conv3:x = self.conv3(x)y += xreturn F.relu(y)

2.2 将残差的每个层合成一个大的block

因为resnet18,有四个大块,每个大块里面有很多个重复的残差块组成

#残差所有层
def resent_block(input_channels, num_channels, num_residuals, first_block=False):block = []for i in range(num_residuals):if i == 0 and not first_block:block.append(Residual(input_channels, num_channels, use_1x1conv = True, strides = 2))else :block.append(Residual(num_channels, num_channels))return block

2.3 resnet18的实现

每个小的残差块两个卷积层,(3+2+2+2)*2=18层

#残差18
def resNet_18(n_classes):b1 = nn.Sequential(nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3),nn.BatchNorm2d(64),nn.ReLU(),nn.MaxPool2d(kernel_size=3, stride=2, padding=1))b2 = nn.Sequential(*resent_block(64, 64, 3, first_block=True))b3 = nn.Sequential(*resent_block(64, 128, 2))b4 = nn.Sequential(*resent_block(128, 256, 2))b5 = nn.Sequential(*resent_block(256, 512, 2))return nn.Sequential(b1, b2, b3, b4, b5,nn.AdaptiveAvgPool2d((1,1)),nn.Flatten(), nn.Linear(512, n_classes))

可以打印每一层看看形状

net = resNet_18(n_classes=100)
x = torch.rand(size=(1, 3, 256, 256))
for layer in net:x = layer(x)print(layer.__class__.__name__,'output shape:\t', x.shape)

3.定义指标

这里只计算准确率

#计算准确率
def calculate_accuracy(model, data_loader, device):correct = 0total = 0with torch.no_grad():for data, target in data_loader:data, target = data.to(device), target.to(device)output = model(data)#它会返回两个值:第一个是最大值本身(我们不需要,所以用下划线 _ 忽略掉),第二个是最大值所在的索引 (index)_, predicted = torch.max(output.data, 1)#沿着维度1(即按行)查找每一行的最大值total += target.size(0)#加上当前批次中的样本数量correct += (predicted==target).sum().item()return correct/total

4.封装训练train函数

1.遍历每个epoch,把训练的数据放进去得到一个预测标签

2.然后调用损失函数计算损失

3.在求损失函数的梯度

4.利用优化器来按照梯度来更新模型的参数

5.最好调用自己写的准确率函数来计算准确率

#定义训练函数
import  torch.optim as optim
def train(model, dataloaders, epochs, criterion, optimizer):for epoch in range(epochs):for batch_idx, (data, target) in enumerate(dataloaders['train']):data, target = data.to(device), target.to(device)optimizer.zero_grad()output = model(data)loss = criterion(output, target)#损失函数 (criterion) 会比较模型的预测 output 和真实的标签 target,计算出一个 loss 值loss.backward()#据损失值 loss 自动计算出模型中每个参数(权重)的梯度optimizer.step()#优化器 (optimizer) 会根据上一步计算出的梯度信息,来更新模型的所有参数if(batch_idx) % 100 ==0:train_accuracy = calculate_accuracy(model, dataloaders['train'], device)test_accuracy = calculate_accuracy(model, dataloaders['test'], device)#在当前Epoch 内的处理进度(例如“处理了3200/18346 张图片"print(f"eopch:{epoch}",f"[{batch_idx*batch_size}/{len(dataloaders['train'].dataset)} ({100.*batch_idx/len(dataloaders['train']):.0f}%)]\t"f"loss:{loss.item():.6f}\t"f"train accuracy:{100. * train_accuracy:.2f}%\t"f"test accuracy:{100. * test_accuracy:.2f}%")

可选:gpu运算

#gpu训练
train_on_gpu = torch.cuda.is_available()
if not train_on_gpu:print('Training on CPU')
else :print('Training on GPU')
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

5.最后运行整个项目

1.给一下超参数赋值,然后调用自己写的数据加载函数来加载数据变成dataloaders

2.调用自己写的函数来创建模型resnet18,可以展示一些数据来观看,

3.定义损失函数和优化器

4.最后调用自己写的封装train函数进行训练

#resnet18
batch_size = 128
img_size = 48
epochs = 50
dataloaders, class_names, predict_dataset = load_dataset(batch_size=128, img_size=256)
model = resNet_18(len(class_names))
model.to(device)
display_data(dataloaders, class_names)
criterion = nn.CrossEntropyLoss() #nn.CrossEntropyLoss包含softmax
optimizer = optim.Adam(model.parameters(), lr = 0.001)#sdg
train(model, dataloaders, epochs, criterion, optimizer)

http://www.dtcms.com/a/486438.html

相关文章:

  • 第六篇: `dmesg` `lspci` - 硬件层面的“黑匣子”与“雷达”
  • 青岛制作网站云南建设厅查证网站
  • 自己怎么做外贸英文网站大型电商网站开发成本
  • 论文理解 【LLM-回归】—— Decoding-based Regression
  • DeepSeek使用教程
  • 青龙 定时任务管理平台
  • csdn手机app应该增加导入word格式markdown格式,或者输入网址自动导入
  • K8s学习笔记(二十) 亲和性、污点、容忍、驱逐
  • 培训餐饮网站建设dede 分类信息网站 模板
  • 硅基计划4.0 算法 二叉树深搜(DFS)
  • 深度学习------目标检测项目
  • 【MySQL】数据库表的CURD(二)
  • 计算机视觉--opencv---如何识别不同方向图片的识别(一)
  • 互联网大厂Java求职面试全景实战解析(涵盖Spring Boot、微服务及云原生技术)
  • Linux使用Docker部署Node.js+Express+SQLite项目
  • 如何自己开网站济南做平台网站的
  • STM32H743-ARM例程21-DSP
  • Linux下编译CGAL
  • 十五、OpenCV中的图像浮雕技术
  • 网站建设的搜索栏怎么设置重庆市建设工程信息网官网施工许可证查询
  • Effectively Using Public Data in Privacy Preserving Machine Learning
  • 国产电脑操作系统与硬盘兼容性现状分析:挑战与前景评估
  • 从 DAG 到 Shuffle:掌握 Spark RDD 宽窄依赖的调优密码
  • 48 元四核 ARM 核心板!明远智睿 2351 进入嵌入式市场
  • 李宏毅机器学习笔记23
  • 为何打不开中国建设银行网站深圳品牌营销策划机构
  • 大连旅顺网站制作有哪些网站可以做笔译
  • 【遥感图像处理】遥感图像车辆检测与跟踪全流程实战:从数据到部署(含Python代码)
  • PPO论文阅读
  • C++学习:异常及其处理