Как определить точность с потерей триплета в сверточной нейронной сети
Сеть Triplet (вдохновленная "сиамской сетью") состоит из 3 экземпляров одной и той же сети прямой связи (с общими параметрами). При подаче 3 выборок сеть выводит 2 промежуточных значения - расстояния L2 (евклидово) между встроенным представлением двух своих входов и представлением третьего.
Я использую пары из трех изображений для подачи в сеть (x = якорное изображение, стандартное изображение, x + = положительное изображение, изображение, содержащее тот же объект, что и x - фактически, x + - тот же класс, что и x, а x- = отрицательный изображение, изображение с другим классом, чем х.
Я использую функцию стоимости потери триплета, описанную здесь.
Как определить точность сети?
2 ответа
Я предполагаю, что вы выполняете работу по поиску изображений или аналогичным задачам.
Сначала вы должны сгенерировать некоторый триплет, либо случайным образом, либо с использованием какого-либо жесткого (полужесткого) негативного метода майнинга. Затем вы разбиваете свой триплет на поезд и проверочный набор.
Если вы делаете это таким образом, то вы можете определить свою точность проверки как пропорцию числа триплетов, в котором расстояние между признаком и положительным элементом меньше, чем расстояние между якорем и отрицательным в вашем триплете проверки. Вы можете увидеть пример здесь, который написан на PyTorch.
В качестве другого способа вы можете напрямую измерить конечную метрику тестирования. Например, для получения изображений, как правило, мы измеряем производительность модели на тестовом наборе, используя среднюю среднюю точность. Если вы используете эту метрику, вы должны сначала определить некоторые запросы к вашему набору валидации и их соответствующее основополагающее изображение истинности.
Любой из вышеуказанных двух показателей в порядке. Выберите то, что вы считаете подходящим для вашего случая.
Итак, я выполняю аналогичную задачу, используя Triplet loss для классификации. Вот как я использовал новый метод потерь с классификатором. Во-первых, обучите свою модель, используя стандартную функцию потерь триплета для N эпох. Как только вы убедитесь, что модель (мы будем называть это генератором встраивания) обучена, сохраните веса, так как мы будем использовать эти веса заранее. Допустим, ваш генератор встраивания определяется как:
class EmbeddingNetwork(nn.Module):
def __init__(self):
super(EmbeddingNetwork, self).__init__()
self.conv1 = nn.Sequential(
nn.Conv2d(1, 64, (7,7), stride=(2,2), padding=(3,3)),
nn.BatchNorm2d(64),
nn.LeakyReLU(0.001),
nn.MaxPool2d((3, 3), 2, padding=(1,1))
)
self.conv2 = nn.Sequential(
nn.Conv2d(64,64,(1,1), stride=(1,1)),
nn.BatchNorm2d(64),
nn.LeakyReLU(0.001),
nn.Conv2d(64,192, (3,3), stride=(1,1), padding=(1,1)),
nn.BatchNorm2d(192),
nn.LeakyReLU(0.001),
nn.MaxPool2d((3,3),2, padding=(1,1))
)
self.fullyConnected = nn.Sequential(
nn.Linear(7*7*256,32*128),
nn.BatchNorm1d(32*128),
nn.LeakyReLU(0.001),
nn.Linear(32*128,128)
)
def forward(self,x):
x = self.conv1(x)
x = self.conv2(x)
x = self.fullyConnected(x)
return torch.nn.functional.normalize(x, p=2, dim=-1)
Теперь мы будем использовать этот генератор встраивания, чтобы создать другой классификатор, подогнать веса, которые мы сохранили ранее, к этой части сети, а затем заморозить эту часть, чтобы наш тренажер классификатора не мешал модели триплета. Это можно сделать так:
class classifierNet(nn.Module):
def __init__(self, EmbeddingNet):
super(classifierNet, self).__init__()
self.embeddingLayer = EmbeddingNet
self.classifierLayer = nn.Linear(128,62)
self.dropout = nn.Dropout(0.5)
def forward(self, x):
x = self.dropout(self.embeddingLayer(x))
x = self.classifierLayer(x)
return F.log_softmax(x, dim=1)
Теперь мы загрузим веса, которые мы сохранили ранее, и заморозим их, используя:
embeddingNetwork = EmbeddingNetwork().to(device)
embeddingNetwork.load_state_dict(torch.load('embeddingNetwork.pt'))
classifierNetwork = classifierNet(embeddingNetwork)
Теперь обучите эту сеть классификаторов, используя стандартные потери классификации, такие как BinaryCrossEntropy или CrossEntropy.