第24周:Resnet结合DenseNet

发布于:2025-04-22 ⋅ 阅读:(30) ⋅ 点赞:(0)

目录

前言

一、 前期准备

1. 设置GPU

2.查看数据

二、构建模型

1.划分数据集

2.划分标签 

3.编译及训练模型 

三、结果可视化

四、总结


前言


一、 前期准备

1. 设置GPU
import os,PIL,pathlib,warnings
warnings.filterwarnings("ignore")            
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
device

2.查看数据

import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']  
plt.rcParams['axes.unicode_minus'] = False 
 
import os,PIL,pathlib
data_dir="data/第8天/bird_photos"
data_dir=pathlib.Path(data_dir)
 
image_count = len(list(data_dir.glob('*/*')))
print("图片总数为:",image_count)

二、构建模型

1.划分数据集

batch_size = 8
img_height = 224
img_width = 224
 
import torchvision.transforms as transforms
import torchvision.datasets as datasets
transforms=transforms.Compose([
    transforms.Resize([224,224]),
    transforms.ToTensor(),
    # transforms.Normalize(
    #     mean=[0.482,0.456,0.406],
    #     std=[0.229,0.224,0.225]
    # )
])
total_data=datasets.ImageFolder("data/第8天/bird_photos",transform=transforms)
total_data
 
total_data.class_to_idx
 
train_size=int(0.8*len(total_data))
test_size=len(total_data)-train_size
train_data,test_data=torch.utils.data.random_split(total_data,[train_size,test_size])
train_data,test_data
 
batch_size=8
train_dl=torch.utils.data.DataLoader(train_data,batch_size,shuffle=True,num_workers=1)
test_dl=torch.utils.data.DataLoader(test_data,batch_size,shuffle=True,num_workers=1)
 
for X,y in train_dl:
    print(X.shape)
    print(y.shape)
    break

2.划分标签 

total_data.class_to_idx

3.编译及训练模型 

def train(dataloader,model,loss_fn,optimizer):
    size=len(dataloader.dataset)
    num_batches=len(dataloader)
    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)
        #反向传播
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        
        train_loss+=loss.item()
        train_acc+=(pred.argmax(1)==y).type(torch.float).sum().item()
    train_acc/=size
    train_loss/=num_batches
    return train_acc,train_loss
def test(dataloader,model,loss_fn):
    size=len(dataloader.dataset)
    num_batches=len(dataloader)
    test_loss,test_acc=0,0
    with torch.no_grad():
        for imgs,target in dataloader:
            imgs,target=imgs.to(device),target.to(device)
            target_pred=model(imgs)
            loss=loss_fn(target_pred,target)
            test_loss+=loss.item()
            test_acc+=(target_pred.argmax(1)==target).type(torch.float).sum().item()
    test_acc/=size
    test_loss/=num_batches
    return test_acc,test_loss
 
import copy
optimizer  = torch.optim.Adam(model.parameters(), lr= 1e-4)
loss_fn    = nn.CrossEntropyLoss()
 
import copy
import torch
 
# Loss function and other initializations
loss_fn = nn.CrossEntropyLoss()
epochs = 20
train_loss = []
train_acc = []
test_loss = []
test_acc = []
best_acc = 0
best_loss = float('inf')  # 初始化最优损失为正无穷
patience = 5  # 设置耐心值,即连续5轮损失不下降时停止训练
patience_counter = 0  # 用于记录损失不下降的轮数
 
# Training and testing loop
for epoch in range(epochs):
    model.train()
    epoch_train_acc, epoch_train_loss = train(train_dl, model, loss_fn, optimizer)
   
    model.eval()
    epoch_test_acc, epoch_test_loss = test(test_dl, model, loss_fn)
 
    # Check if test loss improved
    if epoch_test_loss < best_loss:
        best_loss = epoch_test_loss
        best_model = copy.deepcopy(model)
        patience_counter = 0  # 重置耐心计数器
    else:
        patience_counter += 1  # 增加耐心计数器
 
    # If patience is exceeded, stop training
    if patience_counter >= patience:
        print(f"Stopping early at epoch {epoch+1} due to no improvement in test loss for {patience} epochs.")
        break
 
    train_acc.append(epoch_train_acc)
    train_loss.append(epoch_train_loss)
    test_acc.append(epoch_test_acc)
    test_loss.append(epoch_test_loss)
 
    # Print the results for the current epoch
    lr = optimizer.state_dict()['param_groups'][0]['lr']
    template = ('Epoch:{:2d}, Train_acc:{:.1f}%, Train_loss:{:.3f}, Test_acc:{:.1f}%, Test_loss:{:.3f}, Lr:{:.2E}')
    print(template.format(epoch + 1, epoch_train_acc * 100, epoch_train_loss, 
                          epoch_test_acc * 100, epoch_test_loss, lr))
 
# Save the best model
PATH = './best_model.pth'
torch.save(best_model.state_dict(), PATH)
print('Finished Training')

三、结果可视化

import matplotlib.pyplot as plt
import warnings
epochs = len(train_acc)
    
# 绘制准确率
plt.figure(figsize=(12, 6))
plt.subplot(1, 2, 1)
plt.plot(range(1, epochs + 1), train_acc, label='Train Accuracy', color='blue')
plt.plot(range(1, epochs + 1), test_acc, label='Test Accuracy', color='orange')
plt.title('Training and Test Accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend(loc='best')
    
# 绘制损失
plt.subplot(1, 2, 2)
plt.plot(range(1, epochs + 1), train_loss, label='Train Loss', color='blue')
plt.plot(range(1, epochs + 1), test_loss, label='Test Loss', color='orange')
plt.title('Training and Test Loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend(loc='best')
    
# 显示图形
plt.tight_layout()
plt.show()
Epoch: 1, Train_acc:34.3%, Train_loss:6.088, Test_acc:55.8%, Test_loss:5.442, Lr:1.00E-04
Epoch: 2, Train_acc:55.8%, Train_loss:4.859, Test_acc:56.6%, Test_loss:4.382, Lr:1.00E-04
Epoch: 3, Train_acc:60.8%, Train_loss:4.076, Test_acc:56.6%, Test_loss:3.759, Lr:1.00E-04
Epoch: 4, Train_acc:61.1%, Train_loss:3.380, Test_acc:61.1%, Test_loss:2.907, Lr:1.00E-04
Epoch: 5, Train_acc:60.2%, Train_loss:2.901, Test_acc:69.0%, Test_loss:2.309, Lr:1.00E-04
Epoch: 6, Train_acc:61.5%, Train_loss:2.361, Test_acc:64.6%, Test_loss:2.099, Lr:1.00E-04
Epoch: 7, Train_acc:62.4%, Train_loss:2.051, Test_acc:61.9%, Test_loss:1.911, Lr:1.00E-04
Epoch: 8, Train_acc:65.9%, Train_loss:1.718, Test_acc:69.0%, Test_loss:1.442, Lr:1.00E-04
Epoch: 9, Train_acc:68.1%, Train_loss:1.479, Test_acc:62.8%, Test_loss:1.540, Lr:1.00E-04
Epoch:10, Train_acc:68.1%, Train_loss:1.340, Test_acc:73.5%, Test_loss:1.332, Lr:1.00E-04
Epoch:11, Train_acc:67.5%, Train_loss:1.242, Test_acc:68.1%, Test_loss:1.071, Lr:1.00E-04
Epoch:12, Train_acc:70.6%, Train_loss:1.111, Test_acc:69.9%, Test_loss:1.219, Lr:1.00E-04
Epoch:13, Train_acc:68.4%, Train_loss:1.033, Test_acc:68.1%, Test_loss:1.286, Lr:1.00E-04
Epoch:14, Train_acc:69.9%, Train_loss:0.970, Test_acc:76.1%, Test_loss:0.925, Lr:1.00E-04
Epoch:15, Train_acc:76.1%, Train_loss:0.831, Test_acc:77.9%, Test_loss:0.654, Lr:1.00E-04
Epoch:16, Train_acc:77.0%, Train_loss:0.740, Test_acc:71.7%, Test_loss:0.926, Lr:1.00E-04
Epoch:17, Train_acc:72.8%, Train_loss:0.852, Test_acc:75.2%, Test_loss:0.708, Lr:1.00E-04
Epoch:18, Train_acc:76.1%, Train_loss:0.790, Test_acc:68.1%, Test_loss:0.741, Lr:1.00E-04
Epoch:19, Train_acc:77.7%, Train_loss:0.710, Test_acc:76.1%, Test_loss:0.765, Lr:1.00E-04
Epoch:20, Train_acc:77.0%, Train_loss:0.685, Test_acc:79.6%, Test_loss:0.645, Lr:1.00E-04
Finished Training 


四、总结


模型的核心是一个结合 ResNet 和 DenseNet 的混合网络:

ResNet 残差块:通过残差连接解决了梯度消失问题,使得网络可以训练得更深。

DenseNet 密集块:通过密集连接实现了特征重用,提高了参数效率。

混合模型:先通过一个 ResNet 残差块 提取特征,然后通过一个 DenseNet 密集块 进一步提取和重用特征,最后通过全局平均池化和全连接层进行分类。


网站公告

今日签到

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