神经网络/深度学习
第三章 Python机器学习入门之ResNet18的使用
前言
本文主要是复现resnet18网络代码,训练自己的二分类模型,学习记录下来。
一、ResNet是什么?
深度残差网络(Deep residual network, ResNet)的提出是CNN图像史上的一件里程碑事件,具体多牛,大家自己某度咯。ResNet的作者何恺明也因此摘得CVPR2016最佳论文奖,当然何博士的成就远不止于此,感兴趣的也可以去搜一下他后来的辉煌战绩。下面简单讲述ResNet的理论及实现。具体的解释可以去这位大佬的博文看看。
原文链接:https://blog.csdn.net/weixin_39524208/article/details/124894216
二、使用步骤
1.制作excel表格
我们已第一列为例,0代表扁平,1代表拟物。一次代码只能实行一个二分类的训练,例如途中有四列,那么就要训练四次。下面会说
2.引入库
import torch
from torch.utils.data import DataLoader
from torchvision import transforms
from PIL import Image
from torch.utils.data import Dataset
import pandas as pd
from sklearn.model_selection import train_test_split
import torchvision.models as models
import torch.nn as nn
torch, torchvision, PIL, pandas, sklearn等库用于深度学习、图像处理和数据处理。
3.定义自定义数据集类CustomDataset:
class CustomDataset(Dataset):
def __init__(self, image_paths, labels, transform=None):
self.image_paths = image_paths
self.labels = labels
self.transform = transform
def __len__(self):
return len(self.image_paths)
def __getitem__(self, idx):
try:
image = Image.open(self.image_paths[idx]).convert('RGB')
if self.transform:
image = self.transform(image)
label = self.labels[idx]
return image, torch.tensor(label, dtype=torch.float32)
except Exception as e:
print(f"Error loading image {self.image_paths[idx]}: {e}")
return None
该类继承自 torch.utils.data.Dataset,用于加载图像数据和相应的标签。它包括三个主要方法:
init:初始化图像路径、标签和图像变换。
len:返回数据集的大小。
getitem:获取指定索引的图像和标签,并进行预处理。
4.数据加载预处理和模型训练
def main():
df = pd.read_excel('excel/训练基础标签.xlsx', sheet_name='Sheet1')#这里是读取excel的位置。excel的内容上面已经写了
image_paths = [f"train/基础标签/{path}" for path in
df.iloc[:, 0].astype(str)]#这里是图片训练集所在的位置,也就是excel表中第一列的那些图片
labels = df.iloc[:, 1].tolist()
#image_paths:从第一列获取图像文件名,并将其拼接成完整的路径。
#labels:从第二列(也就是简约复杂)获取标签,并将其转换为列表形式。如果是第三列就可以改成[:, 2]
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
])
train_images, test_images, train_labels, test_labels = train_test_split(
image_paths, labels, test_size=0.2, random_state=42)
train_dataset = CustomDataset(train_images, train_labels, transform)
test_dataset = CustomDataset(test_images, test_labels, transform)
train_loader = DataLoader(train_dataset, batch_size=16, shuffle=True, num_workers=16)
test_loader = DataLoader(test_dataset, batch_size=32, shuffle=False, num_workers=16)
model = models.resnet18(pretrained=True) # 使用预训练的 ResNet18 模型
num_ftrs = model.fc.in_features # 获取最后一层全连接层的输入特征数
model.fc = nn.Linear(num_ftrs, 1) # 修改最后一层以适应二分类任务,输出一个神经元
model.to('cuda') # 将模型加载到 GPU 上
criterion = nn.BCEWithLogitsLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.0001)
for epoch in range(10):
model.train()
for images, labels in train_loader:
if images is None:
continue
images, labels = images.to('cuda'), labels.to('cuda')
optimizer.zero_grad()
outputs = model(images).squeeze()
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
print(f'Epoch {epoch + 1} complete.')
# Model evaluation
model.eval()
total = 0
correct = 0
with torch.no_grad():
for images, labels in test_loader:
if images is None:
continue
images, labels = images.to('cuda'), labels.to('cuda')
outputs = model(images).squeeze()
predicted = (torch.sigmoid(outputs) > 0.5).float()
total += labels.size(0)
correct += (predicted == labels).sum().item()
print(f'Accuracy: {100 * correct / total:.2f}%')
# Save the model
torch.save(model.state_dict(),'models/resnet_multilabel_jichu01.pth')#模型存放的位置
print("Model saved successfully.")
if __name__ == '__main__':
main()
总结来说,在读取文件和标签的时候,确实只读取了Excel文件的前两列,其中第一列包含图像文件名,第二列包含对应的标签(如果训练其他的标签只需要对列数进行修改)。还有一定要注意修改最后一层全连接层的输入特征数,以适应二分类任务,输出一个神经元。
总结
以上就是今天代码所复现的内容,本文仅仅简单复现了ResNet18的代码并训练,如有不足还望批评指正。