Вопрос или проблема
Я пытаюсь создать ансамблевую модель, состоящую из двух заранее обученных моделей, используя torch, чтобы классифицировать изображение.
Ниже приведен некоторый код, основанный на этом посте.
import timm
import torch
from torch.nn import functional as F
num_classes = 100
model1 = timm.create_model("efficientnet_b0", num_classes=num_classes)
checkpoint1 = torch.load(checkpoint_path1)
model1.load_state_dict(checkpoint1["model"])
model2 = timm.create_model("efficientnet_b2", num_classes=num_classes)
checkpoint2 = torch.load(checkpoint_path2)
model2.load_state_dict(checkpoint2["model"])
class EnsembleModel(nn.Module):
def __init__(self, modelA, modelB, num_features):
super().__init__()
self.modelA = modelA
self.modelB = modelB
self.classifier = nn.Linear(2*num_features, num_features)
def forward(self, x):
x1 = self.modelA(x)
x2 = self.modelB(x)
x = torch.cat((x1, x2), dim=1)
x = self.classifier(F.relu(x))
return x
model = EnsembleModel(model1, model2, num_classes)
Общие модели были предварительно обучены на GPU (cuda), и когда я выполняю прогноз из EnsembleModel, я получаю эту ошибку:
RuntimeError: Ожидались все тензоры на одном устройстве, но найдено как минимум два устройства, cpu и cuda:0! (при проверке аргумента для аргумента mat1 в методе wrapper_addmm)
из этой строки:
---> 15 x = self.classifier(F.relu(x))
Честно говоря, я даже не уверен, почему в посте предложили использовать классификатор и комбинировать их с relu.
Какой лучший способ комбинировать такие две модели?
Вот больше информации о трассировке стека, если это полезно:
/tmp/ipykernel_33/4277289726.py in forward(self, x)
13 x2 = self.modelB(x)
14 x = torch.cat((x1, x2), dim=1)
---> 15 x = self.classifier(F.relu(x))
16 return x
в /opt/conda/lib/python3.7/site-packages/torch/nn/modules/module.py in _call_impl(self, *input, **kwargs)
1049 if not (self._backward_hooks or self._forward_hooks or self._forward_pre_hooks or _global_backward_hooks
1050 или _global_forward_hooks или _global_forward_pre_hooks):
-> 1051 return forward_call(*input, **kwargs)
1052 # Не проверять функции, когда используется jit
1053 полные_обратные_хуки, не_полные_обратные_хуки = [], []
в /opt/conda/lib/python3.7/site-packages/torch/nn/modules/linear.py in forward(self, input)
94
95 def forward(self, input: Tensor) -> Tensor:
---> 96 return F.linear(input, self.weight, self.bias)
97
98 def extra_repr(self) -> str:
в /opt/conda/lib/python3.7/site-packages/torch/nn/functional.py in linear(input, weight, bias)
1845 if has_torch_function_variadic(input, weight):
1846 return handle_torch_function(linear, (input, weight), input, weight, bias=bias)
-> 1847 return torch._C._nn.linear(input, weight, bias)
1848
1849
RuntimeError: Ожидались все тензоры на одном устройстве, но найдено как минимум два устройства, cpu и cuda:0! (при проверке аргумента для аргумента mat1 в методе wrapper_addmm)
Из вашего фрагмента кода, я предполагаю, что ошибка cpu и cuda:0
не относится к вашим двум моделям, а касается входных данных x
и self.classifier
. Вы можете проверить их местоположение, распечатав их. Затем вы можете переместить тот, который на CPU, на GPU, используя .to(device)
.
Ответ или решение
Создание ансамблевой модели для классификации с использованием PyTorch
Введение
Ансамблевые модели предоставляют способ объединения нескольких предобученных моделей для повышения точности классификации. В этом руководстве мы рассмотрим, как создать ансамблевую модель, используя библиотеки PyTorch и timm, а также как избежать распространённых ошибок при работе с такими моделями.
Шаг 1: Импорт необходимых библиотек
Прежде всего, необходимо импортировать библиотеки и подготовить предобученные модели.
import timm
import torch
import torch.nn as nn
import torch.nn.functional as F
num_classes = 100
# Загружаем предобученные модели
model1 = timm.create_model("efficientnet_b0", num_classes=num_classes)
checkpoint1 = torch.load(checkpoint_path1)
model1.load_state_dict(checkpoint1["model"])
model2 = timm.create_model("efficientnet_b2", num_classes=num_classes)
checkpoint2 = torch.load(checkpoint_path2)
model2.load_state_dict(checkpoint2["model"])
Шаг 2: Создание ансамблевой модели
Теперь создадим класс EnsembleModel
, который будет объединять две модели и осуществлять их совместную работу:
class EnsembleModel(nn.Module):
def __init__(self, modelA, modelB, num_features):
super().__init__()
self.modelA = modelA
self.modelB = modelB
self.classifier = nn.Linear(2 * num_features, num_classes)
def forward(self, x):
x1 = self.modelA(x)
x2 = self.modelB(x)
x = torch.cat((x1, x2), dim=1) # Объединяем выходы обеих моделей
x = self.classifier(F.relu(x)) # Проходим через классификатор
return x
Обратите внимание, что мы используем F.relu
, чтобы добавить нелинейность перед подачей данных в классификатор.
Шаг 3: Убедитесь, что данные находятся на одной платформе
Ошибка, которую вы указали, связана с тем, что данные находятся на разных устройствах, например, часть на CPU, а часть на GPU. Чтобы избежать этой ошибки, убедитесь, что все тензоры находятся на одном устройстве. Обычно это устройство GPU, если таковой доступен:
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# Перемещаем модели на GPU
model1.to(device)
model2.to(device)
ensemble_model = EnsembleModel(model1, model2, num_classes).to(device)
Также не забудьте переместить входные данные на нужное устройство перед обработкой:
# Пример входного изображения
input_image = ... # Ваше изображение в формате тензора
input_image = input_image.to(device)
# Прогоняем через ансамблевую модель
output = ensemble_model(input_image)
Шаг 4: Вывод
Таким образом, вы создали ансамблевую модель из двух предобученных моделей и скорректировали проблему с несоответствием устройств. Вы можете расширять эту модель и добавлять дополнительные слои, если это необходимо для улучшения производительности.
Заключение
Создание ансамблевой модели — это эффективный способ повысить качество классификации в задачах компьютерного зрения. Важно следить за тем, чтобы все данные и модели находились на одном устройстве, чтобы избежать ошибок времени выполнения. Следуя вышеизложенным рекомендациям, вы сможете успешно настроить и использовать ансамблевую модель для своих нужд.
Если у вас возникнут дополнительные вопросы или проблемы, не стесняйтесь задавать их, и я с радостью помогу вам дальше.