Generación de lotes equilibrados para conjuntos de datos desequilibrados

PythonPythonBeginner
Practicar Ahora

💡 Este tutorial está traducido por IA desde la versión en inglés. Para ver la versión original, puedes hacer clic aquí

Introducción

En este proyecto, aprenderá a implementar una canalización de datos desequilibrada que puede procesar conjuntos de datos desequilibrados y generar lotes con distribuciones de clases aproximadamente equilibradas. Esta es una tarea común en el aprendizaje automático, donde el conjunto de datos puede tener significativamente más muestras de una clase en comparación con otras, lo que puede conducir a un entrenamiento sesgado del modelo y a un rendimiento pobre.

🎯 Tareas

En este proyecto, aprenderá:

  • Cómo implementar la funcionalidad de submuestreo y sobremuestreo para equilibrar la distribución de muestras dentro de un lote.
  • Cómo generar un lote de muestras con un recuento de muestras igual al tamaño del lote, donde la distribución de las etiquetas dentro del lote sea lo más equitativa posible.
  • Cómo probar la canalización de datos desequilibrada para asegurarse de que funcione como se espera.

🏆 Logros

Después de completar este proyecto, podrá:

  • Manejar conjuntos de datos desequilibrados en el aprendizaje automático.
  • Aplicar técnicas de submuestreo y sobremuestreo para equilibrar las distribuciones de clases.
  • Implementar una canalización de datos que pueda generar lotes equilibrados a partir de un conjunto de datos desequilibrado.

Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL python(("Python")) -.-> python/ControlFlowGroup(["Control Flow"]) python(("Python")) -.-> python/DataStructuresGroup(["Data Structures"]) python(("Python")) -.-> python/FunctionsGroup(["Functions"]) python(("Python")) -.-> python/PythonStandardLibraryGroup(["Python Standard Library"]) python/ControlFlowGroup -.-> python/for_loops("For Loops") python/DataStructuresGroup -.-> python/lists("Lists") python/FunctionsGroup -.-> python/function_definition("Function Definition") python/PythonStandardLibraryGroup -.-> python/data_collections("Data Collections") subgraph Lab Skills python/for_loops -.-> lab-373136{{"Generación de lotes equilibrados para conjuntos de datos desequilibrados"}} python/lists -.-> lab-373136{{"Generación de lotes equilibrados para conjuntos de datos desequilibrados"}} python/function_definition -.-> lab-373136{{"Generación de lotes equilibrados para conjuntos de datos desequilibrados"}} python/data_collections -.-> lab-373136{{"Generación de lotes equilibrados para conjuntos de datos desequilibrados"}} end

Implementar submuestreo y sobremuestreo

En este paso, aprenderá a implementar la funcionalidad de submuestreo y sobremuestreo para equilibrar la distribución de muestras dentro de un lote.

Abra el archivo unbalanced_data_pipeline.py ubicado en el directorio /home/labex/project.

En la función unbalanced_data_pipeline, comience creando un defaultdict llamado counter para almacenar los vectores de características y sus correspondientes vectores de etiqueta codificados en caliente.

    counter = defaultdict(list)
    for x, y in data:
        counter[tuple(y)].append(x)

Esto agrupará los datos por sus vectores de etiqueta, lo que facilitará la realización del submuestreo y el sobremuestreo.

A continuación, calcule el número de muestras que se incluirán en cada lote para cada etiqueta. Esto se puede hacer dividiendo el tamaño del lote por el número de etiquetas únicas, y luego almacenando el resto en la variable num_left.

    batch_data = []
    pre_num = batch_size // len(counter.keys())
    num_left = batch_size % len(counter.keys())

Ahora, itere a través del diccionario counter y muestre aleatoriamente el número requerido de muestras para cada etiqueta. Agregue estas muestras a la lista batch_data.

    for y, x in counter.items():
        samples = random.sample(x, pre_num)
        batch_data.extend([[sample, list(y)] for sample in samples])

Finalmente, maneje las muestras restantes seleccionando aleatoriamente una etiqueta y una muestra de la lista correspondiente, y agregándola a la lista batch_data.

    for _ in range(num_left):
        y = random.choice(list(counter.keys()))
        x = random.choice(counter[y])
        batch_data.append([x, list(y)])

Devuelva la lista batch_data.

    return batch_data

En este paso, ha implementado la funcionalidad de submuestreo y sobremuestreo para equilibrar la distribución de muestras dentro de un lote. La función unbalanced_data_pipeline ahora toma los datos de entrada y el tamaño del lote, y devuelve una lista de lotes con distribuciones de clases aproximadamente equilibradas.

✨ Revisar Solución y Practicar

Probar la canalización de datos desequilibrada

En este paso, probará la función unbalanced_data_pipeline para asegurarse de que funcione como se espera.

Agregue el siguiente código al archivo unbalanced_data_pipeline.py.

if __name__ == "__main__":
    data = [
        [[1, 2, 5], [1, 0]],
        [[1, 6, 0], [1, 0]],
        [[4, 1, 8], [1, 0]],
        [[7, 0, 4], [0, 1]],
        [[5, 9, 4], [0, 1]],
        [[2, 0, 1], [0, 1]],
        [[1, 9, 3], [0, 1]],
        [[5, 5, 5], [0, 1]],
        [[8, 4, 0], [0, 1]],
        [[9, 6, 3], [0, 1]],
        [[7, 7, 0], [0, 1]],
        [[0, 3, 4], [0, 1]],
     ]
    for epoch in range(10):
        batch_data = unbalanced_data_pipeline(data, 6)
        batch_data = list(batch_data)
        print(f"{epoch=}, {batch_data=}")

En el bloque if __name__ == "__main__":, llamamos a la función unbalanced_data_pipeline con los datos de muestra y un tamaño de lote de 6.

Ejecute el archivo unbalanced_data_pipeline.py para ver la salida.

python unbalanced_data_pipeline.py

La salida debería ser similar al ejemplo proporcionado en el desafío original:

epoch=0, batch_data=[[[1, 2, 5], [1, 0]], [[4, 1, 8], [1, 0]], [[1, 6, 0], [1, 0]], [[2, 0, 1], [0, 1]], [[7, 0, 4], [0, 1]], [[5, 9, 4], [0, 1]]]
epoch=1, batch_data=[[[4, 1, 8], [1, 0]], [[1, 2, 5], [1, 0]], [[1, 6, 0], [1, 0]], [[2, 0, 1], [0, 1]], [[9, 6, 3], [0, 1]], [[1, 9, 3], [0, 1]]]
epoch=2, batch_data=[[[4, 1, 8], [1, 0]], [[1, 2, 5], [1, 0]], [[1, 6, 0], [1, 0]], [[5, 5, 5], [0, 1]], [[7, 0, 4], [0, 1]], [[8, 4, 0], [0, 1]]]
epoch=3, batch_data=[[[1, 2, 5], [1, 0]], [[1, 6, 0], [1, 0]], [[4, 1, 8], [1, 0]], [[7, 7, 0], [0, 1]], [[8, 4, 0], [0, 1]], [[0, 3, 4], [0, 1]]]
epoch=4, batch_data=[[[4, 1, 8], [1, 0]], [[1, 6, 0], [1, 0]], [[1, 2, 5], [1, 0]], [[5, 5, 5], [0, 1]], [[0, 3, 4], [0, 1]], [[8, 4, 0], [0, 1]]]
epoch=5, batch_data=[[[1, 6, 0], [1, 0]], [[4, 1, 8], [1, 0]], [[1, 2, 5], [1, 0]], [[2, 0, 1], [0, 1]], [[7, 0, 4], [0, 1]], [[7, 7, 0], [0, 1]]]
epoch=6, batch_data=[[[1, 2, 5], [1, 0]], [[1, 6, 0], [1, 0]], [[4, 1, 8], [1, 0]], [[8, 4, 0], [0, 1]], [[5, 9, 4], [0, 1]], [[0, 3, 4], [0, 1]]]
epoch=7, batch_data=[[[1, 2, 5], [1, 0]], [[1, 6, 0], [1, 0]], [[4, 1, 8], [1, 0]], [[2, 0, 1], [0, 1]], [[0, 3, 4], [0, 1]], [[1, 9, 3], [0, 1]]]
epoch=8, batch_data=[[[1, 6, 0], [1, 0]], [[4, 1, 8], [1, 0]], [[1, 2, 5], [1, 0]], [[7, 7, 0], [0, 1]], [[2, 0, 1], [0, 1]], [[0, 3, 4], [0, 1]]]
epoch=9, batch_data=[[[1, 2, 5], [1, 0]], [[4, 1, 8], [1, 0]], [[1, 6, 0], [1, 0]], [[7, 0, 4], [0, 1]], [[0, 3, 4], [0, 1]], [[5, 5, 5], [0, 1]]]

En este paso, ha probado la función unbalanced_data_pipeline para asegurarse de que funcione como se espera. La función ahora debería ser capaz de procesar los datos desequilibrados y devolver lotes de datos con distribuciones de clases aproximadamente equilibradas.

✨ Revisar Solución y Practicar

Resumen

¡Felicidades! Has completado este proyecto. Puedes practicar más laboratorios en LabEx para mejorar tus habilidades.