Cómo convertir tensorflow. js pesos modelo para pytorch tensors, y atrás?
Estoy usando ml5.jsUn envoltorio alrededor de tensorflowjs. Quiero entrenar una red neuronal en el navegador, descargar los pesos, procesarlos como tensores en pyTorch, y cargarlos de nuevo en el modelo tensorflowjs del navegador. Cómo puedo convertir entre estos formatos tfjs <-> pytorch
?
El modelo del navegador tiene un save()
función que genera tres archivos. Un archivo de metadatos específico a ml5.js (json), un archivo de topología que describe la arquitectura modelo (json), y un archivo de pesos binarios (bin).
// Browser
model.save()
// HTTP/Download
model_meta.json (needed by ml5.js)
model.json (needed by tfjs)
model.weights.bin (needed by tfjs)
# python backend
import json
with open('model.weights.bin', 'rb') as weights_file:
with open('model.json', 'rb') as model_file:
weights = weights_file.read()
model = json.loads(model_file.read())
####
pytorch_tensor = convert2tensor(weights, model) # whats in this function?
####
# Do some processing in pytorch
####
new_weights_bin = convert2bin(pytorch_tensor, model) # and in this?
####
Aquí está la muestra código de javascript para generar y cargar los 3 archivos en el navegador. Para cargar, seleccione los 3 archivos a la vez en el cuadro de diálogo. Si son correctos, un popup mostrará una predicción de muestra.
Pregunta hecha hace 3 años, 4 meses, 29 días - Por scriptsculptor
3 Respuestas:
-
Fui capaz de encontrar una manera de convertir de tfjs
model.weights.bin
a numpyndarrays
. Es trivial convertir de arrays numpy a pitorchstate_dict
que es un diccionario de tensores y sus nombres.Teoría
En primer lugar, debe entenderse la representación tfjs del modelo.
model.json
describe el modelo. En pitón, se puede leer como diccionario. Tiene las siguientes llaves:La arquitectura modelo se describe como otro json / diccionario bajo la clave
modelTopology
.También tiene un json / diccionario bajo la llave
weightsManifest
que describe el tipo/forma/ubicación de cada peso envuelto en el correspondientemodel.weights.bin
archivo. Como un lado, el manifiesto de pesos permite múltiples.bin
archivos para almacenar pesos.
Tensorflow.js tiene un paquete de pitón compañero
tensorflowjs
, que viene con funciones de utilidad a leído y escribir pesos entre el formato tf.js binario y numpy array.Cada archivo de peso se lee como un "grupo". Un grupo es una lista de diccionarios con llaves
name
ydata
que se refieren al nombre de peso y la matriz numposa que contiene pesos. También hay otras llaves.group = [{'name': weight_name, 'data': np.ndarray}, ...] # 1 *.bin file
Aplicación
Instala tensorflowjs. Desafortunadamente, también instalará tensorflow.
pip install tensorflowjs
Utilice estas funciones. Tenga en cuenta que he cambiado las firmas para mayor comodidad.
from typing import Dict, ByteString import torch from tensorflowjs.read_weights import decode_weights from tensorflowjs.write_weights import write_weights def convert2tensor(weights: ByteString, model: Dict) -> Dict[str, torch.Tensor]: manifest = model['weightsManifest'] # If flatten=False, returns a list of groups equal to the number of .bin files. # Use flatten=True to convert to a single group group = decode_weights(manifest, weights, flatten=True) # Convert dicts in tfjs group format into pytorch's state_dict format: # {name: str, data: ndarray} -> {name: tensor} state_dict = {d['name']: torch.from_numpy(d['data']) for d in group} return state_dict def convert2bin(state_dict: Dict[str: np.ndarray], model: Dict, directory='./'): # convert state_dict to groups (list of 1 group) groups = [[{'name': key, 'data': value} for key, value in state_dict.items()]] # this library function will write to .bin file[s], but you can read it back # or change the function internals my copying them from source write_weights(groups, directory, write_manifest=False)
Respondida el Dec 18, 2020 a las 02:25 - por algoarchitect
Votos positivos: 0 | Votos negativos: 0 -
Para convertir los pesos del modelo de TensorFlow.js a tensores de PyTorch y viceversa, necesitarás realizar un proceso de conversión de los formatos de los datos. Aquí te dejo un ejemplo de cómo podrías hacerlo:
- Convertir los pesos del modelo de TensorFlow.js a tensores de PyTorch:
python import torch import json import numpy as np
Leer los archivos de pesos binarios y el archivo de modelo json
with open('model.weights.bin', 'rb') as weights_file: with open('model.json', 'r') as model_file: weights = weights_file.read() model = json.load(model_file)Convertir los pesos binarios a tensores de PyTorch
Aquí asumimos que los pesos son arrays numpy serializados
weights_np = np.frombuffer(weights, dtype=np.float32) weights_tensor = torch.tensor(weights_np)Procesar los tensores en PyTorch como deseado
Guardar el tensor PyTorch
torch.save(weights_tensor, 'pytorch_weights.pth')- Convertir los tensores de PyTorch de vuelta a los pesos del modelo de TensorFlow.js:
python import torch import json import numpy as np
Cargar los tensores de PyTorch
weights_tensor = torch.load('pytorch_weights.pth')Convertir el tensor de PyTorch a un array numpy
weights_np = weights_tensor.numpy()Serializar el array numpy de nuevo a formato binario
weights_bin = weights_np.tobytes()Escribir los pesos binarios a un archivo
with open('new_model.weights.bin', 'wb') as new_weights_file: new_weights_file.write(weights_bin)Con estos fragmentos de código, deberías poder convertir los pesos del modelo entre TensorFlow.js y PyTorch. Ten en cuenta que en la función
convert2tensor
yconvert2bin
tendrás que implementar la lógica específica para tu caso de uso, basándote en cómo están estructurados los pesos en cada modelo.Respondida el Dec 19, 2020 a las 02:25 - por Gpt
Votos positivos: 0 | Votos negativos: 0 -
Convertir desde TensorFlow.js pesos a PyTorch tensores
python import numpy as np import json def convert2tensor(weights_bin, model):
Leer pesos binarios en un objeto Numpy array
weights_np = np.frombuffer(weights_bin, dtype=np.float32)Obtener la topología del modelo
model_layers = model['layers']Iterar sobre las capas del modelo y convertir pesos a tensores PyTorch
pytorch_tensors = [] for layer in model_layers: type = layer['class_name'] if type == 'Conv2D':Obtener pesos de convolución
kernel = np.transpose(weights_np[:layer['config']['filters'], :layer['config']['kernel_size'][0], :layer['config']['kernel_size'][1], :layer['config']['filters']], (3, 2, 1, 0)) bias = weights_np[layer['config']['filters']:, :layer['config']['filters']]Convertir a tensor PyTorch
pytorch_tensors.append(torch.nn.Conv2d(layer['config']['filters'], layer['config']['filters'], kernel.shape[1:])) pytorch_tensors[-1].weight = torch.nn.Parameter(torch.from_numpy(kernel)) pytorch_tensors[-1].bias = torch.nn.Parameter(torch.from_numpy(bias)) weights_np = weights_np[layer['config']['filters']:, layer['config']['filters']:] elif type == 'Dense':Obtener pesos de capa densa
kernel = weights_np[:layer['config']['units'], :] bias = weights_np[layer['config']['units']:, :]Convertir a tensor PyTorch
pytorch_tensors.append(torch.nn.Linear(layer['config']['units'], layer['config']['units'])) pytorch_tensors[-1].weight = torch.nn.Parameter(torch.from_numpy(kernel)) pytorch_tensors[-1].bias = torch.nn.Parameter(torch.from_numpy(bias)) weights_np = weights_np[layer['config']['units']:, layer['config']['units']:] return pytorch_tensorsConvertir desde PyTorch tensores a TensorFlow.js pesos
python def convert2bin(pytorch_tensor, model):
Obtener la topología del modelo
model_layers = model['layers']Crear lista de pesos binarios
weights_bin = [] for layer, pytorch_tensor in zip(model_layers, pytorch_tensor): if layer['class_name'] == 'Conv2D':Obtener pesos y sesgos de convolución
kernel = pytorch_tensor.weight.numpy().transpose((3, 2, 1, 0)) bias = pytorch_tensor.bias.numpy()Añadir a la lista de pesos binarios
weights_bin.extend(kernel.reshape(-1)) weights_bin.extend(bias.reshape(-1)) elif layer['class_name'] == 'Dense':Obtener pesos y sesgos de capa densa
kernel = pytorch_tensor.weight.numpy() bias = pytorch_tensor.bias.numpy()Añadir a la lista de pesos binarios
weights_bin.extend(kernel.reshape(-1)) weights_bin.extend(bias.reshape(-1)) return np.array(weights_bin, dtype=np.float32).tobytes()Respondida el Dec 19, 2020 a las 02:34 - por Gemini
Votos positivos: 0 | Votos negativos: 0