English
preview
Integrieren Sie Ihr eigenes LLM in Ihren EA (Teil 3): Training Ihres eigenen LLM mit CPU

Integrieren Sie Ihr eigenes LLM in Ihren EA (Teil 3): Training Ihres eigenen LLM mit CPU

MetaTrader 5Beispiele | 2 Juli 2024, 11:16
93 0
Yuqiang Pan
Yuqiang Pan

Einführung

Liebe Freunde, lange nicht mehr gesehen!

Dieser Titel mag Sie vielleicht ein wenig überraschen, aber Sie haben richtig gelesen, wir werden das tatsächlich tun!

Im vorigen Artikel dieser Serie haben wir die grundlegende Einrichtung der Umgebung für die Ausführung großer Sprachmodelle besprochen und eine einfache LLM-Instanz mit llama.cpp in WSL ausgeführt. Der spannendste Teil ist, dass Sie das Beispiel auch ohne einen leistungsstarken Grafikprozessor mit einer CPU ausführen können! In dieser Reihe von Tutorials werden die Hardware-Anforderungen so weit wie möglich gesenkt, um sicherzustellen, dass die Leser die Beispiele ausprobieren und verifizieren können, ohne durch Hardware-Probleme behindert zu werden. Natürlich werden wir in unserem Modelltrainingsteil auch Versionen für verschiedene Hardwareplattformen einführen, einschließlich einer reinen CPU-Version und einer Version, die AMD-Grafikkarten-beschleunigtes Rechnen unterstützt, in der Überzeugung, dass jeder in der Lage sein wird, es ohne Hardwarebeschränkungen zu versuchen.

Natürlich könnten Sie sich das fragen: Können mit einer CPU trainierte Modelle nützlich sein? Was ist die Bedeutung solcher Modelle? Wenn Sie ein Modell mit komplexen Funktionen trainieren oder komplexe Aufgaben mit Hilfe einer CPU lösen wollen, ist das zwar recht schwierig, aber es ist dennoch möglich, einige spezifische und relativ einfache Funktionen damit zu implementieren.

In diesem Artikel wird beschrieben, wie man ein großes Sprachmodell mit einer CPU trainiert und einen Finanzdatensatz erstellt, der für das Training großer Sprachmodelle erforderlich ist. Dabei kann es sich um Kenntnisse handeln, die in meinen anderen Artikeln erwähnt wurden und die ich hier nicht wiederholen werde. Wenn Sie tiefer einsteigen möchten, lesen Sie bitte meine verwandten Artikel, in denen Sie die entsprechenden Links finden.

Inhaltsverzeichnis


Über große Sprachmodell-Datensätze

Wir wissen, dass in diesem Stadium fast alle großen Sprachmodelle (Large Language Model Datasets) auf Transformer basieren. Wir werden in diesem Artikel nicht auf die Prinzipien von Transformer eingehen, aber interessierte Leser können sich in der offiziellen Dokumentation informieren. Wir müssen nur wissen, dass die Methoden zur Verarbeitung verwandter Datensätze in einige ausgereifte Bibliotheken wie „Transformer“ und „tiktoken“ integriert wurden, und diese Datenverarbeitungsmodelle können bequem in der „Transformers“-Bibliothek oder der „tiktoken“-Bibliothek gefunden werden.


1. Tokenizer

Der Segmentierungsalgorithmus Tokenizer ist die grundlegendste Komponente von NLP-Sprachmodellen. Auf der Grundlage des Tokenizers kann Text in eine Liste unabhängiger Token umgewandelt werden, die dann in Eingabevektoren umgewandelt werden können, die Computer verstehen können. Im Tokenizer verwenden wir vorab trainierte Modelle für die Textnormalisierung, die Vorsegmentierung, die Segmentierung auf der Grundlage des Segmentierungsmodells, die Nachbearbeitung und mehr. Wie bereits erwähnt, integriert der Tokenizer auch verschiedene vortrainierte Modelle (z. B. GPT, GPT-2, GPT-J, GPT-Neo, RoBERTa, BART, LLaMA, AlBERT, T5, mBART, XLNet usw.), und wir können bequem verschiedene vortrainierte Modelle zur Verarbeitung von Daten auswählen (natürlich können Sie auch Ihr eigenes Segmentierungsmodell trainieren).

2. Verschiedene Tokenizer haben unterschiedliche Verwendungen und Zwecke:

  • Encoder-Modelle: Zu den wichtigsten Modellen gehören ALBERT, BERT, DistilBERT, ELECTRA, RoBERTa, die sich für Aufgaben eignen, die das Verstehen vollständiger Sätze erfordern, wie z. B. die Satzklassifikation, die Erkennung benannter Entitäten (und allgemeiner die Wortklassifikation) und die extraktive Beantwortung von Fragen.
  • Decoder-Modelle: Zu den wichtigsten Modellen gehören „CTRL“, „GPT“, „GPT-2“, Transformer XL. Beim Vortraining von Decoder-Modellen geht es in der Regel um die Vorhersage des nächsten Wortes in einem Satz. Diese Modelle eignen sich am besten für Aufgaben der Texterstellung.
  • Encoder-Decoder-Modelle: Die wichtigsten Modelle sind „BART“, „T5“, „Marian“ und „mBART“. Diese Modelle eignen sich am besten für Aufgaben, bei denen es um die Generierung neuer Sätze auf der Grundlage gegebener Eingaben geht, wie z. B. bei der Zusammenfassung, Übersetzung oder generativen Beantwortung von Fragen.
3. Besondere Tokens
Damit das Modell den Anfang und das Ende von Sequenzen erkennen kann, fügen wir im Allgemeinen spezielle Symbole hinzu, wenn wir den Tokenizer für die Segmentierung verwenden, wie [CLS], [SEP] usw. In diesem Artikel werden wir ['<|endoftext|>'] als Sequenzabschluss verwenden.


Erstellen des Datensatzes

Wenn wir unsere eigenen Modelle trainieren, ist die Erstellung des Datensatzes oft die größte Herausforderung, denn es gibt viele Anleitungen, wie man ein Modell mit einem vorhandenen Datensatz trainiert, aber nur sehr wenige, wie man einen eigenen Datensatz erstellt. Sie können also problemlos ein Modell trainieren, haben aber keine Ahnung, wie Sie einen Datensatz auf der Grundlage Ihrer eigenen Ideen erstellen können. Für diesen Teil können Sie sich auf meine Artikelserie „Datenkennzeichnung für Zeitreihenanalyse“ beziehen (sie umfasst 6 Artikel, darunter „Datenkennzeichnung für Zeitreihenanalyse (Teil 1):Erstellen eines Datensatzes mit Trendmarkierungen durch den EA auf einem Chart“), die Ihnen hoffentlich einige Anregungen geben wird. Natürlich können Sie dieses Wissen auch für das Training großer Sprachmodelle nutzen.

Kommen wir zurück zu unserem Thema. Wir holen noch immer Daten vom MetaTrader5-Client ab und verarbeiten sie dann. In Anbetracht der Tatsache, dass wir auf einer CPU arbeiten, und angesichts der Leistung der meisten heutigen PCs, definieren wir unsere Sequenzlänge nicht zu groß. Andernfalls wäre die Ausführung zu langsam, was zu einer schlechten Testerfahrung führen würde. Bitte beachten Sie, dass die Beispiele in diesem Artikel der Demonstration dienen, wie man mit einer CPU trainiert. Die Erstellung des Datensatzes und das Training des Modells sind also nur Beispiele und die Ergebnisse sind möglicherweise nicht ideal. Wenn Sie bessere Ergebnisse erzielen möchten, müssen Sie möglicherweise einen größeren oder für die Aufgabenerwartungen besser geeigneten Datensatz vorbereiten und eine zusätzliche Datenverarbeitung durchführen. Möglicherweise müssen Sie auch die Modellparameter entsprechend anpassen, aber diese Themen werden in diesem einfachen Beispiel nicht behandelt.
Es ist nun an der Zeit, den Datensatz Schritt für Schritt zu erstellen:

1. Definieren von globalen Variablen

Hauptsächlich verwendet, um Dateipfade zu definieren.

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


2. Beschaffung der Daten vom Terminal

Aufgrund der Einschränkungen beim Training auf einer CPU werden wir Daten für ein einzelnes Währungspaar mit einer Länge von 2500 Datenpunkten als Ausgangsdaten erhalten.

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

Anmerkung:

Wir haben die Funktion „mt.symbols_get(group='*micro*')“ verwendet, um die Währungspaare in unserem Client abzurufen, denn mein Konto ist ein Mikro-Konto, also habe ich group='*micro*' verwendet, um Währungspaare mit „micro“ zu finden. Wenn Sie ein Standardkonto verwenden, müssen Sie diese Bedingung entfernen, da Sie sonst keine Währungspaare finden. Natürlich können Sie „micro“ ändern, um die Währungspaare zu finden, an denen Sie interessiert sind, z. B. „GBP“, um alle Währungspaare mit dem britischen Pfund zu finden.


3. Aufteilung der Daten
In Anbetracht der Rechenkapazitäten einer CPU verwenden wir nur die Spalte „close“ statt aller Kurse und beginnen bei Index 0, wobei wir alle 60 Kurse als eine Sequenz betrachten und Sequenzen mit einer Länge von weniger als 60 verwerfen. Auf diese Weise haben wir einfach eine Sammlung von Sequenzen mit einer Länge von jeweils 60 Kursen erstellt. Natürlich kann die Länge entsprechend der Rechenleistung Ihrer persönlichen CPU geändert werden. Grundsätzlich gilt: Je länger die Sequenz, desto besser die mögliche Wirkung. Im Code haben wir zwei for-Schleifen verwendet, um die Auswahl der Zeitrahmen und Varianten zu steuern. So lassen sich leicht weitere Zeitrahmen und Währungspaare hinzufügen, und der Datensatz kann bei Bedarf jederzeit angepasst werden.


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

Anmerkung:

  • Wir haben die Variable „ct“ verwendet, um zu steuern, wie viele Währungspaardaten abgerufen werden sollen.
  • „k“ wird zur Steuerung des Datenindex-Offsets verwendet, um Sequenzdaten zu erhalten. Wenn die Länge der Datensequenz kleiner ist als die in der Variablen „sr_len“ definierte Länge, wird das Hinzufügen von Sequenzen zum Datensatz „xy“ beendet.


4. Schreiben der verarbeiteten Daten in eine Datei

Natürlich ist dies nur ein optionaler Schritt, Sie können auch mit der Datenverarbeitung fortfahren, ohne die Datei zu speichern. Da wir diese Daten jedoch auch in Zukunft verwenden werden und es nicht notwendig ist, sie wiederholt abzurufen, ist es dennoch empfehlenswert, sie zu speichern.

xy.to_csv(data_file)
Zu diesem Zeitpunkt ist unser eigener Datensatz vollständig. Wir werden diesen Teil des Codes in eine Funktion kapseln, um den Aufruf zu erleichtern.
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
Anmerkung: Wie bereits erwähnt, ist die Erstellung des Datensatzes in diesem Artikel nur ein Beispiel. Sie können die Parameter im Inneren komplett nach Ihren eigenen Vorstellungen verändern und testen.


Datenverarbeitung

Wir haben bereits Tokenizer erwähnt und verfügen nun über einen Datensatz. Der nächste Schritt ist die Verarbeitung der Daten mit einem Tokenizer. In diesem Beispiel verwenden wir die Bibliothek „tiktoken“ und wählen das vortrainierte Modell „gpt2“ zur Kodierung unseres Datensatzes.

1. Lesen der Daten

Es gibt zwei Methoden, um die von uns erstellten Daten zu erhalten: Zum einen kann man die gespeicherte Datei lesen, zum anderen kann man direkt den Rückgabewert der Funktion get_data() verwenden.

Es ist wichtig zu beachten, dass wir beim Lesen der gespeicherten Datei die zusätzliche erste Zeile und Spalte, die während des Speicher- und Lesevorgangs hinzugefügt wurden, entfernen müssen, während dies bei Verwendung des Rückgabewerts der Funktion nicht erforderlich ist.
data=get_data()
# data=pd.read_csv(data_file)
# data=data.iloc[1:,1:]
Wir verwenden standardmäßig den Rückgabewert der Funktion, um die Daten zu erhalten.

2. Definieren von Variablen

Hier müssen wir den Tokenizer instanziieren und spezielle Token definieren. Wie bereits erwähnt, verwendet dieser Artikel „<|endoftext|>“ als Anfang und Ende der Sequenz.
    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

Anmerkung:

Der „val_cut“ wird verwendet, um den Trainingsdatensatz und den Validierungssatz aufzuteilen. Wenn Sie das Verhältnis der Trainingsmenge zur Validierungsmenge ändern möchten, können Sie die Zahl 10 in einen Wert ändern, den Sie für angemessen halten. In diesem Beispiel werden 10 % der Gesamtlänge der Daten als Validierungssatz verwendet.


3. Definieren der Funktion zum Schreiben in eine Bin-Datei

Vor der endgültigen Datenverarbeitung müssen wir die Funktion zum Schreiben der verarbeiteten Daten in eine bin-Datei definieren.

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

Diese Funktion selbst ist nicht schwierig, aber es ist wichtig, den Wert „header[0]=20240520“ zu beachten, der beim anschließenden Training des großen Modells verwendet werden kann. Beim Laden der Daten für das Training des großen Modells wird dieser Wert überprüft, und wenn er nicht übereinstimmt, tritt ein Fehler auf. Dies erfordert besondere Aufmerksamkeit!



4. Tokenisierung der Daten


Zunächst wird in einer for-Schleife jede Zeile des Datensatzes durchlaufen, um jede Sequenz zu erhalten, wobei die Variable „i“ die Zeilennummer der Sequenz und „r“ die Sequenz erhält.

for i,r in data.iterrows():
An dieser Stelle speichert „r“ die Daten im Format „Serie“. Zuerst müssen wir sie in ein Listenformat umwandeln, dann das Listenformat in eine Zeichenkettenfolge, gestylt als „x,x,x,x,...“. Natürlich könnten wir direkt „f'{ser}“ verwenden, um die Sequenz in eine Liste im Stil von „[x,x,x,x,x,...]“ umzuwandeln, aber das scheint etwas seltsam zu sein, also bleiben wir beim Stil „x,x,x,x,x,...“.
ser=r.tolist()
ser= ''.join(str(elem) for elem in ser)

Als Nächstes kodieren wir die Sequenz, indem wir die ersten 10 % des Datensatzes in val_tokens und den Rest in train_tokens speichern, und rufen die Funktion data_to_file() auf, um sie in die entsprechenden bin-Dateien zu schreiben:

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)
Jetzt haben wir die Tokenisierung der Daten abgeschlossen. Der gesamte Prozess von der Datenerfassung bis zur Tokenisierung ist abgeschlossen, und wir werden diesen Inhalt in eine Datei namens „data_enc.py“ schreiben. Der vollständige Code für die gesamte Datei:
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)}")

Als Nächstes werden wir unser großes Modell trainieren. Los geht's!
Anmerkung:
  • Wenn Sie die Bibliothek tiktoken zum ersten Mal für die Tokenisierung verwenden, stellt sie eine Verbindung zum Internet her, um das entsprechende trainierte Modell von „huggingface“ herunterzuladen. Stellen Sie also sicher, dass Ihr Netzwerk auf huggingface zugreifen kann. Wenn Sie keinen Zugang dazu haben, bereiten Sie bitte im Voraus Magie vor! Natürlich können Sie auch ein vorgefertigtes lokales Modell für die Tokenisierung verwenden, aber dieser Artikel wird nicht auf diesen Teil eingehen.
  • Im Allgemeinen erfordert die Verarbeitung großer Modelldaten eine Auffüllung und Maskenverarbeitung der Daten. Da unser Datensatz klein ist und jede Sequenz eine feste Länge hat, haben wir dies nicht getan. Wenn Sie jedoch einen großen und komplexen Datensatz erstellen möchten, sollten Sie die Auswahl und Bereinigung der Daten sorgfältig prüfen. Dieser Schritt ist sehr wichtig und hat großen Einfluss auf die Qualität des Modells. Außerdem ist die Verarbeitung unseres Datensatzes vielleicht etwas grob, aber für ein Demonstrationsbeispiel ist sie ausreichend.
  • Die Funktion des Tokenizers besteht darin, Text in eine Liste von Zahlen umzuwandeln, und unsere Daten selbst sind numerisch, warum also Tokenisieren? Ich persönlich bin der Meinung, dass die Vorgehensweise bei der Bearbeitung von der endgültigen Planung der Modellaufgabe abhängt. Die Funktionen und Aufgaben, die das Modell vorsieht, bestimmen die Art der Datenverarbeitung.


Training unseres großen Sprachmodells

Auf den ersten Blick scheint dies der komplexeste Teil zu sein, aber mit Hilfe des Open-Source-Projekts llm.c auf GitHub müssen wir nur dessen Trainingsdateien verwenden. Die Kommentare in allen Dateien sind sehr detailliert und bieten Erklärungen für fast jeden Schritt, sodass eine separate Analyse oder Interpretation des Codes in diesem Artikel nicht erforderlich ist.
1. Vorbereitung vor Beginn des Trainings
llm.c project URL: https://github.com/karpathy/llm.c.
Die Beispielcodeplattform in diesem Artikel ist die WSL-Umgebung, die wie zuvor beschrieben unter Windows eingesetzt wird, wobei miniconda für die Python-Interpreterumgebung mit Python Version 3.11.5 verwendet wird.
Bevor Sie mit der Training beginnen, laden Sie bitte das Projekt llm.c mit git clone herunter und stellen Sie sicher, dass die in der requirements.txt des Projekts geforderten Bibliotheken installiert sind und dass „make“ in WSL installiert ist.


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

cd llm.c

pip install -r requirements.txt

2. Training unseres Modells
Öffnen Sie zunächst den MetaTrader5-Client unter Windows, um Daten zu erhalten, und suchen Sie die Position der Datei data_enc.py (beachten Sie, dass diese Datei auch in der Windows-Umgebung platziert sein muss, ich habe nicht getestet, ob Daten unter WSL erhalten werden können), und führen Sie den Befehl „python data_enc.py“ aus.
python data_enc.py
Nachdem das Skript ausgeführt wurde, werden zwei Dateien im selben Verzeichnis erzeugt, „train_data.bin“ und „val_data.bin“, die wir in das WSL-Dateisystem kopieren müssen. Da die WSL den Inhalt des Windows-Dateisystems vollständig lesen kann, ist das Kopieren der Dateien natürlich nicht zwingend erforderlich.
Nachdem wir die Daten erhalten haben, müssen wir auch die Datei „train_gpt2.py“ im Stammverzeichnis des Projekts llm.c ausführen. Es gibt zwei Möglichkeiten der Bezugnahme:
  • Ändern Sie direkt den Standardwert von „--input_bin“ in Zeile 397 von „train_gpt2.py“ und ersetzen Sie ihn durch den Pfad unserer Datendatei, z. B. „dev/data/mt5/val_data.bin“, und führen Sie dann „python train_gpt2.py“ aus.
  • Fügen Sie die Parameter direkt in die Befehlszeile ein, um unsere Datendatei zu finden, zum Beispiel „python train_gpt2.py --input_bin dev/data/mt5/val_data.bin“.

Wir haben uns dafür entschieden, diese Datei mit Argumenten in der Befehlszeile auszuführen.

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

Laufende Ergebnisse:
tpy

Ah ha, es stellt sich heraus: „<|endoftext|>40% of the remaining 80% of the remaining 20% of the remaining 40“ (40% der restlichen 80% von den restlichen 20% der restlichen 40)“. Diese Testausgabe scheint ein wenig unerwartet seltsam zu sein! Aber das sollte uns nicht davon abhalten, weiterzumachen, also machen wir weiter!

Die Datei „train_gpt2.py“ trainiert unser Modell nicht vollständig. Ihre Aufgabe ist es, einen Stapel aus unserem Datensatz zu nehmen, um das Modell zu initialisieren und vier Dateien im „.bin“-Format zu speichern:

  • Die Modellparameterdateien werden in den Formaten „float32“ und „bfloat16“ gespeichert (die Dateien heißen „gpt2_124M.bin“ bzw. „gpt2_124M_bf16.bin“);
  • Tokenizer-Datei mit dem Namen „gpt2_tokenizer.bin“;
  • Datei für die Fehlersuche in C, „gpt2_124M_debug_state.bin“.


Während des Skriptlaufs werden einige Schritte der Inferenz durchgeführt und die Ergebnisse ausgegeben, was als vorläufiger Test des Modells dient. Der übrige Code in der Datei wird in diesem Artikel nicht weiter interpretiert, da der Quellcode sehr ausführliche Kommentare enthält, die dem Leser ein klares Verständnis des gesamten Prozesses ermöglichen.
Nach der Ausführung des Skripts „train_gpt2.py“ müssen wir den Trainingscode kompilieren. Vor dem Kompilieren müssen wir jedoch auch den Datenlesepfad im Quellcode „train_gpt2.c“ für das Training auf der CPU ändern. In Zeile 1041 dieser C-Datei sind zwei Konstanten definiert, „const char* train_tokens“ und „const char* val_tokens“, und wir müssen ihre Werte in unsere eigenen Pfade „train_data.bin“ und „val_data.bin“ ändern. Zum Beispiel, nach meiner Änderung:
    const char* train_tokens = "dev/data/mt5/train_data.bin";
    const char* val_tokens = "dev/data/mt5/val_data.bin";

Bitte vergessen Sie nicht das „ ; “ am Ende der Anweisung, das sich von der Python-Syntax unterscheidet! Ebenso möchte ich nicht zu viel vom Quellcode diesem Artikel interpretieren, da der Quellcode des Autors ausführliche Kommentare enthält, die den gesamten Trainingsprozess leicht verständlich machen.
Nachdem Sie den Quellcode geändert haben, führen Sie „make train_gpt2“ direkt in der Befehlszeile aus. Wenn Sie die CUDA-Beschleunigungsbibliothek nicht installiert haben, kompiliert dieser Befehl den Quellcode des Trainings direkt in ein Programm, das auf der CPU ausgeführt werden kann.

Wie in der Abbildung dargestellt:


Wenn Sie das Trainingsprogramm erfolgreich kompiliert haben, können wir nun offiziell mit dem Training unseres großen Sprachmodells beginnen. Führen Sie den Befehl „OMP_NUM_THREADS=10 ./train_gpt2“ direkt in der Befehlszeile aus, wobei der Parameter „OMP_NUM_THREADS“ die Anzahl der von Ihnen verwendeten Threads angibt. Bitte stellen Sie einen angemessenen Wert entsprechend der Gesamtzahl der von Ihrem Hardware-Gerät unterstützten Threads ein.

Laufende Ergebnisse:

t

Die Testausgabe während dieses Trainingsprozesses ist:

```

generating: --- 30.605360.605540.605590.605510.605650.605510.605650.60550.605550.605540.605590.605540.605590.606107<|endoftext|>0.605640.60 --- ```
Wenn ich mir nun die ursprünglichen Daten ansehe, sind die Werte in meiner eigenen Datei „llm_data.csv“ wie folgt:
d

Wir wollen vergleichen. Die Originalwerte liegen meist um 0,6, sodass es der Ausgabe an Trennzeichen zu fehlen scheint. Wie bereits erwähnt, ist unser Datenformat „x,x,x,x,...“, aber die Ausgabe sieht aus wie „xxxxxxx...“. Ich glaube jedoch nicht, dass dies ein Problem ist, denn unsere Idee wurde validiert, das große trainierte Modell kann einfach die von uns gewünschten Ergebnisse ausgeben! Dieser Weg ist machbar, und die geringfügigen Probleme können durch eine Optimierung des Kodierungs- und Dekodierungsprozesses behoben werden.
Da es sich hier nur um ein Demonstrationsbeispiel handelt, haben wir das Speichern des Modells oder das Testen von Handelsstrategien im Client nicht erwähnt. Außerdem muss das auf der CPU trainierte Modell nicht gespeichert und aufgrund von Präzisionsproblemen getestet werden. Ich denke, wenn Sie wollen, dass das Modell wirklich brauchbar ist, müssen Sie ein wissenschaftliches Verfahren einführen und sich mehr Mühe geben. Zum Beispiel das Entwerfen von Datensätzen für bestimmte Aufgaben, das Formulieren geeigneter Handelsstrategien, das Entwerfen und Trainieren eines Encoder- und Decodermodells, das den Anforderungen der Aufgabe entspricht, das Festlegen von Modellhyperparametern usw. All dies erfordert eine Menge Übung, und es ist unwahrscheinlich, dass es in ein paar Artikeln klar erklärt werden kann, sodass dieser Prozess vom Leser selbst weiter erkunden sollte. Dieser Artikel bietet Ihnen nur weitere Möglichkeiten.

Dies wirft natürlich auch die Frage auf, wie unser trainiertes Sprachmodell in Handelsstrategien oder Tests eingesetzt werden kann. Das einfachste Beispiel ist, dass wir den großen Modellinferenzdienst in einer Python-Umgebung ausführen und dann Dienstanforderungen über den Handelsstrategie-EA per Socket senden, wobei der Inferenzdienst die Ergebnisse berechnet und an den EA zurückgibt. Dieser Teil des Inhalts ist in meinem Artikel „Datenkennzeichnung für Zeitreihenanalyse (Teil 5):Anwendung und Test in einem EA, der Socket verwendet“ ausführlich beschrieben, und interessierte Leser können ihn ausprobieren. In diesem Artikel werden die damit zusammenhängenden Inhalte nicht mehr behandelt!

Die Skriptdatei für die Datenverarbeitung und die erhaltene Datendatei sind am Ende des Artikels angehängt. Die verarbeitete Datei im Bin-Format ist nicht im Anhang enthalten, da der Upload im Bin-Format nicht unterstützt wird!


Anmerkung:

Im mnt-Verzeichnis unter dem WSL-Stammverzeichnis finden Sie alle Laufwerksbuchstaben von Windows, und Sie können die Dateien in Windows unter dem entsprechenden Laufwerksbuchstaben von WSL finden, z. B. /mnt/g/Program Files“. Wenn der Name des Windows-Ordners Leerzeichen enthält, wie im Beispiel, können wir diesen Ordner nicht direkt mit „cd /mnt/g/Program Files“ eingeben, sondern müssen den Ordnernamen in Anführungszeichen setzen; „ cd /mnt/g/'Program Files' “ ist die richtige Methode.


Schlussfolgerung

Es ist unglaublich, wir haben erfolgreich unser eigenes großes Sprachmodell mit nur einer CPU trainiert!

Aber freuen Sie sich nicht zu früh, denn dieser Artikel zeigt nur anhand eines einfachen Beispiels, wie wir unser eigenes großes Sprachmodell mit einer CPU trainieren können, und das ist natürlich durch die Hardwarebedingungen eingeschränkt. Das mit einer CPU trainierte Modell mag eine einzige Funktion haben und nicht so gut funktionieren, aber es ist unbestreitbar, dass es auch für die Umsetzung spezifischer Strategien im quantitativen Handel eine gute Wahl sein kann.

Im nächsten Artikel werden wir vorstellen, wie wir Grafikkarten nutzen können, um das Training unseres Modells zu beschleunigen. Wenn Sie eine AMD-Grafikkarte verwenden, werden Sie sich vielleicht darüber ärgern, dass die AMD-Beschleunigung in verschiedenen gängigen Bibliotheken nicht unterstützt wird. (Ich spreche natürlich vom aktuellen Stand, d.h. als der Autor diesen Artikel geschrieben hat. Langfristig gesehen glaube ich immer noch, dass das KI-Ökosystem von AMD in naher Zukunft besser werden wird! Oder ein KI-Ökosystem wie „llama.cpp“, das alle Plattformen unterstützt, wird populärer werden, sodass wir im Einklang mit der ursprünglichen Absicht, alle Plattformen so weit wie möglich abzudecken.) Im nächsten Artikel werden wir erörtern, wie man AMD-Grafikkarten zur Beschleunigung des Trainings unseres großen Sprachmodells einsetzen kann! Ich werde zwar nicht erörtern, wie man NVIDIA-Grafikkarten für beschleunigtes Computing verwendet, weil ich derzeit die AMD-Plattform verwende, aber wenn man AMD für beschleunigtes Training verwenden kann, gibt es keinen Grund, die Extrameile mit NVIDIA zu gehen, das ein besseres KI-Ökosystem hat, richtig?

Wir sehen uns in unserem nächsten Artikel!


Referenzen

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


Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/13920

Beigefügte Dateien |
data_enc.py (2.87 KB)
llm_data.csv (1139.04 KB)
Bill Williams Strategie mit und ohne andere Indikatoren und Vorhersagen Bill Williams Strategie mit und ohne andere Indikatoren und Vorhersagen
In diesem Artikel werden wir einen Blick auf eine der berühmten Strategien von Bill Williams werfen, sie diskutieren und versuchen, die Strategie mit anderen Indikatoren und mit Vorhersagen zu verbessern.
Verschaffen Sie sich einen Vorteil auf jedem Markt (Teil II): Vorhersage technischer Indikatoren Verschaffen Sie sich einen Vorteil auf jedem Markt (Teil II): Vorhersage technischer Indikatoren
Wussten Sie, dass die Vorhersage bestimmter technischer Indikatoren genauer ist als die Vorhersage des zugrunde liegenden Preises eines gehandelten Symbols? Lernen Sie mit uns, wie Sie diese Erkenntnisse für bessere Handelsstrategien nutzen können.
MQL5-Assistenten-Techniken, die Sie kennen sollten (Teil 21): Testen mit Wirtschaftskalenderdaten MQL5-Assistenten-Techniken, die Sie kennen sollten (Teil 21): Testen mit Wirtschaftskalenderdaten
Die Daten des Wirtschaftskalenders sind standardmäßig nicht für das Testen mit Expert Advisors im Strategy Tester verfügbar. Wir sehen uns an, wie Datenbanken helfen können, diese Einschränkung zu umgehen. In diesem Artikel untersuchen wir, wie SQLite-Datenbanken verwendet werden können, um Wirtschaftskalender-Nachrichten zu archivieren, sodass assistentengestützte Expert Advisors diese nutzen können, um Handelssignale zu generieren.
Aufbau des Kerzenmodells Trend-Constraint (Teil 4): Anpassen des Anzeigestils für jede Trendwelle Aufbau des Kerzenmodells Trend-Constraint (Teil 4): Anpassen des Anzeigestils für jede Trendwelle
In diesem Artikel werden wir die Möglichkeiten der leistungsstarken MQL5-Sprache beim Zeichnen verschiedener Indikatorstile in Meta Trader 5 untersuchen. Wir werden uns auch mit Skripten beschäftigen und wie sie in unserem Modell verwendet werden können.