
El 24 de febrero de 2022, Rusia declaró la guerra e invadió la pacífica Ucrania. Después de la anexión de Crimea y la ocupación de la región de Donbas, el régimen de Putin decidió destruir la nacionalidad ucraniana. Los ucranianos muestran una resistencia feroz y demuestran al mundo entero cómo es luchar por la independencia de la nación.
El gobierno de Ucrania lanzó un sitio web para ayudar a las madres, esposas y hermanas rusas a encontrar a sus amados asesinados o capturados en Ucrania - https://200rf.com y https://t.me/rf200_now (canal de telegram). Nuestro objetivo es informar a aquellos que todavía están en Rusia y Bielorrusia, por lo que se niegan a asaltar a Ucrania.
Ayúdanos a obtener la máxima exposición a lo que está sucediendo en Ucrania, la violencia y los actos inhumanos de terror que el "mundo ruso" ha traído a Ucrania. Esta es una wiki integral sobre cómo puedes ayudar a terminar esta guerra: https://how-to-help-ukraine-now.super.site/
Canales oficiales
¡Gloria a Ucrania!
Un pytorch-toolbelt es una biblioteca de Python con un conjunto de campanas y silbatos para Pytorch para la prototipos rápidos de I + D y la agricultura de Kaggle:
Showcase: Catalyst, Albumentations, Pytorch Tool Belt Ejemplo: segmentación semántica @ Camvid
La respuesta honesta es "Necesitaba una forma conveniente de reutilizar el código para mi carrera de Kaggle". Durante 2018 logré una insignia maestra de Kaggle y este ha sido un camino largo. Muy a menudo me encontré reutilizando la mayoría de las tuberías viejas una y otra vez. En algún momento se cristalizó en este repositorio.
Esta lib debe reemplazar los marcos Catalyst / Ignite / Fast.AI de alto nivel. En cambio, está diseñado para complementarlos.
pip install pytorch_toolbelt
Debajo de un fragmento de código que crea el modelo de red U de vainilla para la segmentación binaria. Por diseño, tanto el codificador como el decodificador producen una lista de tensores, desde mapas de características finas (alta resolución, 0 ) hasta gruesos (baja resolución). El acceso a todos los mapas de características intermedias es beneficioso si desea aplicar pérdidas de supervisión profunda en ellos o codificador del codificador de la tarea de detección de objetos, donde es necesario el acceso a los mapas de características intermedias.
from torch import nn
from pytorch_toolbelt . modules import encoders as E
from pytorch_toolbelt . modules import decoders as D
class UNet ( nn . Module ):
def __init__ ( self , input_channels , num_classes ):
super (). __init__ ()
self . encoder = E . UnetEncoder ( in_channels = input_channels , out_channels = 32 , growth_factor = 2 )
self . decoder = D . UNetDecoder ( self . encoder . channels , decoder_features = 32 )
self . logits = nn . Conv2d ( self . decoder . channels [ 0 ], num_classes , kernel_size = 1 )
def forward ( self , x ):
x = self . encoder ( x )
x = self . decoder ( x )
return self . logits ( x [ 0 ])De manera similar al ejemplo anterior, puede cambiar el decodificador a FPN con contatenación.
from torch import nn
from pytorch_toolbelt . modules import encoders as E
from pytorch_toolbelt . modules import decoders as D
class SEResNeXt50FPN ( nn . Module ):
def __init__ ( self , num_classes , fpn_channels ):
super (). __init__ ()
self . encoder = E . SEResNeXt50Encoder ()
self . decoder = D . FPNCatDecoder ( self . encoder . channels , fpn_channels )
self . logits = nn . Conv2d ( self . decoder . channels [ 0 ], num_classes , kernel_size = 1 )
def forward ( self , x ):
x = self . encoder ( x )
x = self . decoder ( x )
return self . logits ( x [ 0 ]) Todos los codificadores de pytorch_toolbelt admiten el número de canales de entrada. Simplemente llame encoder.change_input_channels(num_channels) y se cambiará la primera capa de convolución. Siempre que sea posible, se reutilizarán los pesos existentes de la capa convolucional (en caso de que un nuevo número de canales sea mayor que el valor predeterminado, el nuevo tensor de peso se acolchará con weigths inicializados al azar). El método de clase se devuelve self , por lo que esta llamada puede ser encadenada.
from pytorch_toolbelt . modules import encoders as E
encoder = E . SEResnet101Encoder ()
encoder = encoder . change_input_channels ( 6 ) Al diseñar un modelo y optimizar el número de características en la red neuronal, descubrí que es bastante útil imprimir el número de parámetros en bloques de alto nivel (como encoder y decoder ). Aquí se explica cómo hacerlo con pytorch_toolbelt :
from torch import nn
from pytorch_toolbelt . modules import encoders as E
from pytorch_toolbelt . modules import decoders as D
from pytorch_toolbelt . utils import count_parameters
class SEResNeXt50FPN ( nn . Module ):
def __init__ ( self , num_classes , fpn_channels ):
super (). __init__ ()
self . encoder = E . SEResNeXt50Encoder ()
self . decoder = D . FPNCatDecoder ( self . encoder . channels , fpn_channels )
self . logits = nn . Conv2d ( self . decoder . channels [ 0 ], num_classes , kernel_size = 1 )
def forward ( self , x ):
x = self . encoder ( x )
x = self . decoder ( x )
return self . logits ( x [ 0 ])
net = SEResNeXt50FPN ( 1 , 128 )
print ( count_parameters ( net ))
# Prints {'total': 34232561, 'trainable': 34232561, 'encoder': 25510896, 'decoder': 8721536, 'logits': 129}Hay múltiples formas de combinar múltiples pérdidas, y los marcos DL de alto nivel como Catalyst ofrecen una forma más flexible de lograr esto, pero aquí hay una implementación de Pytorch 100%de mía:
from pytorch_toolbelt import losses as L
# Creates a loss function that is a weighted sum of focal loss
# and lovasz loss with weigths 1.0 and 0.5 accordingly.
loss = L . JointLoss ( L . FocalLoss (), L . LovaszLoss (), 1.0 , 0.5 )La augmetnation de tiempo de prueba (TTA) se puede usar tanto en las fases de entrenamiento como en las pruebas.
from pytorch_toolbelt . inference import tta
model = UNet ()
# Truly functional TTA for image classification using horizontal flips:
logits = tta . fliplr_image2label ( model , input )
# Truly functional TTA for image segmentation using D4 augmentation:
logits = tta . d4_image2mask ( model , input )Muy a menudo, es necesario realizar la segmentación de imágenes para una imagen enormemente grande (5000px y más). Hay algunos problemas con una matrices de píxeles tan grandes:
Una de las soluciones es cortar la imagen de entrada en los mosaicos (opcionalmente superpuesto) y alimentar a cada uno a través del modelo y concatenar los resultados. De esta manera, puede garantizar el límite superior del uso de RAM de GPU, al tiempo que mantiene la capacidad de procesar imágenes de tamaño arbitrario en GPU.
import numpy as np
from torch . utils . data import DataLoader
import cv2
from pytorch_toolbelt . inference . tiles import ImageSlicer , CudaTileMerger
from pytorch_toolbelt . utils . torch_utils import tensor_from_rgb_image , to_numpy
image = cv2 . imread ( 'really_huge_image.jpg' )
model = get_model (...)
# Cut large image into overlapping tiles
tiler = ImageSlicer ( image . shape , tile_size = ( 512 , 512 ), tile_step = ( 256 , 256 ))
# HCW -> CHW. Optionally, do normalization here
tiles = [ tensor_from_rgb_image ( tile ) for tile in tiler . split ( image )]
# Allocate a CUDA buffer for holding entire mask
merger = CudaTileMerger ( tiler . target_shape , 1 , tiler . weight )
# Run predictions for tiles and accumulate them
for tiles_batch , coords_batch in DataLoader ( list ( zip ( tiles , tiler . crops )), batch_size = 8 , pin_memory = True ):
tiles_batch = tiles_batch . float (). cuda ()
pred_batch = model ( tiles_batch )
merger . integrate_batch ( pred_batch , coords_batch )
# Normalize accumulated mask and convert back to numpy
merged_mask = np . moveaxis ( to_numpy ( merger . merge ()), 0 , - 1 ). astype ( np . uint8 )
merged_mask = tiler . crop_to_orignal_size ( merged_mask ) @misc{Khvedchenya_Eugene_2019_PyTorch_Toolbelt,
author = {Khvedchenya, Eugene},
title = {PyTorch Toolbelt},
year = {2019},
publisher = {GitHub},
journal = {GitHub repository},
howpublished = {url{https://github.com/BloodAxe/pytorch-toolbelt}},
commit = {cc5e9973cdb0dcbf1c6b6e1401bf44b9c69e13f3}
}