基于pytorch搭建resnet18网络并训练数据集,loss曲线和精确度曲线振荡,怎么办?

import torch.nn as nn
import torch.utils.model_zoo as model_zoo
import urllib3
from tqdm import tqdm
from torchvision.models.resnet import model_urls, resnet18

__all__ = ['ResNet18', 'resnet18', 'BasicBlock']

url = 'https://download.pytorch.org/models/resnet18-5c106cde.pth'
http = urllib3.PoolManager()
response = http.request('GET', url, preload_content=False)
total_size = int(response.headers.get('content-length', 0))
block_size = 1024
with tqdm(total=total_size, unit='iB', unit_scale=True) as progress_bar:
    with open('resnet18-5c106cde.pth', 'wb') as f:
        for data in response.stream(block_size):
            progress_bar.update(len(data))
            f.write(data)


class BasicBlock(nn.Module):
    expansion = 1

    def __init__(self, inplanes, planes, stride=1, downsample=None):
        super(BasicBlock, self).__init__()
        self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=3, stride=stride, padding=1, bias=False)
        self.bn1 = nn.BatchNorm2d(planes)
        self.relu = nn.ReLU(inplace=True)
        self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=1, padding=1, bias=False)
        self.bn2 = nn.BatchNorm2d(planes)
        self.downsample = downsample
        self.stride = stride
        self.fc = nn.Linear(512 * self.expansion, 128)
        self.fc2 = nn.Linear(512 * self.expansion, 20)
        # 添加dropout层
        self.dropout = nn.Dropout(p=0.5)

    def forward(self, x):
        identity = x

        out = self.conv1(x)
        out = self.bn1(out)
        out = self.relu(out)

        out = self.conv2(out)
        out = self.bn2(out)

        # 添加dropout层
        out = self.dropout(out)

        if self.downsample is not None:
            identity = self.downsample(x)

        out += identity
        out = self.relu(out)

        return out


class ResNet18(nn.Module):

    def __init__(self, block=BasicBlock, layers=[2, 2, 2, 2], num_classes=10):
        super(ResNet18, self).__init__()
        self.inplanes = 64
        self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, bias=False)
        self.bn1 = nn.BatchNorm2d(64)
        self.relu = nn.ReLU(inplace=True)
        self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
        self.layer1 = self._make_layer(block, 64, layers[0])
        self.layer2 = self._make_layer(block, 128, layers[1], stride=2)
        self.layer3 = self._make_layer(block, 256, layers[2], stride=2)
        self.layer4 = self._make_layer(block, 512, layers[3], stride=2)
        self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
        self.fc = nn.Linear(512 * block.expansion, num_classes)  # 将输出维度修改为10
        self.softmax = nn.Softmax(dim=1)

        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
            elif isinstance(m, nn.BatchNorm2d):
                nn.init.constant_(m.weight, 1)
                nn.init.constant_(m.bias, 0)

    def _make_layer(self, block, planes, blocks, stride=1):
        downsample = None
        if stride != 1 or self.inplanes != planes * block.expansion:
            downsample = nn.Sequential(
                nn.Conv2d(self.inplanes, planes * block.expansion,
                          kernel_size=1, stride=stride, bias=False),
                nn.BatchNorm2d(planes * block.expansion),
            )

        layers = [block(self.inplanes, planes, stride, downsample)]
        self.inplanes = planes * block.expansion
        for i in range(1, blocks):
            layers.append(block(self.inplanes, planes))

        return nn.Sequential(*layers)

    def forward(self, x):
        x = self.conv1(x)
        x = self.bn1(x)
        x = self.relu(x)
        x = self.maxpool(x)

        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        x = self.layer4(x)

        x = self.avgpool(x)
        x = x.view(x.size(0), -1)
        x = self.fc(x)
        x = self.softmax(x)  # 使用softmax函数对输出结果进行归一化

        return x


def resnet18(pretrained=True, progress=True, **kwargs):
    model = ResNet18(BasicBlock, [2, 2, 2, 2], **kwargs)

    if pretrained:
        state_dict = model_zoo.load_url(model_urls['resnet18'], progress=progress)
        model.load_state_dict(state_dict)

    return model

这是resnet18网络搭建的代码

import torch
import random
from torch.utils.data import DataLoader
from torchvision import transforms
from torchvision.datasets import ImageFolder
from net import resnet18
import matplotlib.pyplot as plt
from typing import Any

# 定义超参数
batch_size = 16
learning_rate_backbone = 0.0001
learning_rate_fc = 0.002

num_epochs = 100

# 定义数据增强
train_transforms_list = [
    transforms.Compose([
        transforms.Resize((64, 64)),
        transforms.RandomHorizontalFlip(),
        transforms.ToTensor(),
        transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
    ]),
    transforms.Compose([
        transforms.Resize((64, 64)),
        transforms.RandomRotation(degrees=15),
        transforms.ToTensor(),
        transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
    ]),
    transforms.Compose([
        transforms.Resize((64, 64)),
        transforms.RandomCrop(size=64, padding=4),
        transforms.ToTensor(),
        transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
    ]),
]

test_transform = transforms.Compose([
    transforms.Resize((64, 64)),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
# 加载数据集
train_datasets_list = [
    ImageFolder('train', transform=train_transforms_list[0]),
    ImageFolder('train', transform=train_transforms_list[1]),
    ImageFolder('train', transform=train_transforms_list[2])
]

test_dataset = ImageFolder('test', transform=test_transform)

train_loaders_list = [
    DataLoader(train_datasets_list[0], batch_size=batch_size, shuffle=True),
    DataLoader(train_datasets_list[1], batch_size=batch_size, shuffle=True),
    DataLoader(train_datasets_list[2], batch_size=batch_size, shuffle=True)
]

test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)

# 定义模型
model = resnet18(pretrained=False)
num_ftrs = model.fc.in_features
model.fc = torch.nn.Sequential(
    torch.nn.Linear(num_ftrs, 128),
    torch.nn.ReLU(),
    torch.nn.Linear(128, 10)
)

criterion = torch.nn.CrossEntropyLoss()
backbone_params = list(model.parameters())
fc_params = list(model.fc.parameters())

weight_decay = 1e-4
optimizer = torch.optim.Adam([
    {'params': model.fc.parameters(), 'lr': learning_rate_fc},
    {'params': model.layer4.parameters()},
    {'params': model.layer3.parameters()},
    {'params': model.layer2.parameters()},
    {'params': model.layer1.parameters()},
    {'params': model.conv1.parameters()},
], lr=learning_rate_backbone, weight_decay=weight_decay)

# 添加学习率调度器
step_size = 10
gamma = 0.1
scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=step_size, gamma=gamma)

# 定义四个列表分别存储4个指标的值
train_losses = []
train_accs = []
test_losses = []
test_accs = []

# 训练模型
device = torch.device('cpu')
model = model.to(device)

for epoch in range(num_epochs):
    train_transform = random.choice(train_transforms_list)
    train_dataset = ImageFolder('train', transform=train_transform)
    train_loader: DataLoader[Any] = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)

    model.train()
    train_loss = 0.0
    train_acc = 0.0
    for i, (inputs, labels) in enumerate(train_loader):
        inputs = inputs.to(device)
        labels = labels.to(device)

        optimizer.zero_grad()

        outputs = model(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        train_loss += loss.item() * inputs.size(0)
        _, preds = torch.max(outputs, 1)
        train_acc += torch.sum(preds == labels.data)

    train_loss = train_loss / len(train_dataset)
    train_acc = train_acc / len(train_dataset)

    print('Epoch: [{}/{}], Train Loss: {:.4f}, Train Acc: {:.4f}, Train Transform: {}'.format(epoch + 1, num_epochs,
                                                                                          train_loss, train_acc,
                                                                                          train_transform))

    model.eval()
    test_loss = 0.0
    test_acc = 0.0
    for i, (inputs, labels) in enumerate(test_loader):
        inputs = inputs.to(device)
        labels = labels.to(device)

        outputs = model(inputs)
        loss = criterion(outputs, labels)

        test_loss += loss.item() * inputs.size(0)
        _, preds = torch.max(outputs, 1)
        test_acc += torch.sum(preds == labels.data)

    test_loss = test_loss / len(test_dataset)
    test_acc = test_acc / len(test_dataset)

    print('Epoch: [{}/{}], Test Loss: {:.4f}, Test Acc: {:.4f}'.format(epoch + 1, num_epochs, test_loss, test_acc))

    # 更新学习率
    scheduler.step()

    # 将得到的指标添加到对应列表
    train_losses.append(train_loss)
    train_accs.append(train_acc)
    test_losses.append(test_loss)
    test_accs.append(test_acc)
# 绘制精度曲线loss曲线
plt.figure(figsize=(10, 3))
plt.subplot(1, 2, 1)
plt.title('Loss')
plt.plot(train_losses, label='Train Loss')
plt.plot(test_losses, label='Test Loss')
plt.legend()
plt.subplot(1, 2, 2)
plt.title('Accuracy')
plt.plot(train_accs, label='Train Acc')
plt.plot(test_accs, label='Test Acc')
plt.legend()
plt.show()

# 保存模型
torch.save(model.state_dict(), 'resnet18_model.pth')

这是调用resnet18网络,训练自己10个人每个人100个样本一共1000个时频图样本的数据集,为什么生成的loss曲线和精确度曲线振荡呢?

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,您可以参考下面的代码: ```python import torch.nn as nn class BasicBlock(nn.Module): expansion = 1 def __init__(self, in_planes, planes, stride=1): super(BasicBlock, self).__init__() self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=3, stride=stride, padding=1, bias=False) self.bn1 = nn.BatchNorm2d(planes) self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=1, padding=1, bias=False) self.bn2 = nn.BatchNorm2d(planes) self.shortcut = nn.Sequential() if stride != 1 or in_planes != self.expansion*planes: self.shortcut = nn.Sequential( nn.Conv2d(in_planes, self.expansion*planes, kernel_size=1, stride=stride, bias=False), nn.BatchNorm2d(self.expansion*planes) ) def forward(self, x): out = nn.ReLU()(self.bn1(self.conv1(x))) out = self.bn2(self.conv2(out)) out += self.shortcut(x) out = nn.ReLU()(out) return out class ResNet(nn.Module): def __init__(self, block, num_blocks, num_classes=10): super(ResNet, self).__init__() self.in_planes = 64 self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False) self.bn1 = nn.BatchNorm2d(64) self.layer1 = self._make_layer(block, 64, num_blocks[0], stride=1) self.layer2 = self._make_layer(block, 128, num_blocks[1], stride=2) self.layer3 = self._make_layer(block, 256, num_blocks[2], stride=2) self.layer4 = self._make_layer(block, 512, num_blocks[3], stride=2) self.linear = nn.Linear(512*block.expansion, num_classes) def _make_layer(self, block, planes, num_blocks, stride): strides = [stride] + [1]*(num_blocks-1) layers = [] for stride in strides: layers.append(block(self.in_planes, planes, stride)) self.in_planes = planes * block.expansion return nn.Sequential(*layers) def forward(self, x): out = nn.ReLU()(self.bn1(self.conv1(x))) out = self.layer1(out) out = self.layer2(out) out = self.layer3(out) out = self.layer4(out) out = nn.AvgPool2d(4)(out) out = out.view(out.size(0), -1) out = self.linear(out) return out def ResNet18(): return ResNet(BasicBlock, [2,2,2,2]) ``` 这是一个基于PyTorch搭建ResNet18模型的例子。其中,BasicBlock是ResNet18的基本模块,ResNet是整个网络的结构体,包含多个BasicBlock,_make_layer函数用于构建多层BasicBlock,forward函数定义前向传播过程,ResNet18函数返回一个ResNet18模型的实例。您可以根据自己的需求修改或扩展该模型

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值