Pytorch模型虽然损失不断减少,但仍停留在0.5

问题描述 投票:0回答:1

这正在使用PyTorch

我一直在尝试在图像上实现UNet模型,但是,我的模型精度始终是精确的0.5。损失确实减少了。

我还检查了班级不平衡状况。我也尝试过学习速度。学习率会影响损失,但不会影响准确性。

我的[[体系结构下面(从这里开始)]

""" `UNet` class is based on https://arxiv.org/abs/1505.04597 The U-Net is a convolutional encoder-decoder neural network. Contextual spatial information (from the decoding, expansive pathway) about an input tensor is merged with information representing the localization of details (from the encoding, compressive pathway). Modifications to the original paper: (1) padding is used in 3x3 convolutions to prevent loss of border pixels (2) merging outputs does not require cropping due to (1) (3) residual connections can be used by specifying UNet(merge_mode='add') (4) if non-parametric upsampling is used in the decoder pathway (specified by upmode='upsample'), then an additional 1x1 2d convolution occurs after upsampling to reduce channel dimensionality by a factor of 2. This channel halving happens with the convolution in the tranpose convolution (specified by upmode='transpose') Arguments: in_channels: int, number of channels in the input tensor. Default is 3 for RGB images. Our SPARCS dataset is 13 channel. depth: int, number of MaxPools in the U-Net. During training, input size needs to be (depth-1) times divisible by 2 start_filts: int, number of convolutional filters for the first conv. up_mode: string, type of upconvolution. Choices: 'transpose' for transpose convolution """ class UNet(nn.Module): def __init__(self, num_classes, depth, in_channels, start_filts=16, up_mode='transpose', merge_mode='concat'): super(UNet, self).__init__() if up_mode in ('transpose', 'upsample'): self.up_mode = up_mode else: raise ValueError("\"{}\" is not a valid mode for upsampling. Only \"transpose\" and \"upsample\" are allowed.".format(up_mode)) if merge_mode in ('concat', 'add'): self.merge_mode = merge_mode else: raise ValueError("\"{}\" is not a valid mode for merging up and down paths.Only \"concat\" and \"add\" are allowed.".format(up_mode)) # NOTE: up_mode 'upsample' is incompatible with merge_mode 'add' if self.up_mode == 'upsample' and self.merge_mode == 'add': raise ValueError("up_mode \"upsample\" is incompatible with merge_mode \"add\" at the moment " "because it doesn't make sense to use nearest neighbour to reduce depth channels (by half).") self.num_classes = num_classes self.in_channels = in_channels self.start_filts = start_filts self.depth = depth self.down_convs = [] self.up_convs = [] # create the encoder pathway and add to a list for i in range(depth): ins = self.in_channels if i == 0 else outs outs = self.start_filts*(2**i) pooling = True if i < depth-1 else False down_conv = DownConv(ins, outs, pooling=pooling) self.down_convs.append(down_conv) # create the decoder pathway and add to a list # - careful! decoding only requires depth-1 blocks for i in range(depth-1): ins = outs outs = ins // 2 up_conv = UpConv(ins, outs, up_mode=up_mode, merge_mode=merge_mode) self.up_convs.append(up_conv) self.conv_final = conv1x1(outs, self.num_classes) # add the list of modules to current module self.down_convs = nn.ModuleList(self.down_convs) self.up_convs = nn.ModuleList(self.up_convs) self.reset_params() @staticmethod def weight_init(m): if isinstance(m, nn.Conv2d): #https://prateekvjoshi.com/2016/03/29/understanding-xavier-initialization-in-deep-neural-networks/ ##Doc: https://pytorch.org/docs/stable/nn.init.html?highlight=xavier#torch.nn.init.xavier_normal_ init.xavier_normal_(m.weight) init.constant_(m.bias, 0) def reset_params(self): for i, m in enumerate(self.modules()): self.weight_init(m) def forward(self, x): encoder_outs = [] # encoder pathway, save outputs for merging for i, module in enumerate(self.down_convs): x, before_pool = module(x) encoder_outs.append(before_pool) for i, module in enumerate(self.up_convs): before_pool = encoder_outs[-(i+2)] x = module(before_pool, x) # No softmax is used. This means we need to use # nn.CrossEntropyLoss is your training script, # as this module includes a softmax already. x = self.conv_final(x) return x
参数是:

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') x,y = train_sequence[0] ; batch_size = x.shape[0] model = UNet(num_classes = 2, depth=5, in_channels=5, merge_mode='concat').to(device) optim = torch.optim.Adam(model.parameters(),lr=0.01, weight_decay=1e-3) criterion = nn.BCEWithLogitsLoss() #has sigmoid internally epochs = 1000

用于训练的

功能

是:import torch.nn.functional as f def train_model(epoch,train_sequence): """Train the model and report validation error with training error Args: model: the model to be trained criterion: loss function data_train (DataLoader): training dataset """ model.train() for idx in range(len(train_sequence)): X, y = train_sequence[idx] images = Variable(torch.from_numpy(X)).to(device) # [batch, channel, H, W] masks = Variable(torch.from_numpy(y)).to(device) outputs = model(images) print(masks.shape, outputs.shape) loss = criterion(outputs, masks) optim.zero_grad() loss.backward() # Update weights optim.step() # total_loss = get_loss_train(model, data_train, criterion)
我的

计算损失和准确性的功能]如下:

def get_loss_train(model, train_sequence): """ Calculate loss over train set """ model.eval() total_acc = 0 total_loss = 0 for idx in range(len(train_sequence)): with torch.no_grad(): X, y = train_sequence[idx] images = Variable(torch.from_numpy(X)).to(device) # [batch, channel, H, W] masks = Variable(torch.from_numpy(y)).to(device) outputs = model(images) loss = criterion(outputs, masks) preds = torch.argmax(outputs, dim=1).float() acc = accuracy_check_for_batch(masks.cpu(), preds.cpu(), images.size()[0]) total_acc = total_acc + acc total_loss = total_loss + loss.cpu().item() return total_acc/(len(train_sequence)), total_loss/(len(train_sequence))

Edit

:运行(调用)功能的代码:
for epoch in range(epochs): train_model(epoch, train_sequence) train_acc, train_loss = get_loss_train(model,train_sequence) print("Train Acc:", train_acc) print("Train loss:", train_loss)
有人可以帮我确定为什么精度总是精确到0.5吗?

Edit-2

根据要求,accuracy_check_for_batch功能在这里:

def accuracy_check_for_batch(masks, predictions, batch_size): total_acc = 0 for index in range(batch_size): total_acc += accuracy_check(masks[index], predictions[index]) return total_acc/batch_size

def accuracy_check(mask, prediction): ims = [mask, prediction] np_ims = [] for item in ims: if 'str' in str(type(item)): item = np.array(Image.open(item)) elif 'PIL' in str(type(item)): item = np.array(item) elif 'torch' in str(type(item)): item = item.numpy() np_ims.append(item) compare = np.equal(np_ims[0], np_ims[1]) accuracy = np.sum(compare) return accuracy/len(np_ims[0].flatten())

这是使用PyTorch的,我一直试图在图像上实现UNet模型,但是,我的模型精度始终是精确的0.5。损失确实减少了。我还检查了班级不平衡状况。我有...
image-processing deep-learning computer-vision pytorch image-segmentation
1个回答
0
投票
我发现了错误。
© www.soinside.com 2019 - 2024. All rights reserved.