Я в основном слежу за этим проектом, но делаю пиксельную классификацию. У меня 8 классов и 9 изображений группы. Мои изображения сгруппированы в 9x128x128. Моя потеря не уменьшается, и точность тренировок не сильно колеблется. Я предполагаю, что у меня что-то не так с моделью. Любой совет высоко ценится! Я получаю точность не менее 91%, используя случайный лес.
Мои занятия крайне несбалансированы, поэтому я попытался откорректировать вес тренировок, исходя из доли классов в данных тренировок.
# get model
learning_rate = 0.0001
model = unet.UNetSmall(8)
optimizer = optim.Adam(model.parameters(), lr=learning_rate)
# set up weights based on data proportion
weights = np.array([0.79594768, 0.07181202, 0.02347426, 0.0042031, 0.00366211, 0.00764327, 0.07003923, 0.02321833])
weights = (1 - weights)/7
print('Weights of training data based on proportion of the training labels. Not compted here')
print(weights)
print(sum(weights))
criterion = nn.CrossEntropyLoss(weight = weight)
lr_scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=5, gamma=0.1)
Вес данных обучения, основанный на пропорции меток обучения.
Здесь не указано [0,02915033 0,13259828 0,13950368 0,1422567
0,14233398 0,14176525
0,13285154 0,13954024]
1,0000000000000002
Я нормализовал данные с помощью функции transforms.functional.normalize. Я рассчитал среднее значение и стандартное отклонение обучающих данных и добавил это увеличение в свой загрузчик данных.
dataset_train = data_utils.SatIn(data_path, 'TrainValTest.csv', 'train', transform=transforms.Compose([aug.ToTensorTarget(), aug.NormalizeTarget(mean=popmean, std=popstd)]))
Я увеличил свои тренировочные данные при предварительной обработке, поворачивая и переворачивая изображения. 1 сетка изображений затем стала 8.
Я проверил, что мои данные тренировок соответствуют моим классам, и все проверили.
Поскольку я использую 8 классов, я решил использовать CrossEntropyLoss, так как в него встроен Softmax.
Текущая модель
class UNetSmall(nn.Module):
"""
Main UNet architecture
"""
def __init__(self, num_classes=1):
super().__init__()
# encoding
self.conv1 = encoding_block(9, 32)
self.maxpool1 = nn.MaxPool2d(kernel_size=2)
self.conv2 = encoding_block(32, 64)
self.maxpool2 = nn.MaxPool2d(kernel_size=2)
self.conv3 = encoding_block(64, 128)
self.maxpool3 = nn.MaxPool2d(kernel_size=2)
self.conv4 = encoding_block(128, 256)
self.maxpool4 = nn.MaxPool2d(kernel_size=2)
# center
self.center = encoding_block(256, 512)
# decoding
self.decode4 = decoding_block(512, 256)
self.decode3 = decoding_block(256, 128)
self.decode2 = decoding_block(128, 64)
self.decode1 = decoding_block(64, 32)
# final
self.final = nn.Conv2d(32, num_classes, kernel_size=1)
def forward(self, input):
# encoding
conv1 = self.conv1(input)
maxpool1 = self.maxpool1(conv1)
conv2 = self.conv2(maxpool1)
maxpool2 = self.maxpool2(conv2)
conv3 = self.conv3(maxpool2)
maxpool3 = self.maxpool3(conv3)
conv4 = self.conv4(maxpool3)
maxpool4 = self.maxpool4(conv4)
# center
center = self.center(maxpool4)
# decoding
decode4 = self.decode4(conv4, center)
decode3 = self.decode3(conv3, decode4)
decode2 = self.decode2(conv2, decode3)
decode1 = self.decode1(conv1, decode2)
# final
final = nn.functional.upsample(self.final(decode1), input.size()[2:], mode='bilinear')
return final
Метод обучения
def train(train_loader, model, criterion, optimizer, scheduler, epoch_num):
correct = 0
totalcount = 0
scheduler.step()
# iterate over data
for idx, data in enumerate(tqdm(train_loader, desc="training")):
# get the inputs and wrap in Variable
if torch.cuda.is_available():
inputs = Variable(data['sat_img'].cuda())
labels = Variable(data['map_img'].cuda())
else:
inputs = Variable(data['sat_img'])
labels = Variable(data['map_img'])
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, labels.long())
loss.backward()
optimizer.step()
test = torch.max(outputs.data, 1)[1] == labels.long()
correct += test.sum().item()
totalcount += test.size()[0] * test.size()[1] * test.size()[2]
print('Training Loss: {:.4f}, Accuracy: {:.2f}'.format(loss.data[0], correct/totalcount))
return {'train_loss': loss.data[0], 'train_acc' : correct/totalcount}
Обучающий вызов в цикле эпохи
lr_scheduler.step()
train_metrics = train(train_dataloader, model, criterion, optimizer, lr_scheduler, epoch)
Некоторые итерации эпохи
#### Эпоха 0/19
---------- тренировка: 100% | ███████████████████████████████████████ ████████████████████████████████████████ |
84/84 [00:17 <00:00, 5.77it / s] Потеря тренировки: 0,8901, точность: 0,83
Текущее прошедшее время 2m 6s </p>
#### эпоха 1/19
---------- тренировка: 100% | ██████████████████████████████████████ ████████████████████████████████████████ |
84/84 [00:17 <00:00, 5.72it / s] Потеря тренировки: 0,7922, точность: 0,83
Текущее прошедшее время 2м 24с </p>
#### эпоха 2/19
---------- тренировка: 100% | ███████████████████████████████████████ ████████████████████████████████████████ |
84/84 [00:18 <00:00, 5.44it / s] Потеря тренировки: 0,8753, точность: 0,84
Текущее прошедшее время 2м 42с </p>
#### эпоха 3/19
---------- тренировка: 100% | ██████████████████████████████████████ ████████████████████████████████████████ |
84/84 [00:18 <00:00, 5.53it / s] Потеря тренировки: 0,7741, Точность: 0,84
Текущее прошедшее время 3м 1с </p>