English Deutsch 日本語 Português
preview
Añadimos un LLM personalizado a un robot comercial (Parte 3): Entrenando tu propio LLM utilizando la CPU

Añadimos un LLM personalizado a un robot comercial (Parte 3): Entrenando tu propio LLM utilizando la CPU

MetaTrader 5Ejemplos | 7 octubre 2024, 09:24
151 0
Yuqiang Pan
Yuqiang Pan

Introducción

Queridos amigos, ¡cuanto tiempo sin vernos!

Puede que te sorprenda un poco ver este título, pero lo leíste bien: ¡realmente vamos a hacer esto!

En el artículo anterior de esta serie, analizamos la configuración básica del entorno para ejecutar modelos de lenguaje grandes y ejecutamos una instancia LLM simple usando llama.cpp en WSL. ¡La parte más emocionante es que incluso sin una GPU potente, puedes ejecutar el ejemplo únicamente con una CPU! Esta serie de tutoriales reducirá los requisitos de hardware tanto como sea posible, con el objetivo de garantizar que los lectores puedan probar y verificar los ejemplos sin verse obstaculizados por problemas de hardware. Por supuesto, en nuestra parte de entrenamiento modelo, también presentaremos ramas para diferentes plataformas de hardware, incluida una versión de CPU pura y una versión que admite la computación acelerada con tarjetas gráficas AMD, creyendo que todos podrán probar sin limitaciones de hardware.

Por supuesto, usted podría preguntarse: ¿Pueden ser útiles los modelos entrenados con una CPU? ¿Cuál es la importancia de estos modelos? De hecho, si quieres entrenar un modelo con funciones complejas o resolver tareas complejas usando una CPU, es bastante difícil, pero aún es posible usarlo para implementar algunas funciones específicas y relativamente simples.

En este artículo, cubriremos cómo entrenar un modelo de lenguaje grande con una CPU y crear un conjunto de datos financieros necesarios para entrenar modelos de lenguaje grandes. Esto puede implicar conocimientos mencionados en mis otros artículos, que no repetiré aquí. Si los lectores desean profundizar más, lean mis artículos relacionados, donde se proporcionarán enlaces relevantes.

Tabla de contenido:


Acerca de los grandes conjuntos de datos de modelos lingüísticos

Sabemos que en esta etapa, casi todos los modelos de lenguaje grandes se basan en Transformers. No profundizaremos en los principios de Transformers en este artículo, pero los lectores interesados pueden consultar la documentación oficial para comprenderlo. Solo necesitamos saber que los métodos para procesar conjuntos de datos relacionados se han integrado en algunas bibliotecas maduras, como 'Transformers' y 'tiktoken', y estos modelos de procesamiento de datos se pueden encontrar convenientemente en la biblioteca 'Transformers' o la biblioteca 'tiktoken'.


1. Tokenizador

El algoritmo de segmentación del tokenizador es el componente más básico de los modelos de lenguaje NLP. Gracias al tokenizador, el texto se puede convertir en una lista de tokens independientes, que luego se pueden transformar en vectores de entrada que las computadoras pueden entender. En el tokenizador, utilizamos modelos previamente entrenados para normalización de texto, presegmentación, segmentación basada en el modelo de segmentación, posprocesamiento y más. Como se mencionó anteriormente, el tokenizador también integra varios modelos pre-entrenados (como GPT, GPT-2, GPT-J, GPT-Neo, RoBERTa, BART, LLaMA, AlBERT, T5, mBART, XLNet, etc.), y podemos elegir convenientemente diferentes modelos pre-entrenados para procesar datos (por supuesto, también puede entrenar su propio modelo de segmentación).

2. Diferentes tokenizadores tienen diferentes usos y propósitos:

  • Modelos de codificador: Los modelos principales incluyen ALBERT, BERT, DistilBERT, ELECTRA, RoBERTa, adecuados para tareas que requieren la comprensión de oraciones completas, como la clasificación de oraciones, el reconocimiento de entidades con nombre (y, de manera más general, la clasificación de palabras) y la respuesta a preguntas extractivas.
  • Modelos de decodificador: Los modelos principales incluyen 'CTRL', 'GPT', 'GPT-2', Transformer XL. El entrenamiento previo de los modelos decodificadores generalmente gira en torno a la predicción de la siguiente palabra en una oración. Estos modelos son los más adecuados para tareas que implican generación de texto.
  • Modelos de codificador-decodificador: Los modelos principales incluyen 'BART', 'T5', 'Marian', 'mBART'. Estos modelos son más adecuados para tareas que giran en torno a la generación de nuevas oraciones a partir de entradas dadas, como resúmenes, traducciones o respuestas generativas a preguntas.
3. Tokens especiales
Para permitir que el modelo reconozca el comienzo y el final de las secuencias, generalmente agregamos símbolos especiales cuando usamos el tokenizador para la segmentación, como [CLS], [SEP], etc. En este artículo, utilizaremos ['<|endoftext|>'] como terminador de secuencia.


Creando el conjunto de datos

Al entrenar nuestros propios modelos, crear el conjunto de datos suele ser el mayor desafío, porque hay muchos tutoriales sobre cómo entrenar un modelo con un conjunto de datos existente, pero muy pocos te dicen cómo crear tu propio conjunto de datos. Entonces, puedes entrenar fácilmente un modelo, pero no tienes idea de cómo crear un conjunto de datos basado en tus propias ideas. Para esta parte, puede consultar mi serie de artículos en "Marcado de datos en el análisis de series temporales" (incluye 6 artículos, incluido "Marcado de datos en el análisis de series temporales (Parte 1): Creamos un conjunto de datos con marcadores de tendencia utilizando el gráfico de un asesor".), que espero te sirva de inspiración. Por supuesto, también puedes aplicar este conocimiento al entrenamiento de grandes modelos lingüísticos.

Ahora volvamos a nuestro tema. Todavía estamos obteniendo datos del cliente MetaTrader 5 y luego procesándolos. Teniendo en cuenta que trabajamos con una CPU y dado el rendimiento de la mayoría de las PC hasta la fecha, definimos nuestra longitud de secuencia como no demasiado grande. De lo contrario, la ejecución sería demasiado lenta, lo que daría como resultado una experiencia de prueba deficiente. Tenga en cuenta que los ejemplos de este artículo tienen como objetivo demostrar cómo entrenar con una CPU, por lo que la creación del conjunto de datos y el entrenamiento del modelo son solo ejemplos y los resultados pueden no ser ideales. Si desea mejores resultados, es posible que necesite preparar un conjunto de datos más grande o uno que sea más adecuado a las expectativas de la tarea y realizar un procesamiento de datos adicional. Es posible que también sea necesario ajustar los parámetros del modelo en consecuencia, pero estos temas no se tratarán en este ejemplo básico.
Es hora de comenzar a crear el conjunto de datos paso a paso:

1. Definición de variables globales

Se utiliza principalmente para definir rutas de archivos.

DATA_DIR = os.path.dirname(__file__)
data_file = os.path.join(DATA_DIR, "llm_data.csv")


2. Obtención de datos del cliente

Debido a las limitaciones del entrenamiento en una CPU, obtendremos datos para un solo par de divisas con una longitud de 2500 puntos de datos como nuestros datos iniciales.

    mt_data_len=2500
    sr_len=60

    if not mt.initialize():
        print("mt initialize failed!")
    else:
        sbs=mt.symbols_get(group='*micro*')
        if sbs is  not  None:
            # for i in [mt.TIMEFRAME_M5,mt.TIMEFRAME_M15,mt.TIMEFRAME_H1,mt.TIMEFRAME_D1]:

Nota:

Utilizamos la función 'mt.symbols_get(group='*micro*')' para obtener los pares de divisas en nuestro cliente, porque mi cuenta es una cuenta micro, así que usé group='*micro*' para encontrar pares de divisas con "micro". Si está utilizando una cuenta estándar, debe eliminar esta condición; de lo contrario, no encontrará ningún par de divisas. Por supuesto, puedes modificar "micro" para que coincida con los pares de divisas que te interesan, como por ejemplo usar "GBP" para que coincida con todos los pares de divisas con la libra esterlina.


3. División de los datos
Considerando las capacidades computacionales de una CPU, solo tomaremos la columna "close" de las comillas y comenzaremos desde el índice 0, tomando cada 60 comillas como una secuencia y descartando secuencias que tengan una longitud menor a 60. De esta manera, simplemente hemos creado una colección de secuencias, cada una de ellas con una longitud de 60 citas. Por supuesto, la longitud se puede cambiar de acuerdo con la potencia de cálculo de su CPU personal. En principio, cuanto más larga sea la secuencia, mejor será el efecto potencial. En el código, utilizamos dos bucles for para controlar la selección de períodos y variedades, que pueden agregar fácilmente más períodos y más pares de divisas, y el conjunto de datos se puede ajustar en cualquier momento según sea necesario.


            for i in [mt.TIMEFRAME_M5,]: 
                xy=None
                # xy_list=[]
                ct=0
                for j in sbs: 
                    if ct>0:
                        break 
                    print(j.name)
                    d_=mt.copy_rates_from_pos(j.name,i,0,mt_data_len)
                    df_d=pd.DataFrame(d_)
                    cl_d=df_d['close']
                    k=0
                    while k+1:
                        if mt_data_len-k>=sr_len:
                            cl_ds=cl_d[k:k+sr_len].tolist()
                            if xy is None:
                                xy=pd.DataFrame([cl_ds])
                                # xy_list=[cl_ds]
                            else:
                                xy.loc[len(xy)]=cl_ds
                                # xy_list.append(cl_ds)
                            k+=1                       
                        else:
                            break
                    ct+=1
            mt.shutdown()

Nota:

  • Utilizamos la variable "ct" para controlar cuántos datos de pares de divisas obtener.
  • "k" se utiliza para controlar el desplazamiento del índice de datos para obtener datos de secuencia. Si la longitud de la secuencia de datos es menor que la longitud definida en la variable "sr_len", dejará de agregar secuencias al conjunto de datos "xy".


4. Escritura de los datos procesados en un archivo

Por supuesto, este es solo un paso opcional, también puede continuar con el procesamiento de datos sin guardar el archivo. Sin embargo, dado que continuaremos utilizando estos datos en el futuro y no es necesario obtenerlos repetidamente, se recomienda guardarlos.

xy.to_csv(data_file)
En este punto, nuestro propio conjunto de datos está completo. Encapsularemos esta parte del código en una función para facilitar su llamada.
def get_data():
    mt_data_len=2500
    sr_len=60

    if not mt.initialize():
        print("mt initialize failed!")
    else:
        sbs=mt.symbols_get(group='*micro*')
        if sbs is  not  None:
            # for i in [mt.TIMEFRAME_M5,mt.TIMEFRAME_M15,mt.TIMEFRAME_H1,mt.TIMEFRAME_D1]:
            for i in [mt.TIMEFRAME_M5,]: 
                xy=None
                # xy_list=[]
                ct=0
                for j in sbs: 
                    if ct>0:
                        break 
                    print(j.name)
                    d_=mt.copy_rates_from_pos(j.name,i,0,mt_data_len)
                    df_d=pd.DataFrame(d_)
                    cl_d=df_d['close']
                    k=0
                    while k+1:
                        if mt_data_len-k>=sr_len:
                            cl_ds=cl_d[k:k+sr_len].tolist()
                            if xy is None:
                                xy=pd.DataFrame([cl_ds])
                                # xy_list=[cl_ds]
                            else:
                                xy.loc[len(xy)]=cl_ds
                                # xy_list.append(cl_ds)
                            k+=1                       
                        else:
                            break
                    ct+=1
            mt.shutdown()
            
    # print(len(xy),"   ",len(xy_list))
    xy.to_csv(data_file)
    # xy.to_json(f'llm_data.json')
    return xy
Nota: Como se mencionó, la creación del conjunto de datos en este artículo es solo un ejemplo. Puedes cambiar completamente los parámetros internos según tus propias ideas y probarlos.


Proceso de datos

Ya hemos mencionado los tokenizadores y ahora que poseemos un conjunto de datos, el siguiente paso es procesar los datos utilizando un tokenizador. En el ejemplo, utilizaremos la biblioteca tiktoken y elegiremos el modelo preentrenado "gpt2" para codificar nuestro conjunto de datos.

1. Leyendo los datos

Hay dos métodos para obtener los datos que hemos creado: uno es leer el archivo guardado y el otro es utilizar directamente el valor de retorno de la función get_data().

Es importante tener en cuenta que si leemos el archivo guardado, debemos eliminar la primera fila y columna adicionales agregadas durante el proceso de guardado y lectura, mientras que el uso del valor de retorno de la función no requiere esto.
data=get_data()
# data=pd.read_csv(data_file)
# data=data.iloc[1:,1:]
De forma predeterminada, utilizaremos el valor de retorno de la función para obtener los datos.

2. Definición de variables

Aquí necesitamos instanciar el tokenizador y definir tokens especiales. Como se mencionó anteriormente, este artículo utiliza "<|endoftext|>" como inicio y final de la secuencia.
    enc = tiktoken.get_encoding("gpt2")
    encode = lambda s: enc.encode_ordinary(s)
    eot = enc._special_tokens['<|endoftext|>']

    train_tokens=[]
    val_tokens=[]
    val_cut=len(data)//10

Nota:

"val_cut" se utiliza para dividir el conjunto de datos de entrenamiento y el conjunto de validación. Si desea cambiar la relación entre el conjunto de entrenamiento y el conjunto de validación, puede cambiar el número 10 por un valor que considere apropiado. En este ejemplo, se utiliza el 10% de la longitud total de los datos como conjunto de validación.


3. Definición de la función para escribir en un archivo Bin

Antes del procesamiento final de los datos, necesitamos definir la función para escribir los datos procesados en un archivo Bin.

def data_to_file(path, tks):

    header = np.zeros(256, dtype=np.int32)
    header[0] = 20240520
    header[1] = 1
    header[2] = len(tks)
    toks_np = np.array(tks, dtype=np.uint16)
    with open(path, "wb") as f:
        f.write(header.tobytes())
        f.write(toks_np.tobytes())

Esta función en sí no es difícil, pero es importante tener en cuenta el valor "header[0]=20240520", que puede usarse en el entrenamiento posterior del modelo grande. Durante la carga de datos para entrenar el modelo grande, se verificará este valor y, si no coincide, se producirá un error. ¡Esto necesita atención especial!



4. Tokenización de los datos


Primero, usamos un bucle for para recorrer cada fila del conjunto de datos para obtener cada secuencia, con la variable "i" recibiendo el número de fila de la secuencia y "r" recibiendo la secuencia.

for i,r in data.iterrows():
En este punto, 'r' almacena los datos en formato Serie. Primero debemos convertirlo a un formato de lista y luego el formato de lista a una secuencia de cadenas, con el estilo "x,x,x,x,…". Por supuesto, podríamos usar directamente f'{ser}' para convertir la secuencia en una lista envuelta en cadena estilo "[x,x,x,x,x,…]", pero eso parece un poco extraño, así que quedémonos con el estilo "x,x,x,x,x,…".
ser=r.tolist()
ser= ''.join(str(elem) for elem in ser)

A continuación, codificamos la secuencia, almacenando el primer 10% del conjunto de datos en val_tokens y el resto en train_tokens, y llamamos a la función data_to_file() para escribirlos en sus respectivos archivos bin:

tokens = encode(ser)
if i< val_cut:
    val_tokens.append(eot)
    val_tokens.extend(tokens)
    enc_f = os.path.join(DATA_DIR, "val_data.bin")
    data_to_file(enc_f, val_tokens)
else:
    train_tokens.append(eot)
    train_tokens.extend(tokens)
    enc_f = os.path.join(DATA_DIR, "train_data.bin")
    data_to_file(enc_f, train_tokens)
Ahora hemos completado el proceso de tokenización de los datos. Se ha concluido todo el proceso desde la adquisición de datos hasta la tokenización y escribiremos este contenido en un archivo llamado "data_enc.py". El código completo para todo el archivo:
import MetaTrader5 as mt
import pandas as pd
import numpy as np
import os
import tiktoken


DATA_DIR = os.path.dirname(__file__)
data_file = os.path.join(DATA_DIR, "llm_data.csv")

def get_data():
    mt_data_len=2500
    sr_len=60

    if not mt.initialize():
        print("mt initialize failed!")
    else:
        sbs=mt.symbols_get(group='*micro*')
        if sbs is  not  None:
            # for i in [mt.TIMEFRAME_M5,mt.TIMEFRAME_M15,mt.TIMEFRAME_H1,mt.TIMEFRAME_D1]:
            for i in [mt.TIMEFRAME_M5,]: 
                xy=None
                # xy_list=[]
                ct=0
                for j in sbs: 
                    if ct>0:
                        break 
                    print(j.name)
                    d_=mt.copy_rates_from_pos(j.name,i,0,mt_data_len)
                    df_d=pd.DataFrame(d_)
                    cl_d=df_d['close']
                    k=0
                    while k+1:
                        if mt_data_len-k>=sr_len:
                            cl_ds=cl_d[k:k+sr_len].tolist()
                            if xy is None:
                                xy=pd.DataFrame([cl_ds])
                                # xy_list=[cl_ds]
                            else:
                                xy.loc[len(xy)]=cl_ds
                                # xy_list.append(cl_ds)
                            k+=1                       
                        else:
                            break
                    ct+=1
            mt.shutdown()
            
    # print(len(xy),"   ",len(xy_list))
    xy.to_csv(data_file)
    # xy.to_json(f'llm_data.json')
    return xy

def data_to_file(path, tks):

    header = np.zeros(256, dtype=np.int32)
    header[0] = 20240520 
    header[1] = 1 
    header[2] = len(tks) 
    toks_np = np.array(tks, dtype=np.uint16)
    with open(path, "wb") as f:
        f.write(header.tobytes())
        f.write(toks_np.tobytes())

if __name__=="__main__":

    data=get_data()
    # data=pd.read_csv(data_file)
    # data=data.iloc[1:,1:]

    enc = tiktoken.get_encoding("gpt2")
    encode = lambda s: enc.encode_ordinary(s)
    eot = enc._special_tokens['<|endoftext|>']

    train_tokens=[]
    val_tokens=[]
    val_cut=len(data)//10
    for i,r in data.iterrows():
        ser=r.tolist()
        ser=''.join(str(elem) for elem in ser)
        # ser = ser.strip() 
        tokens = encode(ser)
        if i< val_cut:
            val_tokens.append(eot)
            val_tokens.extend(tokens)
            enc_f = os.path.join(DATA_DIR, "val_data.bin")
            data_to_file(enc_f, val_tokens)
        else:
            train_tokens.append(eot)
            train_tokens.extend(tokens)
            enc_f = os.path.join(DATA_DIR, "train_data.bin")
            data_to_file(enc_f, train_tokens)
    print(f"tain:{len(train_tokens)}",f"val:{len(val_tokens)}")

A continuación, entrenaremos nuestro modelo grande. ¡Vamos!
Nota:
  • La primera vez que use la biblioteca tiktoken para la tokenización, se conectará a Internet para descargar el modelo pre-entrenado correspondiente de huggingface, así que asegúrese de que su red pueda acceder a huggingface. Si no puedes acceder, ¡prepara la magia con antelación! Por supuesto, también puedes utilizar un modelo local previamente preparado para tokenizar, pero este artículo no tratará esta parte.
  • Generalmente, el procesamiento de datos de modelos grandes requiere procesamiento de relleno y máscara de los datos. Como nuestro conjunto de datos es pequeño y cada secuencia tiene una longitud fija, no lo hicimos. Pero si desea crear un conjunto de datos grande y complejo, considere cuidadosamente la selección y limpieza de los datos. Este paso es muy importante y afecta en gran medida la calidad del modelo. Además, nuestro procesamiento del conjunto de datos puede ser un poco tosco, pero es suficiente para un ejemplo de demostración.
  • La función del tokenizador en sí es convertir texto en una lista de números, y nuestros datos en sí son numéricos, entonces ¿por qué tokenizarlos? Personalmente, creo que el enfoque del procesamiento depende de la planificación de la tarea del modelo final. Las funciones y tareas diseñadas por el modelo determinan el método de procesamiento de datos.


Entrenando nuestro gran modelo de lenguaje

Inicialmente, esta puede parecer la parte más compleja, pero con la ayuda del proyecto de código abierto llm.c en GitHub, solo necesitamos usar sus archivos de entrenamiento. Los comentarios dentro de todos los archivos son muy detallados y brindan explicaciones para casi cada paso, por lo que no es necesario realizar un análisis o interpretación por separado del código en este artículo.
1. Preparación antes de comenzar el entrenamiento
llm.c project URL: https://github.com/karpathy/llm.c.
La plataforma de código de ejemplo en este artículo es el entorno WSL implementado en Windows como se presentó anteriormente, utilizando miniconda para el entorno del intérprete de Python, con la versión 3.11.5 de Python.
Antes de comenzar la capacitación, utilice git clone para descargar el proyecto llm.c y asegúrese de que las bibliotecas requeridas por requirements.txt del proyecto estén instaladas y que "make" esté instalado en WSL.


git clone  https://github.com/karpathy/llm.c.git

cd llm.c

pip install -r requirements.txt

2. Entrenando nuestro modelo
Primero, abra el cliente MetaTrader 5 en Windows para obtener los datos y localice la posición del archivo data_enc.py (tenga en cuenta que este archivo también debe ubicarse en el entorno de Windows, no he probado si los datos se pueden obtener bajo WSL), y ejecute el comando "python data_enc.py".
python data_enc.py
Después de ejecutar el script, generaremos dos archivos en el mismo directorio, "train_data.bin" y "val_data.bin", que debemos copiar en el sistema de archivos WSL. Por supuesto, dado que WSL puede leer completamente el contenido del sistema de archivos de Windows, copiar los archivos no es un paso obligatorio.
Después de obtener los datos, también necesitamos ejecutar el archivo "train_gpt2.py" en el directorio raíz del proyecto llm.c. Hay dos opciones de referencia:
  • Modifique directamente el valor predeterminado de "--input_bin" en la línea 397 de "train_gpt2.py" para reemplazarlo con la ruta de nuestro archivo de datos, como "dev/data/mt5/val_data.bin", y luego ejecute "python train_gpt2.py".
  • Agregue parámetros directamente en la línea de comando para ubicar nuestro archivo de datos, por ejemplo, "python train_gpt2.py --input_bin dev/data/mt5/val_data.bin".

Elegimos ejecutar este archivo con argumentos en la línea de comando.

python train_gpt2.py --input_bin dev/data/mt5/val_data.bin

Resultados de la ejecución:
tpy

Ajá, resulta ser esto: "<|endoftext|>40% del 80% restante del 20% restante del 40% restante". ¡Este resultado de prueba parece un poco inesperadamente extraño! Pero esto no debe impedirnos seguir adelante, ¡así que continuamos!

De hecho, el archivo "train_gpt2.py" no entrena completamente nuestro modelo, su tarea es tomar un lote de nuestro conjunto de datos para inicializar el modelo y guardará cuatro archivos en formato ".bin":

  • Los archivos de parámetros del modelo se guardan en formatos "float32" y "bfloat16" (los archivos son "gpt2_124M.bin" y "gpt2_124M_bf16.bin", respectivamente);
  • Archivo Tokenizer, llamado "gpt2_tokenizer.bin";
  • Archivo para depurar C, "gpt2_124M_debug_state.bin".


Durante la ejecución del script, se realizarán algunos pasos de inferencia y se generarán resultados que sirven como prueba preliminar del modelo. El resto del código del archivo no se interpretará más en este artículo, ya que el código fuente proporciona comentarios muy detallados que permiten a los lectores comprender claramente todo el proceso.
Después de ejecutar el script "train_gpt2.py", necesitamos compilar el código de entrenamiento. Pero antes de compilar, también necesitamos modificar la ruta de lectura de datos en el código fuente "train_gpt2.c" para el entrenamiento en la CPU. Alrededor de la línea 1041 de este archivo C, hay dos constantes definidas, "const char* train_tokens" y "const char* val_tokens", y necesitamos cambiar sus valores a nuestras propias rutas "train_data.bin" y "val_data.bin". Por ejemplo, después de mi modificación:
    const char* train_tokens = "dev/data/mt5/train_data.bin";
    const char* val_tokens = "dev/data/mt5/val_data.bin";

¡Recuerde no olvidar el ";" al final de la declaración, que es diferente de la sintaxis de Python! De manera similar, no quiero interpretar demasiado el código fuente de este archivo, ya que el código fuente del autor contiene comentarios detallados, lo que facilita la comprensión de todo el proceso de entrenamiento.
Después de modificar el código fuente, ejecute "make train_gpt2" directamente en la línea de comando. Si no ha instalado la biblioteca de computación de aceleración CUDA, este comando compilará directamente el código fuente de entrenamiento en un programa que pueda ejecutarse en la CPU.

Como se muestra en la figura:


Si ha compilado con éxito el programa de entrenamiento, ahora podemos comenzar oficialmente a entrenar nuestro gran modelo de lenguaje. Ejecute directamente el comando "OMP_NUM_THREADS=10 ./train_gpt2" en la línea de comando, donde el parámetro "OMP_NUM_THREADS" especifica la cantidad de subprocesos que utiliza. Establezca un valor apropiado según la cantidad total de subprocesos admitidos por su dispositivo de hardware.

Resultados de la ejecución:

t

El resultado de la prueba durante este proceso de entrenamiento es:

```

generating: --- 30.605360.605540.605590.605510.605650.605510.605650.60550.605550.605540.605590.605540.605590.606107<|endoftext|>0.605640.60 --- ```
Ahora, volviendo a mirar los datos originales, los valores en mi propio archivo "llm_data.csv" son los que se muestran:
d

Vamos a comparar. Los valores originales rondan en su mayoría 0,6, por lo que parece que la salida carece de separadores. Como se mencionó anteriormente, nuestro formato de datos es "x,x,x,x,…", pero la salida se ve como "xxxxxxx…". Sin embargo, no creo que esto sea un problema porque nuestra idea ha sido validada y el modelo grande entrenado simplemente puede generar los resultados que queremos. Este camino es viable y los problemas menores se pueden resolver optimizando el proceso de codificación y decodificación.
Dado que este es solo un ejemplo de demostración, no hemos mencionado guardar el modelo ni probar estrategias comerciales en el cliente. Además, el modelo entrenado en la CPU no necesita guardarse ni probarse debido a problemas de precisión. Creo que si quieres que el modelo sea realmente utilizable, quizá tengas que establecer un proceso científico y esforzarte más. Por ejemplo, diseñar conjuntos de datos para tareas específicas, formular estrategias comerciales apropiadas, diseñar y entrenar un modelo de codificador y decodificador que cumpla con los requisitos de la tarea, establecer hiperparámetros del modelo, etc. Todo esto requiere mucha práctica para completarse, y es poco probable que se explique claramente en unos pocos artículos, por lo que este proceso aún requiere que los lectores lo exploren por su cuenta. Este artículo sólo le ofrece más posibilidades.

Por supuesto, esto también plantea la cuestión de cómo utilizar nuestro modelo de lenguaje entrenado en estrategias comerciales o pruebas. El ejemplo más simple es que podemos ejecutar el servicio de inferencia de modelos grandes en un entorno Python y luego enviar solicitudes de servicio a través del EA de estrategia comercial mediante un socket, con el servicio de inferencia calculando los resultados y devolviéndolos al EA. Esta parte del contenido está detallada en mi "Etiqueta de datos para minería de series temporales (Parte 5): aplicación y prueba en EA mediante socket " artículo, y los lectores interesados pueden probarlo. ¡Este artículo no volverá a discutir el contenido relacionado!

El archivo de script de procesamiento de datos y el archivo de datos obtenido se adjuntan al final del artículo, y el archivo de formato bin procesado no está incluido en el archivo adjunto porque no se admite la carga del formato bin.


Nota:

En el directorio mnt bajo la raíz de WSL, puedes encontrar todas las letras de unidad de nuestro Windows, y puedes ubicar los archivos en Windows bajo la letra de unidad correspondiente de WSL, como "/mnt/g/Program Files". Cabe señalar que si el nombre de la carpeta de Windows contiene espacios, como en el ejemplo, no podemos ingresar a esta carpeta directamente con "cd /mnt/g/Program Files", debemos usar comillas para envolver el nombre de la carpeta con caracteres de espacio, "cd /mnt/g/'Program Files'" es el método correcto.


Conclusión

¡Es increíble, hemos entrenado con éxito nuestro propio modelo de lenguaje grande usando solo una CPU!

Pero no te emociones demasiado pronto, este artículo solo demuestra cómo entrenar nuestro propio modelo de lenguaje grande con una CPU usando un ejemplo simple, y obviamente está limitado por las condiciones del hardware. El modelo entrenado con una CPU puede tener una sola función y no desempeñarse tan bien, pero es innegable que también puede ser una opción para implementar estrategias específicas en el trading cuantitativo.

En el próximo artículo presentaremos cómo utilizar tarjetas gráficas para acelerar el entrenamiento de nuestro modelo. Si está utilizando una tarjeta gráfica AMD, es posible que le moleste descubrir que la aceleración AMD no es compatible con varias bibliotecas comunes (por supuesto, estoy hablando de la etapa actual, es decir, cuando el autor escribió este artículo). Desde una perspectiva a largo plazo, ¡sigo creyendo que el ecosistema de IA de AMD mejorará en el futuro cercano! ¡O un ecosistema de IA como "llama.cpp" que admita todas las plataformas se volverá más popular!), así que, en línea con la intención original de cubrir todas las plataformas tanto como sea posible, discutiremos cómo usar tarjetas gráficas AMD para acelerar el entrenamiento de nuestro gran modelo de lenguaje en el próximo artículo. Puede que no analice cómo usar las tarjetas gráficas NVIDIA para la computación acelerada, porque actualmente estoy usando la plataforma AMD, pero si puedes usar AMD para entrenamiento acelerado, no hay necesidad de hacer un esfuerzo adicional con NVIDIA, que tiene un mejor ecosistema de IA, ¿verdad?

¡Nos vemos en nuestro próximo artículo!


Referencias

llm.c: https://github.com/karpathy/llm.c.git


Traducción del inglés realizada por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/en/articles/13920

Archivos adjuntos |
data_enc.py (2.87 KB)
llm_data.csv (1139.04 KB)
Estrategia de Bill Williams con y sin otros indicadores y predicciones Estrategia de Bill Williams con y sin otros indicadores y predicciones
En este artículo, analizaremos una de las famosas estrategias de Bill Williams, la analizaremos e intentaremos mejorarla con otros indicadores y predicciones.
Algoritmo de optimización Brain Storm - Brain Storm Optimization (Parte II): Multimodalidad Algoritmo de optimización Brain Storm - Brain Storm Optimization (Parte II): Multimodalidad
En la segunda parte del artículo pasaremos a la aplicación práctica del algoritmo BSO, realizaremos tests con funciones de prueba y compararemos la eficacia de BSO con otros métodos de optimización.
Aprendizaje automático y Data Science (Parte 23): ¿Por qué LightGBM y XGBoost superan a muchos modelos de IA? Aprendizaje automático y Data Science (Parte 23): ¿Por qué LightGBM y XGBoost superan a muchos modelos de IA?
Estas técnicas avanzadas de árboles de decisión potenciados por gradiente ofrecen un rendimiento y una flexibilidad superiores, lo que las hace ideales para el modelado financiero y el comercio algorítmico. Aprenda a aprovechar estas herramientas para optimizar sus estrategias comerciales, mejorar la precisión predictiva y obtener una ventaja competitiva en los mercados financieros.
Desarrollamos un asesor experto multidivisa (Parte 8): Realizamos pruebas de carga y procesamos la nueva barra Desarrollamos un asesor experto multidivisa (Parte 8): Realizamos pruebas de carga y procesamos la nueva barra
Conforme hemos ido avanzado, hemos utilizado cada vez más instancias simultáneas de estrategias comerciales en un mismo asesor experto. Hoy intentaremos averiguar a cuántas instancias podemos llegar antes de encontrarnos con limitaciones de recursos.