图像去噪是指减少或去除图像中噪声的过程,噪声是图像中不希望存在的随机变化或干扰。作为使用PyTorch进行深度学习的入门案例,主要了解深度学习任务所需要的整体流程,不熟悉其中的程序设计和编写问题不大,只要求了解每个过程需要做的事情和步骤就好。
一、数据集准备
MNIST是一个手写数字的图片数据库,它有60000个训练样本集和10000个测试样本集。(可能需要魔法,看运气)
下载地址:https://github.com/cvdfoundation/mnist?tab=readme-ov-file
这几个依次是:训练图片集、训练标签集、测试图片集、测试标签集。
二、数据集简介
打开后看到的是一堆数字,并不是手写数字的图片,如下图所示:
结合数据集的文件结构:
从数据集文件结构可以看出,从偏移量为0016,才是像素信息的开始。前面的4*32bit分别是magic number、number of images、number of rows、number of columns,即魔数、图像数量、图像行数和图像列数。所有的图片都是 28×28 ,也就是每幅图片都有28×28个像素。
魔数:是一个校验数,用来判断这个文件是不是MNIST里面的 train-images-idx3-ubyte 文件
读取数据集中的数据并显示图片(其中的某一张)
三、Unet模型
不懂没事,我也不懂(doge)呈U字形
Unet输入和输出大小是同样的维度(了解这个就好)
模型代码:仅供参考(了解个过程,知道有这个东西即可)
import torch
class Unet(torch.nn.Module):
def __init__(self):
super(Unet, self).__init__()
'''
2D卷积层;
输入通道数为1,输出通道数为32,
卷积核大小为3x3,
填充为1,填充为1可以确保在卷积操作时输入和输出的图像尺寸在宽度和高度上保持不变(假设步长为1)
MaxPool2d 最大池化层,池化核大小为2x2,步长为2。对输入进行下采样,将图像的宽度和高度缩小一半,用于减少数据的维度,同时保留重要的特征信息
'''
self.first_block_down = torch.nn.Sequential(
torch.nn.Conv2d(in_channels=1, out_channels=32, kernel_size=3, padding=1), torch.nn.GELU(),
torch.nn.MaxPool2d(kernel_size=2, stride=2)
)
self.second_block_down = torch.nn.Sequential(
torch.nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, padding=1), torch.nn.GELU(),
torch.nn.MaxPool2d(kernel_size=2, stride=2)
)
# 定义网络的瓶颈部分
self.latent_space_block = torch.nn.Sequential(
torch.nn.Conv2d(in_channels=64, out_channels=128, kernel_size=3, padding=1), torch.nn.GELU(),
)
self.second_block_up = torch.nn.Sequential(
torch.nn.Upsample(scale_factor=2),
torch.nn.Conv2d(in_channels=128, out_channels=64, kernel_size=3, padding=1), torch.nn.GELU(),
)
self.first_block_up = torch.nn.Sequential(
torch.nn.Upsample(scale_factor=2),
torch.nn.Conv2d(in_channels=64, out_channels=32, kernel_size=3, padding=1), torch.nn.GELU(),
)
# 定义最后卷积层
self.convUP_end = torch.nn.Sequential(
torch.nn.Conv2d(in_channels=32, out_channels=1, kernel_size=3, padding=1),
torch.nn.Tanh() # 一种激活函数,将输出的值映射到 - 1到1之间
)
'''
用于定义神经网络的前向传播过程。
前向传播就是将输入数据按照定义好的网络结构进行计算,
得到输出结果的过程。
'''
def forward(self, img_tensor):
image = img_tensor
image = self.first_block_down(image)
image = self.second_block_down(image)
image = self.latent_space_block(image)
image = self.second_block_up(image)
image = self.first_block_up(image)
image = self.convUP_end(image)
return image
if __name__ == '__main__': # main是Python进⾏单⽂件测试的技巧
image = torch.randn(size=(5, 1, 28, 28))
unet_model = Unet()
torch.save(unet_model, './unet_model.pth')
# 通过⼀个main架构标识了可以在单个⽂件中对⽂件进⾏测试
1️⃣在这个 if 语句块内部的代码只有当这个脚本直接被执行时才会运行,而当这个脚本被导入到其他脚本中时,这部分代码不会被执行
2️⃣torch.randn 函数创建了一个随机张量
5表示有5个样本
1表示每个样本的通道数为1(灰度图像,通道数通常为1;彩色图像,通道数通常为3,如RGB图像)
28和28表示每个样本图像的高度和宽度都是28像素
3️⃣torch.save 保存模型,后续可以加载这个模型并继续训练或者用于预测任务。可以使用torch.load函数加载这个保存的模型文件,然后将图像数据输入到加载后的模型。
四、损失函数及优化函数
(目前了解有这两个函数即可)
1️⃣均方损失函数(MSELoss):Mean Squared Error Loss
计算预测值和真实值之间的欧式距离。预测值和真实值越接近,两者的均方差就越小,均方差函数常用于线性回归模型的计算。
欧式距离:就是平常理解的距离。这里主要是指数据点之间的相似性
loss = torch.nn.MSELoss(reduction="sum")(pred, y_batch)
'''
MSELoss默认的归约方式是“mean”(计算平均值)
这里为“sum”(将所有样本的均方误差求和)
pred:预测值
y_batch:真实值
'''
2️⃣Adam优化函数
optimizer = torch.optim.Adam(model.parameters(), lr=2e-5)
'''
model.parameters()是一个生成器(generator),它返回模型 model的所有可学习参数(例如神经网络中的权重和偏置等)。
Adam优化器将对这些参数进行优化操作。
lr(learning rate,学习率)
'''
五、开训
1️⃣运行代码后,可能会遇到这样的报错
根据提示,可以导入
import torch._dynamo
然后在代码设置
torch._dynamo.config.suppress_errors = True
2️⃣结果展示
这是前面刚训练的图片
这是训练到几百个的时候,还是可以看到明显差别的,噪点少了很多。
训练过程:
完整代码