深度学习与神经网络-2

卷积神经网络(离焦图像去模糊)

卷积网络介绍

卷积过程

在这里插入图片描述
对于计算卷积之后的大小,需要考虑图像的尺寸n,卷积核的大小f,图像的填充p,步长s。
在这里插入图片描述

池化

主要目的:是减小特征图的空间维度,同时保留重要的特征信息。具体来分析具有以下功能:
特征降维:池化操作可以减小特征图的空间尺寸,从而降低整个网络的参数量和计算量。加快网络的训练和推理速度。
位置不变性:池化操作具有一定的平移不变性,无论特征在图像中的位置如何变化,池化操作都能够保留其相对位置信息。
过拟合控制:池化操作可以通过减少特征图的维度和参数数量来控制模型的复杂性,从而降低过拟合的风险。池化操作的降维作用可以减少参数的数量,有助于提高模型的泛化能力。

经典神经网络结构介绍

LeNet-5

在这里插入图片描述
网络结构的概要:
输入层:图像通常被标准化为32x32像素的灰度图像作为网络的输入。
卷积层1:第一层卷积层有6个卷积核(滤波器),每个卷积核大小为5x5,步长为1,通过滑窗操作对输入图像进行特征提取,输出特征图尺寸会因为有效感受野而减小至28x28。
每个卷积核后面都会接一个sigmoid激活函数,增加网络的非线性表达能力。
池化层1:使用平均池化(pooling)操作,窗口大小为2x2,步长也为2,进行下采样,输出特征图尺寸进一步减小至14x14。
卷积层2:第二个卷积层有16个卷积核,每个卷积核大小仍为5x5,同样使用sigmoid激活函数。
这一步之后输出的特征图尺寸变为10x10。
池化层2:再次进行池化操作,窗口大小和步长同上,输出尺寸为5x5。
全连接层1:将前一层池化层的结果展平成一维向量,然后连接到一个全连接层,该层有120个神经元,并且每个神经元后都跟随sigmoid激活函数。
全连接层2:又一个全连接层,拥有84个神经元,同样使用sigmoid激活函数。
输出层:最后一层是全连接层,对应于最终分类任务,对于MNIST数据集,该层会有10个神经元(对应0-9十个数字类别),并通常使用softmax函数生成概率分布,表示每个类别的预测可能性。

AlexNet

在这里插入图片描述
输入层:AlexNet 的输入是固定大小的图像,通常为 227x227 像素的 RGB 图像。
卷积层1:第一个卷积层有 96 个卷积核(过滤器),大小为 11x11,步幅为 4,使用 ReLU 激活函数。这个卷积层负责提取图像的低级特征。
池化层1:一个 3x3 大小的最大池化层,步幅为 2。这个池化层的作用是减小特征图的尺寸。
卷积层2:第二个卷积层有 256 个卷积核,大小为 5x5,使用 ReLU 激活函数。这个卷积层进一步提取图像的中级特征。
池化层2:一个 3x3 大小的最大池化层,步幅为 2。
卷积层3-4:两个连续的卷积层,每个卷积层有 384 个卷积核,大小为 3x3,使用 ReLU 激活函数。这些卷积层继续提取图像的高级特征。
卷积层5:第五个卷积层有 256 个卷积核,大小为 3x3,使用 ReLU 激活函数。这个卷积层进一步提取图像的高级特征。
池化层3:一个 3x3 大小的最大池化层,步幅为 2。
全连接层1:一个具有 4096 个神经元的全连接层,使用 ReLU 激活函数。
全连接层2:一个具有 4096 个神经元的全连接层,使用 ReLU 激活函数。
全连接层3:一个具有 1000 个神经元的全连接层,对应于 ImageNet 数据集中的 1000 个类别。这个全连接层的输出通过 Softmax 函数进行分类预测。

vgg16

在这里插入图片描述
输入层:VGG16 模型的输入是固定大小的图像,通常为 224x224 像素的 RGB 图像。
卷积层1-2:两个连续的卷积层,每个卷积层都有 64 个卷积核(过滤器)大小为 3x3,使用 ReLU 激活函数。这两个卷积层的作用是提取图像的低级特征。
池化层1:一个 2x2 大小的最大池化层,其步幅为 2。这个池化层的作用是减小特征图的尺寸并保留重要的特征。
卷积层3-4:两个连续的卷积层,每个卷积层都有 128 个卷积核(过滤器)大小为 3x3,使用 ReLU 激活函数。这两个卷积层进一步提取图像的中级特征。
池化层2:一个 2x2 大小的最大池化层,其步幅为 2。
卷积层5-7:三个连续的卷积层,每个卷积层都有 256 个卷积核(过滤器)大小为 3x3,使用 ReLU 激活函数。这些卷积层继续提取图像的中级特征。
池化层3:一个 2x2 大小的最大池化层,其步幅为 2。
卷积层8-9:两个连续的卷积层,每个卷积层都有 512 个卷积核(过滤器)大小为 3x3,使用 ReLU 激活函数。这些卷积层进一步提取图像的高级特征。
池化层4:一个 2x2 大小的最大池化层,其步幅为 2。
卷积层10-11:两个连续的卷积层,每个卷积层都有 512 个卷积核(过滤器)大小为 3x3,使用 ReLU 激活函数。这些卷积层继续提取图像的高级特征。
池化层5:一个 2x2 大小的最大池化层,其步幅为 2。
全连接层1-2:两个全连接层,每个全连接层有 4096 个神经元,使用 ReLU 激活函数。这些全连接层将卷积层输出的特征映射转换为固定长度的特征向量。
全连接层3:一个全连接层,有 1000 个神经元,对应于 ImageNet 数据集中的 1000 个类别。这个全连接层的输出通过 Softmax 函数进行分类预测。

残差神经网络

问题:梯度消失,梯度爆炸
在这里插入图片描述
在这里插入图片描述
残差网络:
在这里插入图片描述
经典残差网络:Deep Residual Learning for Image Recognition Kaiming He, Xiangyu Zhang, Shaoqing Ren, Jian Sun
[https://arxiv.org/abs/1512.03385]

使用卷积神经网络实现模糊图像去模糊

数据集介绍

使用圆盘点扩散函数(psf)对原始进行模糊,得到需要复原的图像,以模糊图像和原始图像为训练数据,实现模糊图像到原始图像的端到端映射。
在这里插入图片描述
在这里插入图片描述

训练数据加载

class ImagePairDataset(Dataset):
    def __init__(self, root_dir, transform=None):
        self.root_dir = root_dir
        self.transform = transform
        self.file_list = os.listdir(os.path.join(root_dir, "images"))#获取images下的所有图片名称
    def __len__(self):
        return len(self.file_list)

    def __getitem__(self, index):
        filename = self.file_list[index]
        image_path = os.path.join(self.root_dir, "images", filename)#获取图片地址
        image = self.load_image(image_path)

        label_path = os.path.join(self.root_dir, "labels", filename)
        label = self.load_image(label_path)


        if self.transform:
            image = self.transform(image)
            label = self.transform(label)
        return image, label

    def load_image(self, image_path):
        image = cv2.imread(image_path,0)
        image = cv2.resize(image,(256,256))
        return image

网络结构模型

class VGG16(nn.Module):
    def __init__(self,channels):
        super(VGG16, self).__init__()
        self.features = nn.Sequential(
            nn.Conv2d(channels, 64, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv2d(64, 64, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2, stride=2),
            nn.Conv2d(64, 128, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv2d(128, 128, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2, stride=2),
            nn.ConvTranspose2d(128,128,kernel_size=3,padding=1, stride=2, output_padding=1),
            nn.ConvTranspose2d(128, 128, kernel_size=3, padding=1),
            nn.ConvTranspose2d(128, 64, kernel_size=3, padding=1),
            nn.ConvTranspose2d(64, 64, kernel_size=3, padding=1, stride=2, output_padding=1),
            nn.ConvTranspose2d(64, 64, kernel_size=3, padding=1),
            nn.ConvTranspose2d(64, channels, kernel_size=3, padding=1),
        )
    def forward(self, x):
        x = self.features(x)
        return x

在这里插入图片描述
通过端到端的网络结构模型进行图像的去模糊,特征提取部分借鉴了VGG16网络的前两个block,图像重建的网络层使用对称的反卷积层。

训练循环

def train(model, train_loader, criterion, optimizer, num_epochs):
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    model.to(device)
    min_loss = float('inf')
    for epoch in range(num_epochs):
        running_loss = 0.0
        for images, labels in train_loader:
            images = images.to(device)
            labels = labels.to(device)
            optimizer.zero_grad()

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

            running_loss += loss.item()
            scheduler.step()  # 在每个epoch结束时更新学习率
        if running_loss < min_loss:
            # 更新最小损失值
            min_loss = running_loss
            # 保存模型
            torch.save(model.state_dict(), 'best_model.pt')

        print(f"Epoch {epoch+1}/{num_epochs}, Loss: {running_loss/len(train_loader)}")
    torch.save(model.state_dict(), 'last_model.pt')
    print("Training completed.")

评估测试

def _test(model, test_loader):
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    model.eval()  # 将模型设置为评估模式
    model.to(device)
    total_loss = 0
    with torch.no_grad():
        for images,  _ in test_loader:
            images = images.to(device)
            outputs = model(images)  # 前向传播
            original_image = images.squeeze().cpu()
            restored_image = outputs.squeeze().cpu()
            fig, axs = plt.subplots(1, 2)
            axs[0].imshow(original_image, cmap='gray')
            axs[0].set_title('Originaldasd Image')
            axs[0].axis('off')
            axs[1].imshow(restored_image, cmap='gray')
            axs[1].set_title('Restored Image')
            axs[1].axis('off')
            plt.show()
    avg_loss = total_loss / len(test_loader)
    return avg_loss

训练参数设置

# 加载训练数据
train_data = ImagePairDataset("train", transform=transforms.ToTensor())
train_loader = DataLoader(train_data, batch_size=4, shuffle=True)
channels = 1
model = VGG16(channels)
for m in model.features:
    if isinstance(m, (nn.Conv2d, nn.ConvTranspose2d)):
        init.xavier_uniform_(m.weight)
        if m.bias is not None:
            init.zeros_(m.bias)
criterion = nn.MSELoss()
optimizer = optim.Adam(model.parameters(), lr=1e-4)
# 设置余弦衰减调度器
T_max = 20  # 设置周期的一半,即余弦函数半个周期的epochs数
eta_min = 0  # 学习率衰减时的最小值,默认为0
scheduler = CosineAnnealingLR(optimizer, T_max=T_max, eta_min=eta_min)
# Step 6: 开始训练
num_epochs = 3000
train(model, train_loader, criterion, optimizer, num_epochs)
model = VGG16(channels)
checkpoint = torch.load('best_model.pt')
optimizer = optim.Adam(model.parameters(), lr=1e-4)
# 设置余弦衰减调度器
T_max = 20  # 设置周期的一半,即余弦函数半个周期的epochs数
eta_min = 0  # 学习率衰减时的最小值,默认为0
scheduler = CosineAnnealingLR(optimizer, T_max=T_max, eta_min=eta_min)
# 如果需要,还可以加载学习率调度器的状态
# scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=10, gamma=0.1)
# scheduler.load_state_dict(checkpoint['scheduler_state_dict'])
# 设置模型为训练模式
model.train()
train(model, train_loader, criterion, optimizer, num_epochs)
模糊图像复原效果

在这里插入图片描述
在这里插入图片描述

  • 23
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值