es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Quedando sin RAM utilizando FilePerUserClientData.

Tengo un problema con el entrenamiento usando tff.simulation.FilePerUserClientData – Estoy quedándome rápidamente sin RAM después de 5-6 rondas con 10 clientes por ronda. El uso de RAM aumenta constantemente con cada ronda. Intenté reducirlo y me di cuenta de que el problema no es el proceso iterativo en sí, sino la creación de los conjuntos de datos de los clientes. Simplemente llamar a create_tf_dataset_for_client(client) en un bucle causa el problema.

Entonces, esta es una versión mínima de mi código:

import tensorflow as tf
import tensorflow_federated as tff
import numpy as np
import pickle

TAMAÑO_LOTE = 16
ÉPOCAS = 2
LONGITUD_MÁXIMA_SECUENCIA = 20
NUM_RONDAS = 100
CLIENTES_POR_RONDA = 10

def decode_fn(datos_registro):
    return tf.io.parse_single_example(
        datos_registro,
        {"x": tf.io.FixedLenFeature([LONGITUD_MÁXIMA_SECUENCIA], dtype=tf.string),
         "y": tf.io.FixedLenFeature([LONGITUD_MÁXIMA_SECUENCIA], dtype=tf.string)}
    )

def obtener_dataset(ruta):
    return tf.data.TFRecordDataset([ruta]).map(decode_fn).padded_batch(TAMAÑO_LOTE).repeat(ÉPOCAS)

def obtener_datos_cliente(metadatos, ids_clientes, probabilidad_muestreo):
    total_clientes = len(ids_clientes)
    x = np.random.uniform(size=total_clientes)
    ids_seleccionados = [ids_clientes[i] for i in range(total_clientes) if x[i] < probabilidad_muestreo]
    datos = [metadatos.create_tf_dataset_for_client(cliente) for cliente in ids_seleccionados]
    return datos

with open('users.pkl', 'rb') as f:
    usuarios = pickle.load(f)

ids_clientes_entrenamiento = usuarios["train"]
id_cliente_a_archivo_entrenamiento = {i: "reddit_leaf_tf/" + i for i in ids_clientes_entrenamiento}

datos_entrenamiento = tff.simulation.datasets.FilePerUserClientData(
    client_ids_to_files=id_cliente_a_archivo_entrenamiento,
    dataset_fn=obtener_dataset
)

probabilidad_muestreo = CLIENTES_POR_RONDA / len(ids_clientes_entrenamiento)

for num_ronda in range(0, NUM_RONDAS):
    print('Ronda {r}'.format(r=num_ronda))
    datos_participantes = obtener_datos_cliente(datos_entrenamiento, ids_clientes_entrenamiento, probabilidad_muestreo)
    print("Ronda completada")

Estoy usando tensorflow-federated 19.0.

¿Hay algo mal en la forma en que creo los conjuntos de datos de los clientes o es de alguna manera esperado que la RAM de la ronda anterior no se libere?

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Parece que el problema está en la forma en que creas los conjuntos de datos del cliente. Específicamente, llamar a create_tf_dataset_for_client(client) en un bucle puede hacer que el programa se quede rápidamente sin memoria. Esto se debe a que cada llamada a create_tf_dataset_for_client(client) crea un nuevo objeto de conjunto de datos que se almacena en la memoria. Con muchas iteraciones, esto puede hacer que el programa agote toda la memoria disponible.

    Para solucionar este problema, puedes intentar cargar previamente todos los datos del cliente en la memoria antes de iniciar el bucle de entrenamiento. Por ejemplo, puedes modificar tu función sample_client_data de la siguiente manera:

    def sample_client_data(data, client_ids, sampling_prob):
        clients_total = len(client_ids)
        x = np.random.uniform(size=clients_total)
        sampled_ids = [client_ids[i] for i in range(clients_total) if x[i] < sampling_prob]
        data = [data.create_tf_dataset_for_client(client) for client in sampled_ids]
        data = [list(dataset.as_numpy_iterator()) for dataset in data]
        return data
    

    Esta modificación carga todos los datos de cada cliente seleccionado en la memoria como una lista de matrices numpy, de modo que el programa ya no necesita crear repetidamente nuevos objetos de conjunto de datos en cada ronda. Al hacer esto, puedes reducir significativamente el uso de memoria de tu programa.

    En cuanto a la pregunta de si se libera la RAM de la ronda anterior, eso depende de cómo estés ejecutando tu programa. Si estás ejecutando múltiples rondas dentro del mismo proceso de Python, es posible que la memoria utilizada por la ronda anterior no se libere hasta que el proceso se termine. Sin embargo, si estás ejecutando cada ronda en un proceso o contenedor separado, entonces la memoria debería liberarse automáticamente al final de cada ronda.

Comments are closed.