English Español Deutsch 日本語
preview
Integre seu próprio LLM no EA (Parte 3): Treinando seu próprio LLM com CPU

Integre seu próprio LLM no EA (Parte 3): Treinando seu próprio LLM com CPU

MetaTrader 5Exemplos | 9 outubro 2024, 10:26
34 0
Yuqiang Pan
Yuqiang Pan

Introdução

Caros amigos, há quanto tempo!

Você pode estar um pouco surpreso ao ver este título, mas leu corretamente, nós realmente vamos fazer isso!

No artigo anterior desta série, discutimos a configuração básica do ambiente para executar grandes modelos de linguagem e rodamos uma instância simples de LLM usando llama.cpp no WSL. A parte mais emocionante é que, mesmo sem uma GPU poderosa, você ainda pode executar o exemplo apenas com um CPU! Esta série de tutoriais reduzirá os requisitos de hardware o máximo possível, esforçando-se para garantir que os leitores possam testar e verificar os exemplos sem serem impedidos por problemas de hardware. Claro, na parte de treinamento do nosso modelo, também introduziremos ramificações para diferentes plataformas de hardware, incluindo uma versão pura de CPU e uma versão que suporta computação acelerada por placas gráficas AMD, acreditando que todos poderão testar sem limitações de hardware.

Claro, você pode se perguntar: Modelos treinados com CPU são úteis? Qual é a importância de tais modelos? De fato, se você quiser treinar um modelo com funções complexas ou para resolver tarefas complexas usando um CPU, é bastante difícil, mas ainda é possível usá-lo para implementar algumas funções específicas e relativamente simples.

Neste artigo, abordaremos como treinar um grande modelo de linguagem com CPU e criar um conjunto de dados financeiros necessário para o treinamento de grandes modelos de linguagem. Isso pode envolver conhecimentos mencionados em outros artigos meus, que não repetirei aqui. Se os leitores quiserem se aprofundar, leiam meus artigos relacionados, onde os links relevantes serão fornecidos.

Índice


Sobre Conjuntos de Dados de Grandes Modelos de Linguagem

Sabemos que, nesta fase, quase todos os grandes modelos de linguagem são baseados em Transformers. Não vamos nos aprofundar nos princípios dos Transformers neste artigo, mas leitores interessados podem consultar a documentação oficial para entender. Precisamos apenas saber que os métodos para processar conjuntos de dados relacionados foram integrados a algumas bibliotecas maduras, como 'Transformers' e 'tiktoken', e esses modelos de processamento de dados podem ser encontrados convenientemente na biblioteca 'Transformers' ou na biblioteca 'tiktoken'.


1. Tokenizer

O algoritmo de segmentação do tokenizer é o componente mais básico dos modelos de linguagem de PNL. Com base no tokenizer, o texto pode ser convertido em uma lista de tokens independentes, que podem ser transformados em vetores de entrada que os computadores conseguem entender. No tokenizer, usamos modelos pré-treinados para normalização de texto, pré-segmentação, segmentação com base no modelo de segmentação, pós-processamento e mais. Como mencionado anteriormente, o tokenizer também integra vários modelos pré-treinados (como GPT, GPT-2, GPT-J, GPT-Neo, RoBERTa, BART, LLaMA, AlBERT, T5, mBART, XLNet, etc.), e podemos escolher convenientemente diferentes modelos pré-treinados para processar dados (claro, você também pode treinar seu próprio modelo de segmentação).

2. Diferentes Tokenizers Têm Diferentes Usos e Propósitos:

  • Modelos de encoder: Os principais modelos incluem ALBERT, BERT, DistilBERT, ELECTRA, RoBERTa, adequados para tarefas que exigem compreensão de frases completas, como classificação de sentenças, reconhecimento de entidades nomeadas (e, mais geralmente, classificação de palavras), e questionário extrativo.
  • Modelos de decoder: Os principais modelos incluem 'CTRL', 'GPT', 'GPT-2', Transformer XL. O pré-treinamento dos modelos de decoder geralmente gira em torno de prever a próxima palavra em uma frase. Esses modelos são mais adequados para tarefas que envolvem geração de texto.
  • Modelos encoder-decoder: Os principais modelos incluem 'BART', 'T5', 'Marian', 'mBART'. Esses modelos são mais adequados para tarefas que envolvem a geração de novas frases com base em entradas dadas, como sumarização, tradução ou respostas generativas a perguntas.
3. Tokens Especiais
Para permitir que o modelo reconheça o início e o fim das sequências, geralmente adicionamos símbolos especiais ao usar o tokenizer para segmentação, como [CLS], [SEP], etc. Neste artigo, usaremos ['<|endoftext|>'] como o terminador de sequência.


Criando o Conjunto de Dados

Ao treinar nossos próprios modelos, criar o conjunto de dados é muitas vezes o maior desafio, porque existem muitos tutoriais sobre como treinar um modelo com um conjunto de dados existente, mas poucos dizem como criar seu próprio conjunto de dados. Assim, você pode facilmente treinar um modelo, mas não saberá como criar um conjunto de dados com base em suas próprias ideias. Para esta parte, você pode consultar minha série de artigos em "Data label for timeseries mining" (inclui 6 artigos, incluindo "Data label for time series mining(Part 1):Make a dataset with trend markers through the EA operation chart"), o que espero que lhe dê alguma inspiração. Claro, você também pode aplicar esse conhecimento ao treinamento de grandes modelos de linguagem.

Agora, voltemos ao nosso tópico. Ainda estamos obtendo dados do cliente MetaTrader5 e depois processando os dados. Considerando que estamos rodando em um CPU, e dado o desempenho da maioria dos PCs até o momento, definimos nosso comprimento de sequência não muito grande. Caso contrário, seria muito lento para rodar, resultando em uma experiência de teste ruim. Por favor, note que os exemplos deste artigo são para fins de demonstração sobre como treinar com um CPU, então a criação do conjunto de dados e o treinamento do modelo são apenas exemplos e os resultados podem não ser ideais. Se você quiser melhores resultados, pode precisar preparar um conjunto de dados maior ou mais adequado às expectativas da tarefa e realizar processamento de dados adicional. Você também pode precisar ajustar os parâmetros do modelo de acordo, mas esses tópicos não serão abordados neste exemplo básico.
É hora de começar a criar o conjunto de dados passo a passo:

1. Definindo Variáveis Globais

Principalmente usadas para definir caminhos de arquivo.

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


2. Obtendo Dados do Cliente

Devido às limitações de treinar em um CPU, obteremos dados de um único par de moedas com um comprimento de 2500 pontos de dados como nossos dados iniciais.

    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]:

Notas:

Usamos a função 'mt.symbols_get(group='micro')' para obter os pares de moedas em nosso cliente, porque minha conta é uma conta micro, então usei group='micro' para encontrar pares de moedas com "micro". Se você estiver usando uma conta padrão, precisará remover essa condição, caso contrário, não encontrará nenhum par de moedas. Claro, você pode modificar "micro" para corresponder aos pares de moedas do seu interesse, como usar "GBP" para encontrar todos os pares de moedas com a libra esterlina.


3. Dividindo os Dados
Considerando as capacidades computacionais de um CPU, vamos pegar apenas a coluna "close" das cotações e começar do índice 0, pegando a cada 60 cotações como uma sequência e descartando sequências que tenham menos de 60 cotações. Dessa forma, criamos simplesmente uma coleção de sequências, cada uma com 60 cotações. Claro, o comprimento pode ser alterado de acordo com o poder computacional do seu CPU. Em princípio, quanto maior a sequência, melhor o efeito potencial. No código, usamos dois loops for para controlar a seleção de períodos e variedades, o que pode adicionar facilmente mais períodos e mais pares de moedas, e o conjunto de dados pode ser ajustado a qualquer momento conforme necessário.


            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()

Notas:

  • Usamos a variável "ct" para controlar quantos dados de pares de moedas serão obtidos.
  • "k" é usada para controlar o deslocamento do índice de dados para obter a sequência de dados. Se o comprimento da sequência de dados for menor que o comprimento definido na variável "sr_len", ele interromperá a adição de sequências ao conjunto de dados "xy".


4. Escrevendo os Dados Processados em um Arquivo

Claro, este é apenas um passo opcional, você também pode continuar o processamento de dados sem salvar o arquivo. No entanto, como continuaremos usando esses dados no futuro e não há necessidade de obtê-los repetidamente, ainda é recomendável salvá-los.

xy.to_csv(data_file)
Neste ponto, nosso próprio conjunto de dados está completo. Vamos encapsular essa parte do código em uma função para facilitar a chamada.
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 mencionado, a criação do conjunto de dados neste artigo é apenas um exemplo. Você pode alterar completamente os parâmetros internos de acordo com suas próprias ideias e testá-los.


Processamento de Dados

Já mencionamos tokenizers e agora possuímos um conjunto de dados. O próximo passo é processar os dados usando um tokenizer. No exemplo, usaremos a biblioteca tiktoken e escolheremos o modelo pré-treinado "gpt2" para codificar nosso conjunto de dados.

1. Lendo os Dados

Existem dois métodos para obter os dados que criamos: um é ler o arquivo salvo, e o outro é usar diretamente o valor de retorno da função get_data().

É importante notar que, se lermos o arquivo salvo, precisaremos remover a primeira linha e a primeira coluna extras adicionadas durante o processo de salvamento e leitura, enquanto usar o valor de retorno da função não requer isso.
data=get_data()
# data=pd.read_csv(data_file)
# data=data.iloc[1:,1:]
Por padrão, usaremos o valor de retorno da função para obter os dados.

2. Definindo Variáveis

Definindo Variáveis
Como mencionado anteriormente, este artigo usa "<|endoftext|>" como o início e o fim da sequência.
    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

Notas:

"val_cut" é usado para dividir o conjunto de dados de treinamento e o conjunto de validação. Se você quiser alterar a proporção do conjunto de treinamento em relação ao conjunto de validação, pode mudar o número 10 para um valor que você considere apropriado. Neste exemplo, 10% do comprimento total dos dados é usado como conjunto de validação.


3. Definindo a Função para Escrever em um Arquivo Binário

Antes do processamento final dos dados, precisamos definir a função para escrever os dados processados em um arquivo binário.

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 função em si não é difícil, mas é importante observar o valor "header[0]=20240520", que pode ser utilizado no treinamento subsequente do grande modelo. Durante o carregamento dos dados para o treinamento do grande modelo, este valor será verificado, e se não corresponder, ocorrerá um erro. Isso requer atenção especial!



4. Tokenizando os Dados


Primeiro, usamos um loop for para percorrer cada linha do conjunto de dados para obter cada sequência, com a variável "i" recebendo o número da linha da sequência e "r" recebendo a sequência.

for i,r in data.iterrows():
Neste ponto, 'r' armazena os dados no formato Series. Precisamos convertê-lo primeiro para o formato de lista, e depois o formato de lista em uma sequência de string, estilizada como "x,x,x,x,…". Claro, poderíamos usar diretamente f'{ser}' para converter a sequência em uma lista no estilo de string "[x,x,x,x,x,…]", mas isso parece um pouco estranho, então vamos manter o estilo "x,x,x,x,x,…".
ser=r.tolist()
ser= ''.join(str(elem) for elem in ser)

Em seguida, codificamos a sequência, armazenando os primeiros 10% do conjunto de dados em val_tokens e o restante em train_tokens, e chamamos a função data_to_file() para gravá-los em seus respectivos arquivos 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)
Agora, concluímos o processo de tokenização dos dados. O processo completo, desde a aquisição dos dados até a tokenização, foi finalizado, e escreveremos esse conteúdo em um arquivo chamado "data_enc.py". O código completo para o arquivo inteiro:
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 seguir, treinaremos nosso grande modelo. Vamos lá!
Nota:
  • Na primeira vez que você usar a biblioteca tiktoken para tokenização, ela se conectará à internet para baixar o modelo pré-treinado correspondente do Huggingface, então, certifique-se de que sua rede possa acessar o Huggingface. Se não puder acessar, prepare-se com antecedência! Claro, você também pode usar um modelo local pré-preparado para tokenização, mas este artigo não discutirá essa parte.
  • Geralmente, o processamento de dados de grandes modelos requer preenchimento (padding) e processamento de máscara. Como nosso conjunto de dados é pequeno e cada sequência tem um comprimento fixo, não fizemos isso. Mas, se você quiser criar um conjunto de dados grande e complexo, considere cuidadosamente a seleção e a limpeza dos dados. Essa etapa é muito importante e afeta muito a qualidade do modelo. Além disso, nosso processamento de dados pode ser um pouco rudimentar, mas é suficiente para um exemplo demonstrativo.
  • A função do tokenizer em si é converter texto em uma lista de números, e nossos dados já são numéricos, então por que tokenizar? Pessoalmente, acredito que a abordagem de processamento depende do planejamento final da tarefa do modelo. As funções e tarefas projetadas pelo modelo determinam o método de processamento de dados.


Treinando Nosso Grande Modelo de Linguagem

Inicialmente, isso pode parecer a parte mais complexa, mas com a ajuda do projeto de código aberto llm.c no GitHub, só precisamos usar seus arquivos de treinamento. Os comentários em todos os arquivos são muito detalhados, fornecendo explicações para quase todas as etapas, então não há necessidade de análise ou interpretação separada do código neste artigo.
1. Preparação Antes de Iniciar o Treinamento
URL do projeto llm.c: https://github.com/karpathy/llm.c.
A plataforma de código de exemplo neste artigo é o ambiente WSL implantado no Windows, como introduzido anteriormente, usando miniconda para o ambiente interpretador Python, com a versão Python 3.11.5.
Antes de iniciar o treinamento, use git clone para baixar o projeto llm.c e certifique-se de que as bibliotecas exigidas pelo requirements.txt do projeto estejam instaladas, e que "make" esteja instalado no WSL.


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

cd llm.c

pip install -r requirements.txt

2. Treinando Nosso Modelo
Primeiro, abra o cliente MetaTrader5 no Windows para obter dados, localize a posição do arquivo data_enc.py (observe que este arquivo também deve ser colocado no ambiente Windows, não testei se os dados podem ser obtidos no WSL) e execute o comando "python data_enc.py".
python data_enc.py
Após a execução do script, dois arquivos serão gerados no mesmo diretório, "train_data.bin" e "val_data.bin", que precisaremos copiar para o sistema de arquivos do WSL. Claro, como o WSL pode ler completamente o conteúdo do sistema de arquivos do Windows, copiar os arquivos não é um passo obrigatório.
Depois de obter os dados, também precisaremos executar o arquivo "train_gpt2.py" no diretório raiz do projeto llm.c. Há duas opções de referência:
  • Modificar diretamente o valor padrão de "--input_bin" na linha 397 de "train_gpt2.py" para substituí-lo pelo caminho do nosso arquivo de dados, como "dev/data/mt5/val_data.bin", e depois rodar "python train_gpt2.py".
  • Adicionar diretamente parâmetros na linha de comando para localizar nosso arquivo de dados, por exemplo, "python train_gpt2.py --input_bin dev/data/mt5/val_data.bin".

Escolhemos rodar este arquivo com argumentos na linha de comando.

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

Resultados da execução:
tpy

Ah ha, parece que é isso: "<|endoftext|>40% dos 80% restantes dos 20% restantes dos 40% restantes". Este resultado de teste parece um pouco estranhamente inesperado! Mas isso não deve nos impedir de continuar, então seguimos em frente!

Na verdade, o arquivo "train_gpt2.py" não treina completamente nosso modelo, sua tarefa é pegar um lote do nosso conjunto de dados para inicializar o modelo e salvará quatro arquivos no formato ".bin":

  • Os arquivos de parâmetros do modelo são salvos nos formatos "float32" e "bfloat16" (os arquivos são "gpt2_124M.bin" e "gpt2_124M_bf16.bin", respectivamente);
  • Arquivo de tokenizer, chamado "gpt2_tokenizer.bin";
  • Arquivo para depuração em C, "gpt2_124M_debug_state.bin".


Durante a execução do script, algumas etapas de inferência serão realizadas e os resultados serão impressos, servindo como um teste preliminar do modelo. O outro código no arquivo não será interpretado mais detalhadamente neste artigo, pois o código fonte fornece comentários muito detalhados, permitindo que os leitores compreendam claramente todo o processo.
Depois de executar o script "train_gpt2.py", precisamos compilar o código de treinamento. Mas, antes de compilar, também precisamos modificar o caminho de leitura dos dados no código-fonte "train_gpt2.c" para o treinamento no CPU. Em torno da linha 1041 deste arquivo C, existem duas constantes definidas, "const char* train_tokens" e "const char* val_tokens", e precisamos alterar seus valores para nossos próprios caminhos "train_data.bin" e "val_data.bin". Por exemplo, após minha modificação:
    const char* train_tokens = "dev/data/mt5/train_data.bin";
    const char* val_tokens = "dev/data/mt5/val_data.bin";

Lembre-se de não esquecer o ";" no final da instrução, o que é diferente da sintaxe do Python! Da mesma forma, não quero interpretar muito do código-fonte deste arquivo, pois o código-fonte do autor contém comentários detalhados, tornando fácil entender todo o processo de treinamento.
Após modificar o código-fonte, execute "make train_gpt2" diretamente na linha de comando. Se você não tiver instalado a biblioteca de computação de aceleração CUDA, este comando irá compilar diretamente o código-fonte de treinamento em um programa que pode ser executado na CPU.

Como mostrado na figura:


Se você compilou com sucesso o programa de treinamento, agora podemos oficialmente começar o treinamento do nosso modelo de linguagem grande. Execute diretamente o comando "OMP_NUM_THREADS=10 ./train_gpt2" na linha de comando, onde o parâmetro "OMP_NUM_THREADS" especifica o número de threads que você usa. Defina um valor apropriado de acordo com o número total de threads suportados pelo seu dispositivo de hardware.

Resultados da execução:

t

A saída de teste durante este processo de treinamento é:

```

generating: --- 30.605360.605540.605590.605510.605650.605510.605650.60550.605550.605540.605590.605540.605590.606107<|endoftext|>0.605640.60 --- ```
Agora, olhando para os dados originais, os valores no meu próprio arquivo "llm_data.csv" são mostrados como: d

Vamos comparar. Os valores originais estão, na maioria, em torno de 0.6, então parece que a saída carece de separadores. Como mencionado anteriormente, nosso formato de dados é "x,x,x,x,…", mas a saída parece como "xxxxxxx…". No entanto, não acredito que isso seja um problema, pois nossa ideia foi validada, e o grande modelo treinado pode simplesmente gerar os resultados que queremos! Esse caminho é viável, e as pequenas questões podem ser resolvidas otimizando o processo de codificação e decodificação.
Como este é apenas um exemplo de demonstração, não mencionamos salvar o modelo ou testar estratégias de negociação no cliente. Além disso, o modelo treinado na CPU não precisa ser salvo e testado devido a questões de precisão. Acredito que, se você quiser que o modelo seja realmente utilizável, será necessário estabelecer um processo científico e investir mais esforço. Por exemplo, projetar conjuntos de dados para tarefas específicas, formular estratégias de negociação adequadas, projetar e treinar um modelo de codificação e decodificação que atenda aos requisitos da tarefa, definir hiperparâmetros do modelo, etc. Tudo isso requer muita prática para ser concluído, e é improvável que seja explicado claramente em alguns artigos, então esse processo ainda exigirá que os leitores explorem por conta própria. Este artigo apenas lhe fornece mais possibilidades.

Claro, isso também levanta a questão de como usar nosso modelo de linguagem treinado em estratégias de negociação ou testes. O exemplo mais simples é que podemos executar o serviço de inferência do grande modelo em um ambiente Python e, em seguida, enviar solicitações de serviço através da estratégia de negociação EA via socket, com o serviço de inferência calculando os resultados e retornando-os ao EA. Essa parte do conteúdo está detalhada no meu artigo "Rótulo de Dados para Mineração de Séries Temporais (Parte 5): Aplicar e Testar no EA Usando Socket", e leitores interessados podem experimentá-lo. Este artigo não discutirá o conteúdo relacionado novamente!

O arquivo do script de processamento de dados e o arquivo de dados obtido estão anexados ao final do artigo, e o arquivo de formato bin processado não está incluído no anexo porque o upload do formato bin não é suportado!


Notas:

No diretório mnt, sob a raiz do WSL, você pode encontrar todas as letras de unidade do nosso Windows e localizar os arquivos no Windows sob a letra de unidade correspondente a partir do WSL, como "/mnt/g/Program Files". Vale ressaltar que, se o nome da pasta do Windows contiver espaços, como no exemplo, não podemos entrar nessa pasta diretamente com "cd /mnt/g/Program Files", precisamos usar aspas para envolver o nome da pasta com caracteres de espaço, "cd /mnt/g/'Program Files'" é o método correto.


Conclusão

É incrível, treinamos com sucesso nosso próprio grande modelo de linguagem usando apenas uma CPU!

Mas não se empolgue muito rapidamente, este artigo apenas demonstra como treinar nosso próprio grande modelo de linguagem com uma CPU usando um exemplo simples, e é obviamente limitado pelas condições de hardware. O modelo treinado com uma CPU pode ter uma função única e não apresentar o melhor desempenho, mas é inegável que também pode ser uma escolha para implementar estratégias específicas em negociação quantitativa.

No próximo artigo, introduziremos como usar placas gráficas para acelerar o treinamento do nosso modelo. Se você está usando uma placa gráfica AMD, pode ficar frustrado ao descobrir que a aceleração da AMD não é suportada em várias bibliotecas comuns (claro, estou falando da fase atual, isto é, quando o autor escreveu este artigo). A longo prazo, ainda acredito que o ecossistema de IA da AMD melhorará em breve! Ou um ecossistema de IA como o "llama.cpp", que suporta todas as plataformas, se tornará mais popular! Portanto, em linha com a intenção original de cobrir o máximo de plataformas possível, discutiremos como usar placas gráficas AMD para acelerar o treinamento do nosso grande modelo de linguagem no próximo artigo! Eu talvez não discuta como usar placas gráficas NVIDIA para computação acelerada, porque atualmente estou usando a plataforma AMD, mas se você puder usar a AMD para treinamento acelerado, não há necessidade de se esforçar demais com a NVIDIA, que possui um ecossistema de IA melhor, certo?

Nos vemos no nosso próximo artigo!


Referências

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


Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/13920

Arquivos anexados |
data_enc.py (2.87 KB)
llm_data.csv (1139.04 KB)
Estratégia de Bill Williams com e sem outros indicadores e previsões Estratégia de Bill Williams com e sem outros indicadores e previsões
Neste artigo, vamos dar uma olhada em uma das estratégias famosas de Bill Williams, discuti-la e tentar melhorá-la com outros indicadores e previsões.
Reimaginando Estratégias Clássicas: Petróleo Bruto Reimaginando Estratégias Clássicas: Petróleo Bruto
Neste artigo, revisitamos uma estratégia clássica de negociação de petróleo bruto com o objetivo de aprimorá-la, utilizando algoritmos de aprendizado de máquina supervisionado. Vamos construir um modelo de mínimos quadrados para prever os preços futuros do petróleo Brent, com base na diferença entre os preços do Brent e do WTI. Nosso objetivo é identificar um indicador líder de futuras mudanças nos preços do Brent.
Está chegando o novo MetaTrader 5 e MQL5 Está chegando o novo MetaTrader 5 e MQL5
Esta é apenas uma breve resenha do MetaTrader 5. Eu não posso descrever todos os novos recursos do sistema por um período tão curto de tempo - os testes começaram em 09.09.2009. Esta é uma data simbólica, e tenho certeza que será um número de sorte. Alguns dias passaram-se desde que eu obtive a versão beta do terminal MetaTrader 5 e MQL5. Eu ainda não consegui testar todos os seus recursos, mas já estou impressionado.
Redes neurais de maneira fácil (Parte 89): Transformador de decomposição por frequência do sinal (FEDformer) Redes neurais de maneira fácil (Parte 89): Transformador de decomposição por frequência do sinal (FEDformer)
Todos os modelos que analisamos anteriormente examinam o estado do ambiente na forma de uma sequência temporal. No entanto, a mesma série temporal pode ser representada por suas características de frequência. Neste artigo, proponho que você conheça um algoritmo que utiliza as características de frequência da sequência temporal para prever estados futuros.