Cet article est un résumé d'une tentative d'exécution de PyTorch sur AWS Lambda. Il a une balise DeepLearning, mais ne touche pas à l'apprentissage. Le but est d'essayer une inférence sur Lambda. (Cliquez ici pour les paramètres EFS](https://qiita.com/myonoym/items/5d360ed11931474cb640))
C'est un stand à trois volets.
Cette fois, je vais essayer de l'exécuter avec Lambda EML-NET. Voir Page du projet Github pour plus de détails, mais SaliencyMap ) Est un modèle à générer. SaliencyMap est une carte thermique qui montre la position où la ligne de vue d'une personne est dirigée.
J'ai monté EFS sur / mnt dans Article précédent, mais mettons la bibliothèque que je veux importer de Lambda dans EFS.
$ cd /mnt/lambda
$ sudo pip3 install -t . torch==1.6.0+cpu torchvision==0.7.0+cpu -f https://download.pytorch.org/whl/torch_stable.html
$ sudo pip3 install --upgrade -t . opencv-python==4.4.0.42 scipy==1.5.2
par ça,
Est maintenant sous / mnt / lambda
.
Cliquez sur Créer une fonction
-> Créer à partir de zéro
-> Entrer le nom de la fonction-> Définir Runtime sur Python3.7
-> Créer une fonction
VPC Autour d'ici Quelque chose est écrit, mais pour connecter Lambda à EFS, Lambda est VPC. Doit être placé à l'intérieur. Le VPC par défaut devrait convenir. En ce qui concerne le groupe de sécurité, je pense qu'il existe un paramètre EC2 utilisé pour préparer la bibliothèque en EFS, alors spécifiez-le. Lorsque je clique sur Enregistrer, j'obtiens l'erreur suivante: Je ne semble pas avoir assez d'autorité. Selon ici
ec2:CreateNetworkInterface
ec2:DescribeNetworkInterfaces
ec2:DeleteNetworkInterface
Il semble que Lambda ait besoin de l'autorisation de. «La politique de gestion AWS est incluse dans le AWSLambdaVPCAccessExecutionRole», donc attachons cette politique au rôle Lambda. Ensuite, vous devriez pouvoir configurer le VPC.
Connectez l'EFS et Lambda préparés. Cliquez sur «Ajouter un système de fichiers» à partir de «Système de fichiers» dans la console. Spécifiez le système de fichiers EFS et le point d'accès, définissez le chemin de montage local sur / mnt / lambda
et cliquez sur Enregistrer
.
Testons si Lambda peut charger la bibliothèque dans EFS.
EFS est monté sur / mnt / lambda
, donc ajoutez / mnt / lambda
au chemin python.
lambda_function.py
import json
import sys
sys.path.append("/mnt/lambda")
import torch
import torchvision
import PIL
import cv2
import numpy as np
def lambda_handler(event, context):
print(f"torch:{torch.__version__}")
print(f"torchvision:{torchvision.__version__}")
print(f"PIL:{PIL.__version__}")
print(f"cv2:{cv2.__version__}")
print(f"numpy:{np.__version__}")
return {
'statusCode': 200,
'body': json.dumps('Hello from Lambda!')
}
Si vous créez un événement de test approprié sur la console et exécutez le test, vous obtiendrez le résultat suivant. Vous pouvez lire correctement PyTorch.
START RequestId: 35329cd4-50f6-4eb7-8950-f27daf75462b Version: $LATEST
OpenBLAS WARNING - could not determine the L2 cache size on this system, assuming 256k
torch:1.6.0+cpu
torchvision:0.7.0+cpu
PIL:7.2.0
cv2:4.4.0
numpy:1.19.2
END RequestId: 35329cd4-50f6-4eb7-8950-f27daf75462b
REPORT RequestId: 35329cd4-50f6-4eb7-8950-f27daf75462b Duration: 29212.21 ms Billed Duration: 29300 ms Memory Size: 128 MB Max Memory Used: 129 MB
Maintenant que nous sommes prêts, déplaçons le modèle. L'emplacement du modèle entraîné est répertorié dans la page github EML, téléchargez-le. Selon l'enseignement de README, placez trois fichiers, res_imagenet.pth, res_places.pth, res_decoder.pth
, dans / mnt / lambda / backbone
de EFS monté sur EC2 par scp.
Sur la base de eval_combined.py, nous allons le modifier pour qu'il puisse être exécuté sur Lambda.
lambda_function.py
import sys
sys.path.append("/mnt/lambda")
import os
import torch
import torch.nn as nn
import torch.backends.cudnn as cudnn
import torchvision.transforms as transforms
from PIL import Image
import cv2
import numpy as np
import resnet
import decoder
#La variable d'environnement ici n'est-elle pas inutile? Je le sens aussi.
os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID"
os.environ["CUDA_VISIBLE_DEVICES"] = "0"
image_model_path = "/mnt/lambda/backbone/res_imagenet.pth"
place_model_path = "/mnt/lambda/backbone/res_places.pth"
decoder_model_path = "/mnt/lambda/backbone/res_decoder.pth"
size = (480, 640)
num_feat = 5
def normalize(x):
x -= x.min()
x /= x.max()
def post_process(pred):
pred = cv2.GaussianBlur(pred, (5,5), 10.0)
normalize(pred)
pred_uint = (pred * 255).astype(np.uint8)
return pred, pred_uint
def draw_heatmap(pred, img):
#Convertissez la carte de saillance à la taille d'image d'origine.
resized_pred = np.asarray(Image.fromarray(pred).resize((img.size[0], img.size[1])), dtype=np.uint8)
resized_colormap = cv2.applyColorMap(resized_pred, cv2.COLORMAP_JET)
resized_colormap = cv2.cvtColor(resized_colormap, cv2.COLOR_BGR2RGB)
#Convertissez l'image d'origine en ndarray numpy.
img_array = np.asarray(img)
#Mélange
alpha = 0.5
blended = cv2.addWeighted(img_array, alpha, resized_colormap, 1-alpha, 0)
return blended
def predict(image_model_path, place_model_path, decoder_model_path, pil_img):
img_model = resnet.resnet50(image_model_path).eval()
pla_model = resnet.resnet50(place_model_path).eval()
decoder_model = decoder.build_decoder(decoder_model_path, size, num_feat, num_feat).eval()
preprocess = transforms.Compose([
transforms.Resize(size),
transforms.ToTensor(),
])
processed = preprocess(pil_img).unsqueeze(0)
with torch.no_grad():
img_feat = img_model(processed, decode=True)
pla_feat = pla_model(processed, decode=True)
pred = decoder_model([img_feat, pla_feat])
pred_origin = pred.squeeze().detach().cpu().numpy()
pred, pred_uint = post_process(pred_origin)
heatmap = draw_heatmap(pred_uint, pil_img)
return heatmap
def lambda_handler(event, context):
#Réponse vide
empty_response = {
"statusCode": 200,
"body": "{}"
}
pil_img = Image.open("/mnt/lambda/image/examples/115.jpg ").convert("RGB")
heatmap = predict(image_model_path, place_model_path, decoder_model_path, pil_img)
print(heatmap.shape)
return empty_response
C'est un peu long, mais vous pouvez maintenant générer une carte de saillance sur Lambda. Étant donné que le GPU ne peut pas être utilisé sur Lambda, la description de la partie liée au cuda est modifiée à partir du code d'origine. Quand tu cours
START RequestId: 6f9baccf-b758-4e9a-b43a-b92bdd9757ec Version: $LATEST
OpenBLAS WARNING - could not determine the L2 cache size on this system, assuming 256k
Model loaded /mnt/lambda/backbone/res_imagenet.pth
Model loaded /mnt/lambda/backbone/res_places.pth
Loaded decoder /mnt/lambda/backbone/res_decoder.pth
(511, 681, 3)
END RequestId: 6f9baccf-b758-4e9a-b43a-b92bdd9757ec
REPORT RequestId: 6f9baccf-b758-4e9a-b43a-b92bdd9757ec Duration: 20075.02 ms Billed Duration: 20100 ms Memory Size: 1024 MB Max Memory Used: 614 MB
Il semble qu'il puisse être exécuté en toute sécurité. Je voulais sortir le fichier du côté EFS, mais c'était un peu ennuyeux, alors modifions-le pour qu'il puisse être sorti vers S3 lors de l'appel de Slack la prochaine fois.
En connectant EFS à Lambda, vous pouvez désormais charger des bibliothèques et des fichiers de modèle. Je pense que cela permettra d'effectuer l'inférence de modèle sans se soucier de la capacité de Lambda comme par le passé. La prochaine fois, en tant qu'édition Slack Call, j'appellerai cette Lambda de Slack et la verrai.
En écrivant cet article, j'ai à nouveau créé la configuration à partir de zéro pour confirmation, mais je regrette que si je l'ai fait avec AWS CDK ou quelque chose du genre, l'écriture aurait progressé. Je vais.