Неожиданная ошибка при загрузке модели: проблема в предикторе - ModuleNotFoundError: нет модуля с именем 'torchvision'

Я пытался развернуть свою модель на платформе AI для прогнозирования через консоль на моем экземпляре виртуальной машины, но у меня возникла ошибка "(gcloud.beta.ai-platform.versions.create) Ошибка создания версии. Плохая модель обнаружена с ошибкой: «Не удалось загрузить модель: непредвиденная ошибка при загрузке модели: проблема в предикторе - ModuleNotFoundError: нет модуля с именем 'torchvision' (код ошибки: 0)»

Мне нужно включить как torch, так и torchvision. Я выполнил шаги, указанные в этом вопросе Невозможно развернуть обученную модель в Google Cloud Ai-Platform с помощью настраиваемой процедуры прогнозирования: для модели требуется больше памяти, чем разрешено, но мне не удалось получить файлы, на которые указал пользователь gogasca. Я попытался загрузить это .whl с веб-сайта Pytorch и загрузил его в свое облачное хранилище, но получил ту же ошибку, что нет модуля torchvision, хотя эта версия должна включать как torch, так и torchvision. Также пробовали использовать здесь пакеты, совместимые с Cloud AI, но они этого не сделали. включить torchvision.

Я попытался указать два отдельных файла .whl для torch и torchvision в аргументах --package-uris, они указывают на файлы в моем облачном хранилище, но затем я получил ошибку, что объем памяти был превышен. Это странно, ведь в совокупности их размер составляет около 130 Мб. Пример моей команды, результатом которой стало отсутствие torchvision, выглядел так:

gcloud beta ai-platform versions create version_1 \
  --model online_pred_1 \
  --runtime-version 1.15 \
  --python-version 3.7 \
  --origin gs://BUCKET/model-dir \
  --package-uris gs://BUCKET/staging-dir/my_package-0.1.tar.gz,gs://BUCKET/torchvision-dir/torch-1.4.0+cpu-cp37-cp37m-linux_x86_64.whl \
  --prediction-class predictor.MyPredictor

Я пробовал указывать на различные комбинации файлов .whl, которые я получил из разных источников, но получил либо ошибку без модуля, либо недостаточно памяти. Я не понимаю, как модули взаимодействуют в этом случае и почему компилятор считает, что такого модуля нет. Как я могу это решить? Или, как вариант, как я могу сам скомпилировать пакет, включающий как torch, так и torchvision. Не могли бы вы дать подробные ответы, потому что я не очень хорошо знаком с управлением пакетами и сценариями bash.

Вот код, который я использовал, torch_model.py:

from torch import nn


class EthnicityClassifier44(nn.Module):
    def __init__(self, num_classes=2):
        super().__init__()
        self.conv1 = nn.Conv2d(3, 32, kernel_size=7, stride=1, padding=3)
        self.maxpool1 = nn.MaxPool2d(kernel_size=2, stride=2)
        self.conv22 = nn.Conv2d(32, 32, kernel_size=3, stride=1, padding=1)
        self.maxpool2 = nn.MaxPool2d(kernel_size=2, stride=2)
        self.conv3 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
        self.maxpool3 = nn.MaxPool2d(kernel_size=2, stride=2)
        self.conv4 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
        self.maxpool4 = nn.MaxPool2d(kernel_size=2, stride=2)
        self.relu = nn.ReLU(inplace=False)
        self.fc1 = nn.Linear(8*8*128, 128)
        self.fc2 = nn.Linear(128, 128)
        self.fc4 = nn.Linear(128, num_classes)


    def forward(self, x):
        x = self.relu(self.conv1(x))
        x = self.maxpool1(x)
        x = self.relu(self.conv22(x))
        x = self.maxpool2(x)
        x = self.maxpool3(self.relu(self.conv3(x)))
        x = self.maxpool4(self.relu(self.conv4(x)))
        x = self.relu(self.fc1(x.view(x.shape[0], -1)))
        x = self.relu(self.fc2(x))
        x = self.fc4(x)
        return x

Это predictor_py:

from facenet_pytorch import MTCNN, InceptionResnetV1, extract_face
import torch
import torchvision
from torchvision import transforms
from torch.nn import functional as F
from PIL import Image
from sklearn.externals import joblib
import numpy as np
import os
import torch_model


class MyPredictor(object):

    import torch
    import torchvision

    def __init__(self, model, preprocessor, device):
        """Stores artifacts for prediction. Only initialized via `from_path`.
        """
        self._resnet = model
        self._mtcnn_mult = preprocessor
        self._device = device
        self.get_std_tensor = transforms.Compose([
            np.float32,
            np.uint8,
            transforms.ToTensor(),
        ])
        self.tensor2pil = transforms.ToPILImage(mode='RGB')
        self.trans_resnet = transforms.Compose([
            transforms.Resize((100, 100)),
            np.float32,
            transforms.ToTensor()
        ])

    def predict(self, instances, **kwargs):

        pil_transform = transforms.Resize((512, 512))

        imarr = np.asarray(instances)
        pil_im = Image.fromarray(imarr)
        image = pil_im.convert('RGB')
        pil_im_512 = pil_transform(image)

        boxes, _ = self._mtcnn_mult(pil_im_512)
        box = boxes[0]

        face_tensor = extract_face(pil_im_512, box, margin=40)
        std_tensor = self.get_std_tensor(face_tensor.permute(1, 2, 0))
        cropped_pil_im = self.tensor2pil(std_tensor)

        face_tensor = self.trans_resnet(cropped_pil_im)
        face_tensor4d = face_tensor.unsqueeze(0)
        face_tensor4d = face_tensor4d.to(self._device)

        prediction = self._resnet(face_tensor4d)
        preds = F.softmax(prediction, dim=1).detach().numpy().reshape(-1)
        print('probability of (class1, class2) = ({:.4f}, {:.4f})'.format(preds[0], preds[1]))

        return preds.tolist()

    @classmethod
    def from_path(cls, model_dir):
        import torch
        import torchvision
        import torch_model

        model_path = os.path.join(model_dir, 'class44_M40RefinedExtra_bin_no_norm_7860.joblib')
        classifier = joblib.load(model_path)

        mtcnn_path = os.path.join(model_dir, 'mtcnn_mult.joblib')
        mtcnn_mult = joblib.load(mtcnn_path)

        device_path = os.path.join(model_dir, 'device_cpu.joblib')
        device = joblib.load(device_path)

        return cls(classifier, mtcnn_mult, device)

И setup.py:

from setuptools import setup

REQUIRED_PACKAGES = ['opencv-python-headless', 'facenet-pytorch']

setup(
 name="my_package",
 version="0.1",
 include_package_data=True,
 scripts=["predictor.py", "torch_model.py"],
 install_requires=REQUIRED_PACKAGES
)

person dream_variable    schedule 21.05.2020    source источник
comment
эта версия должна включать и torch, и torchvision - нет, это просто torch сама по себе. torchvision довольно мала (даже версия для GPU составляет всего около 20 МБ), поэтому с версией PyPI должно быть все в порядке. Но я не совсем понимаю, где будет установлен torchvision. Этого нет в вашем REQUIRED_PACKAGES и в требованиях из facenet-pytorch. Не могли бы вы попробовать добавить 'torchvision==0.5.0REQUIRED_PACKAGES? 0.5.0, потому что это версия для PyTorch 1.4.0.   -  person Michael Jungo    schedule 21.05.2020
comment
@MichaelJungo, спасибо за ответ! Я пробовал это раньше и получал сообщение об ошибке, что недостаточно места (gcloud.beta.ai-platform.versions.create) Create Version failed. Bad model detected with error: Model requires more memory than allowed. Please try to decrease the model size an d re-deploy.. Я попробовал еще раз и получил ту же ошибку, что не имеет смысла, потому что действительно tochvision довольно мало.   -  person dream_variable    schedule 21.05.2020
comment
@MichaelJungo Более того, мне кажется странным, что facenet-pytorch не имеет torchvision в установочном файле, потому что он используется в detect_face модуле здесь   -  person dream_variable    schedule 21.05.2020
comment
torchvision зависит от torch, поэтому он также автоматически попытается установить его. Затем вам нужно убедиться, что он загружает версию процессора torch, вы также можете попытаться указать torch==1.4.0+cpu в качестве требования, чтобы torchvision не пытался получить обычную версию torch, которая была бы версией GPU.   -  person Michael Jungo    schedule 21.05.2020
comment
@MichaelJungo Я сделал эту передачу torch и torchvision как отдельные записи в REQUIRED_PACKAGES. Я также пропустил ссылку на пакет .whl, содержащий torch, в моем облачном хранилище в аргументе --package-uris . Получена новая ошибка: Bad model detected with error: "Failed to load model: User-provided package my_package-0.1.tar.gz failed to ins tall: Command '['python-default', '-m', 'pip', 'install', '--target=/tmp/custom_lib', '--no-cache-dir', '-b', '/tmp/pip_builds', '/tmp/custom_code/my_package-0.1.tar.gz']' returned non -zero exit status 1. (Error code: 0)   -  person dream_variable    schedule 21.05.2020
comment
Похоже, что my_package-0.1.tar.gz не существует. Я не думаю, что вам нужно указывать gs://BUCKET/staging-dir/my_package-0.1.tar.gz в --package-uris, это должно быть только для пакетов, от которых зависит ваш код (например, версия процессора PyTorch). В конце концов, вы собираетесь собрать этот пакет, нет возможности установить его до того, как вы его создадите.   -  person Michael Jungo    schedule 21.05.2020
comment
@MichaelJungo, это то, что должно быть включено в соответствии с руководством и документацию. Я попытался включить только каталог, но это не сработало. Если я вообще этого не укажу, то как будет установлен мой собственный пакет?   -  person dream_variable    schedule 22.05.2020
comment
О, да, в прошлый раз, когда я проверял, я смотрел на учебную часть, там ее можно опустить, но в ней также есть раздел, если вы хотите встроить себя, что, кажется, вам необходимо сделать для развертывания. Вы выполнили шаги из Упакуйте свой Predictor и его зависимости? Вам нужно собрать его с помощью python setup.py sdist --formats=gztar, а затем скопировать сгенерированный архив в gs://BUCKET/staging-dir/my_package-0.1.tar.gz.   -  person Michael Jungo    schedule 22.05.2020
comment
@MichaelJungo Я нашел решение. В файл setup.py следовало поместить следующее: REQUIRED_PACKAGES = ['torchvision==0.5.0', 'torch @ https://download.pytorch.org/whl/cpu/torch-1.4.0%2Bcpu-cp37-cp37m-linux_x86_64.whl', 'opencv-python', 'facenet-pytorch']. Затем у меня возникла другая проблема с созданием пользовательского класса, но эта статья хорошо это объясняет. Итак, я смог успешно развернуть свою модель на платформе AI.   -  person dream_variable    schedule 23.05.2020


Ответы (1)


Решением было поместить следующие пакеты в файл thsetup.py для пользовательского кода прогноза:

REQUIRED_PACKAGES = ['torchvision==0.5.0', 'torch @ https://download.pytorch.org/whl/cpu/torch-1.4.0%2Bcpu-cp37-cp37m-linux_x86_64.whl', 'opencv-python', 'facenet-pytorch']

Затем у меня возникла другая проблема с созданием пользовательского класса, но эта статья хорошо это объясняет. Таким образом, я смог успешно развернуть свою модель на платформе AI для прогнозирования.

person dream_variable    schedule 23.05.2020