我有一个由 3 个 conv2D 层和 ReLU 激活组成的模型。它将标准化为区间 [0,1] 的灰度图像作为输入。输入图像有一些黑色区域、一些白色区域和其他区域。
但是,输出动态范围被压缩到 [0.4,0.401]。所有图像都是灰色的,即使在重新规范化将它们带回 [0,255] 之后也是如此。
我有点迷失,我不明白为什么会出现这种情况。
我尝试过的:
- 情节梯度直方图,尽管我不确定如何解释它。对于某些参数,模型似乎在几个时期后停止学习。对于其他层,一层会停止学习。
- 修改内核大小
- 添加更多层
- 尝试很多不同的学习率值
下面您将找到我的模型和我的训练循环。
class Model(nn.Module):
def __init__(self):
super().__init__()
self.model = nn.Sequential(
nn.Conv2d(in_channels=1, out_channels=64, kernel_size=13, stride=1, padding=5),
nn.ReLU(True),
nn.Conv2d(in_channels=64, out_channels=32, kernel_size=3, stride=1, padding=2),
nn.ReLU(True),
nn.Conv2d(in_channels=32, out_channels=1, kernel_size=5, stride=1, padding=2),
)
def forward(self, input_image):
output_image = self.model(input_image)
return output_image
def train_one_epoch(
model: nn.Module,
dataloader: torch.utils.data.DataLoader,
loss_fn: nn.MSELoss,
optimizer: optim.Adam,
epoch_index,
scaler: amp.GradScaler,
):
model.train()
running_loss = 0
last_loss = 0
batch_index = 0
for batch, loader in enumerate(train_dataloader):
input_img = loader['input'].to(device, non_blocking=True)
gt_img = loader['gt'].to(device, non_blocking=True)
model.zero_grad(set_to_none=True)
with amp.autocast():
output = model(input_img)
loss = loss_fn(output, gt_img)
scaler.scale(loss).backward()
scaler.step(optimizer)
scaler.update()
running_loss += loss.item()
if batch_index % 100 == 99:
last_loss = running_loss / 1000
running_loss = 0.0
batch_index += 1
return last_loss
任何感谢帮助。如果需要更多信息,请告诉我。
以下是的模型输出范围限于一小段的原因以及如何解决该问题:
- 激活函数缺失: 的模型架构中缺少输出层的激活函数。目前,的模型应用三个卷积层,然后是 ReLU 激活。这会导致线性输出,并且由于的输入在 [0, 1] 范围内进行归一化,因此模型的输出也倾向于保持在有限的范围内。在最后一层添加一个 sigmoid 或 tanh 激活函数可以帮助扩展输出范围。
- sigmoid 会将输出压缩到 [0, 1] 范围内,这对于的情况是合适的,因为的目标输出也是灰度图像。
-
tanh 会将输出压缩到 [-1, 1] 范围内,在训练过程中可能需要将其重新缩放回 [0, 1] 范围。
-
权重初始化: 如果即使添加了激活函数,的输出范围仍然很小,那么问题可能出在权重初始化上。尝试使用不同的初始化技术来查看它们是否对输出范围有影响。PyTorch 提供了许多初始化函数,例如
torch.nn.init.kaiming_normal_()
或torch.nn.init.xavier_uniform_()
,这些函数可以帮助设置适合 ReLU 激活的权重。 -
数据分布: 提到的输入图像有一些黑色、白色和其他区域。如果这些区域之间的对比度较低或数据集的整体动态范围有限,则可能会导致模型输出范围较小。请确保的数据具有足够的对比度和变化以使模型能够学习有意义的表示。还可以尝试使用直方图均衡化等技术来增强训练数据的对比度。
-
学习率: 虽然尝试了许多不同的学习率值,但确保使用合适的学习率仍然很重要。学习率过高或过低都会导致收敛问题。考虑使用学习率调度器来在训练过程中调整学习率。
以下是应该进行的代码更改以解决这些问题:
class Model(nn.Module):
def __init__(self):
super().__init__()
self.model = nn.Sequential(
nn.Conv2d(in_channels=1, out_channels=64, kernel_size=13, stride=1, padding=5),
nn.ReLU(True),
nn.Conv2d(in_channels=64, out_channels=32, kernel_size=3, stride=1, padding=2),
nn.ReLU(True),
nn.Conv2d(in_channels=32, out_channels=1, kernel_size=5, stride=1, padding=2),
nn.Sigmoid() # 添加 sigmoid 激活函数
)
def forward(self, input_image):
output_image = self.model(input_image)
return output_image
# ...(其余代码保持不变)
为的模型尝试这些更改:
- 添加 sigmoid 或 tanh 激活函数。
- 尝试不同的权重初始化技术。
- 验证的数据是否具有足够的对比度和变化。
- 微调学习率并考虑使用学习率调度器。
通过解决这些问题,应该能够扩展模型的输出范围并生成更生动的灰度图像。
标签:python,deep-learning,pytorch,neural-network,computer-vision From: 77273071