
Integrieren Sie Ihr eigenes LLM in EA (Teil 5): Handelsstrategie mit LLMs(II)-LoRA-Tuning entwickeln und testen
Inhaltsverzeichnis
- Inhaltsverzeichnis
- Einführung
- Umgebung Konfiguration
- LoRA-Konfiguration
- LoRA-Tuning
- Vergleich verschiedener Feinsteuerungsmethoden
- Schlussfolgerung
Einführung
Im vorangegangenen Artikel haben wir die Feinabstimmung des vortrainierten GPT-2-Modells anhand unserer eigenen Finanzdaten mit einer Vollparameter-Feinabstimmungsmethode vorgestellt und die Ausgabeergebnisse des Modells bewertet. In diesem und den folgenden Artikeln werden wir anhand von Code-Beispielen erörtern, wie andere Feinabstimmungsmethoden implementiert werden können (wir werden nur die im vorherigen Artikel vorgestellten Feinabstimmungsmethoden erörtern, und natürlich ist es unmöglich, jede Methode zu implementieren. Ich werde nur einige häufig verwendete Methoden zur Umsetzung auswählen). In diesem Artikel wird die LoRA-Tuning-Methode als Beispiel für die Diskussion herangezogen.
Außerdem müssen wir versuchen, die mit diesen verschiedenen Feinabstimmungsmethoden trainierten Modelle horizontal zu vergleichen und dann das Modell mit der besten Leistung für das aktuelle Währungspaar zu finden (natürlich kann die Leistung des Modells auch unter verschiedenen Marktbedingungen variieren, z. B. bei Aufwärtstrends, Abwärtstrends oder schwankenden Trends). Dies kann uns einen klareren Hinweis darauf geben, welche Methode der Modelltraining wir in der Praxis anwenden sollten, um bessere Ergebnisse zu erzielen. Wenn wir strenger sind, sollten wir natürlich nicht nur diese verschiedenen Verarbeitungsmethoden horizontal vergleichen, sondern auch die Leistung der Feinabstimmungsmodelle verschiedener Währungspaare unter verschiedenen Datenverarbeitungsmethoden und Feinabstimmungsmethoden vergleichen. Dies scheint eine einfache, aber äußerst mühsame Aufgabe zu sein. Ich persönlich glaube, dass dieser Schritt von entscheidender Bedeutung ist, wenn wir diese Reihe von Methoden im Handel wirklich anwenden wollen. Ich habe jedoch nicht die Absicht, diesen Teil in dieser Artikelserie im Detail vorzustellen, weil ich glaube, dass jeder anhand unserer Beispiele leicht erweitern kann. Ersetzen Sie einfach die Trainingsdaten durch verschiedene Währungspaare und vergleichen Sie dann die Modellleistung horizontal. Dies ist zwar mühsam, aber leicht zu bewerkstelligen.
Ein weiterer Punkt ist, dass ich in früheren Artikeln versäumt habe, die entsprechenden Umgebungskonfigurationen und Bibliotheksabhängigkeiten in den Beispielcode einzufügen, was dazu führen kann, dass einige Freunde beim Versuch, die Beispiele auszuführen, auf Fehler aufgrund fehlender Abhängigkeiten stoßen. In zukünftigen Artikeln werde ich die Umgebungskonfiguration und die Abhängigkeiten, die im aktuellen Code verwendet werden, ausführlich erläutern, um den Lesern die Ausführung der Beispiele zu erleichtern.
Kommen wir nun offiziell zum Thema dieses Artikels!
Umgebung Konfiguration
Nachfolgend finden Sie die Betriebsumgebung für die Codebeispiele in diesem Artikel. Das bedeutet natürlich nicht, dass Ihre Code-Umgebung die gleiche sein muss wie meine, aber wenn Sie beim Ausführen des Codes auf Probleme stoßen, können Sie sich an meiner Umgebungskonfiguration orientieren. - Betriebssystem: Ubuntu 22.04.5 LTS (oder die entsprechende Version von WSL)
- Python-Version: 3.10.14
- Erforderliche Python-Bibliotheken:
- torch-2.4.1
- numpy-1.26.3
- pandas-2.2.3
- transformers-4.45.1
- petf-0.13.0
- matplotlib-3.9.2
Wenn Sie mit der Konfiguration der Code-Ausführungsumgebung nicht vertraut sind, finden Sie in anderen Artikeln dieser Reihe ausführliche Einführungen:
- Nutzer von AMD-Grafikkarten können sich auf den vorhergehenden Artikel beziehen (Integrieren Sie Ihr eigenes LLM in einem EA (Teil 4): Trainieren Sie Ihr eigenes LLM mit GPU)
- Nutzer von NVIDIA-Grafikkarten können den zweiten Artikel dieser Serie lesen (Integrieren Sie Ihr eigenes LLM in einem EA (Teil 2): Beispiel für den Einsatz in einer Umgebung)
Dieser Artikel wird keine detaillierte Einführung in diesen Teil geben.
LoRA-Konfiguration
Wir haben LoRA bereits im vorangegangenen Artikel vorgestellt, sodass wir die Beschreibung in diesem Artikel nicht wiederholen werden. Um den Prozess der Feinabstimmung einfacher und übersichtlicher zu gestalten, wird in diesem Artikel nicht das Codebeispiel des ursprünglichen LoRA-Autors reproduziert, sondern die einfachere peft-Bibliothek verwendet.
Diese Python-Bibliothek integriert verschiedene Konfigurationen, die wir benötigen, einschließlich der LoRA-Tuning-Parameter-Konfigurationsklasse (LoraConfig), der LoRA-Tuning-Initialisierungsmodellmethode (get_peft_model) und der LoRA-Feinabstimmungsmodell-Ladeklasse (PeftModel).
Als Nächstes werde ich sie Schritt für Schritt vorstellen, beginnend mit der Klasse LoraConfig.
1. LoraConfig-Klasse
Die Klasse LoraConfig gehört zur peft-Bibliothek und kann direkt aus der peft-Bibliothek importiert werden. Nachdem Sie die Klasse LoraConfig importiert haben, müssen Sie ihre Konfigurationsparameter festlegen.
Als Nächstes stellen wir die Parameterkonfiguration in der Klasse „LoraConfig“ vor
- r (`int`):
Lora Aufmerksamkeitsdimension (der Rang bzw. „rank").
- target_modules (`Optional[Union[List[str], str]]`):
Die Namen der Module, auf die der Adapter angewendet werden soll. Wenn dies angegeben wird, werden nur die Module mit den angegebenen Namen ersetzt. Bei Übergabe einer Zeichenkette wird eine Regex-Übereinstimmung durchgeführt. Bei der Übergabe einer Liste von Zeichenketten wird entweder eine exakte Übereinstimmung durchgeführt oder es wird geprüft, ob der Name des Moduls mit einer der übergebenen Zeichenketten endet. Wird hier „all-linear“ angegeben, werden alle linearen/Conv1D-Module ausgewählt, mit Ausnahme der Ausgabeschicht. Wenn dies nicht angegeben wird, werden die Module entsprechend der Modellarchitektur ausgewählt. Wenn die Architektur nicht bekannt ist, wird eine Fehlermeldung ausgegeben - in diesem Fall sollten Sie die Zielmodule manuell angeben.
- lora_alpha (`int`):
Der Alpha-Parameter für die Lora-Skalierung.
- lora_dropout (`float`):
Die Abbrecherwahrscheinlichkeit für Lora-Schichten.
- fan_in_fan_out (`bool`):
Setzen Sie diesen Wert auf True, wenn die zu ersetzende Ebene Gewichtungen wie (fan_in, fan_out) enthält. Zum Beispiel verwendet gpt-2 „Conv1D“, das Gewichte wie (fan_in, fan_out) speichert und daher auf „True“ gesetzt werden sollte.
- bias (`str`):
Das Bias für LoRA. Möglich sind: „none“, „all“ or „lora_only“. Bei „all“ oder „lora_only“ werden die entsprechenden Verzerrungen während des Trainings aktualisiert. Dies bedeutet, dass das Modell auch bei deaktivierten Adaptern nicht die gleiche Leistung erbringt wie das Basismodell ohne Anpassung.
- use_rslora (`bool`):
Wenn auf True gesetzt, wird <a href='https://doi.org/10.48550/arXiv.2312.03732'>Rank-Stabilized LoRA</a> verwendet, das den Skalierungsfaktor des Adapters auf „lora_alpha/math.sqrt(r)“ setzt, da es sich als besser erwiesen hat. Andernfalls wird der ursprüngliche Standardwert von „lora_alpha/r“ verwendet.
- modules_to_save (`List[str]`):
Liste der Module mit Ausnahme der Adapterschichten, die als trainierbar einzustufen und im letzten Checkpoint zu speichern sind.
- init_lora_weights (`bool` | `Literal["gaussian", "olora", "pissa", "pissa_niter_[number of iters]", "loftq"]`):
Wie man die Gewichte der Adapterschichten initialisiert. Die Übergabe von True (der Standard) führt zu der Standardinitialisierung aus der Referenzimplementierung von Microsoft. Die Übergabe von „gaussian“ führt zu einer Gauß-Initialisierung, skaliert mit dem LoRA-Rang für linear und Schichten. Das Setzen der Initialisierung auf False führt zu einer völlig zufälligen Initialisierung und wird nicht empfohlen. Übergeben Sie „loftq“, um die LoftQ-Initialisierung zu verwenden. Übergeben Sie „olora“, um die OLoRA-Initialisierung zu verwenden. Die Übergabe von „pissa“ führt zur Initialisierung von <a
href='https://arxiv.org/abs/2404.02948'>Principal Singular values and Singular vectors Adaptation (PiSSA)</a>, das schneller konvergiert als LoRA und letztlich eine bessere Leistung erzielt. Darüber hinaus reduziert PiSSA den Quantisierungsfehler im Vergleich zu QLoRA, was zu weiteren Verbesserungen führt. Übergabe
„pissa_niter_[number of iters]'` leitet die Fast-SVD-basierte PiSSA-Initialisierung ein, wobei „[number of iters]“ die Anzahl der Unterraum-Iterationen für die Durchführung der FSVD angibt und eine nichtnegative ganze Zahl sein muss. Wenn „[number of iters]“ auf 16 gesetzt wird, kann die Initialisierung eines 7B-Modells innerhalb von Sekunden abgeschlossen werden, und der Trainingseffekt entspricht in etwa der Verwendung von SVD.
- layers_to_transform (`Union[List[int], int]`):
Die zu transformierenden Ebenenindizes. Wenn eine Liste von Ints übergeben wird, wird der Adapter auf die in dieser Liste angegebenen Ebenenindizes angewendet. Wenn eine einzelne ganze Zahl übergeben wird, werden die Transformer auf die Ebene mit diesem Index angewendet.
- layers_pattern (`str`):
Der Name des Ebenenmusters, der nur verwendet wird, wenn `layers_to_transform` anders als `None` ist.
- rank_pattern (`dict`):
Die Zuordnung von Ebenennamen oder Regexp-Ausdrücken zu Rängen, die sich von dem durch „r“ angegebenen Standardrang unterscheiden.
- alpha_pattern (`dict`):
Die Zuordnung von Ebenennamen oder Regexp-Ausdrücken zu Alphas, die sich von dem durch „Lora_alpha“ festgelegten Standard-Alpha unterscheiden.
- megatron_config (`Optional[dict]`):
Die TransformerConfig-Argumente für Megatron. Sie wird verwendet, um die parallele lineare Ebene von LoRA zu erstellen. Sie können es so erhalten, „core_transformer_config_from_args(get_args())“, diese beiden Funktionen sind von Megatron. Die Argumente werden verwendet, um die TransformerConfig von Megatron zu initialisieren. Sie müssen diesen Parameter angeben, wenn Sie LoRA auf die Ebenen ColumnParallelLinear und RowParallelLinear von megatron anwenden wollen.
- megatron_core (`Optional[str]`):
Das zu verwendende Kernmodul von Megatron, Standardwert ist „megatron.core“.
- loftq_config (`Optional[LoftQConfig]`):
Die Konfiguration von LoftQ. Wenn dies nicht None ist, wird LoftQ zur Quantisierung der Backbone-Gewichte und zur Initialisierung der Lora-Schichten verwendet. Übergeben Sie auch init_lora_weights='loftq'. Beachten Sie, dass Sie in diesem Fall kein quantisiertes Modell übergeben sollten, da LoftQ das Modell selbst quantisieren wird.
- use_dora (`bool`):
Aktivieren Sie die „Weight-Decomposed Low-Rank Adaptation“ (DoRA). Bei dieser Technik werden die Aktualisierungen der Gewichte in zwei Teile zerlegt, nämlich in Größe und Richtung. Die Richtung wird durch die normale LoRA gehandhabt, während die Größe durch einen separaten lernbaren Parameter gehandhabt wird. Dies kann die Leistung von LoRA insbesondere bei niedrigen Rängen verbessern. Derzeit unterstützt DoRA nur lineare und Conv2D-Ebenen. DoRA führt zu einem größeren Overhead als reines LoRA, daher wird empfohlen, die Gewichte für die Inferenz zusammenzuführen. Weitere Informationen finden Sie unter https://arxiv.org/abs/2402.09353.
- layer_replication (`List[Tuple[int, int]]`):
Wir erstellen einen neuen Stapel von Ebenen, indem wir die ursprünglichen Modellebenen entsprechend den angegebenen Bereichen stapeln. Dadurch kann das Modell erweitert (oder verkleinert) werden, ohne dass die Gewichte des Basismodells dupliziert werden. Die neuen Ebenen werden alle mit separaten LoRA-Adaptern ausgestattet.
- runtime_config (`LoraRuntimeConfig`):
Laufzeitkonfigurationen (die nicht gespeichert oder wiederhergestellt werden).
Dies sind alle Parameter der Klasse LoraConfig. In der Praxis werden in der Regel nicht alle Werte eingestellt, sondern nur einige wichtige Parameter, die wir benötigen, und die anderen als Standardwerte beibehalten. In unserem Beispiel setzen wir nur die folgenden Parameter: lora_alpha=32, lora_dropout=0.1, und belassen die anderen Parameter als Standard. Natürlich stellen die in diesem Artikel genannten Einstellungen nicht die optimale Wahl dar. Sie können jederzeit einige Parameterkombinationen auswählen und verschiedene Einstellungen ausprobieren, um die optimale Parameterkombination zu finden.
peft_config = LoraConfig( lora_alpha=32, lora_dropout=0.1)
2. Die Funktion get_peft_model()
Die Funktion get_peft_model() kann auch direkt aus der peft-Bibliothek importiert werden. Wir müssen es verwenden, um unser GPT-2-Modell als ein Modell zu laden, das die angegebene Konfiguration vor der Feinabstimmung erfüllt. Im Beispiel dieses Artikels werden wir GPT-2 als konfiguriertes LoRA-Modell laden.
Schauen wir uns zunächst die Parameterkonfiguration dieser Funktion an:
- model ([`transformers.PreTrainedModel`]):
Das zu verpackende Modell.
- peft_config ([`PeftConfig`]):
Konfigurationsobjekt, das die Parameter des Peft-Modells enthält.
- adapter_name (`str`, `optional`, defaults to `"default"`):
Der Name des Adapters, der injiziert werden soll. Wenn er nicht angegeben wird, wird der Standardadaptername verwendet („default").
- mixed (`bool`, `optional`, defaults to `False`):
Je nachdem, ob das Mischen verschiedener (kompatibler) Adaptertypen erlaubt werden soll.
- autocast_adapter_dtype (`bool`, *optional*):
Ob der Adapter dtype automatisch übertragen werden soll. Der Standardwert ist „True“. Im Moment werden nur Adaptergewichte, die float16 oder bfloat16 verwenden, in float32 umgewandelt, da dies typischerweise für ein stabiles Training erforderlich ist und nur ausgewählte PEFT-Tuner betrifft.
- revision (`str`, `optional`, defaults to `main`):
Die Überarbeitung des Basismodells. Wenn dies nicht eingestellt ist, wird das gespeicherte Postmodell die „Haupt"-Revision für das Basismodell laden.
In diesem Beispiel werden nur die Parameter model und peft_config verwendet, die anderen Parameter bleiben als Standardwerte erhalten. Das Modell wird verwendet, um das GPT-2-Modell zu übergeben, und peft_config wird verwendet, um unsere LoraConfig-Konfiguration zu empfangen.
model = get_peft_model(model, peft_config)
3. Die Klasse PeftModel
Die Klasse PeftModel ist die Basisklasse der Peft-Bibliothek. Sie kann jeden von dieser Bibliothek unterstützten Modelltyp initialisieren. Wir müssen die Klasse PeftModel verwenden, um die während der Feinabstimmung gespeicherten LoRA-Parameter und die ursprünglichen, von GPT-2 trainierten Modellparameter nach Abschluss des Trainings in ein Modell zu laden und dann das geladene Modell für Inferenztests zu verwenden. Schauen wir uns zunächst die Parameterkonfiguration dieser Klasse an.
- Modell ([~transformers.PreTrainedModel`]): Das Basistransformermodell, das für Peft.
- peft_config ([`PeftConfig`]): Die Konfiguration des Peft-Modells.
- adapter_name (`str`, *optional*): Der Name des Adapters, Standardwert ist „default“.
- autocast_adapter_dtype (`bool`, *optional*):
Ob der Adapter dtype automatisch übertragen werden soll. Der Standardwert ist „True“. Im Moment werden nur Adaptergewichte, die float16 und bfloat16 verwenden, in float32 umgewandelt, da dies typischerweise für ein stabiles Training erforderlich ist und nur ausgewählte PEFT-Tuner betrifft.
- low_cpu_mem_usage (`bool`, `optional`, defaults to `False`):
Leere Adaptergewichte auf dem Meta-Gerät erstellen. Nützlich zur Beschleunigung des Ladevorgangs.
- Attribute:
- base_model ([`torch.nn.Module`]) -- Das für Peft verwendete Basis-Transformermodell.
- peft_config ([`PeftConfig`]) -- Die Konfiguration des Peft-Modells.
- modules_to_save (`list` of `str`) -- Die Liste der Namen von Untermodulen, die beim Speichern des Modells gespeichert werden sollen.
- prompt_encoder ([`PromptEncoder`]) -- Der für Peft verwendete Prompt-Encoder, wenn [`PromptLearningConfig`] verwendet wird.
- prompt_tokens (`torch.Tensor`) -- Die virtuellen Prompt-Token, die für Peft verwendet werden, wenn [`PromptLearningConfig`] verwendet wird.
- transformer_backbone_name (`str`) -- Der Name des Transformer-Backbones im Basismodell, wenn [`PromptLearningConfig`] verwendet wird.
- word_embeddings (`torch.nn.Embedding`) -- Die Worteinbettungen des Transformer-Backbones im Basismodell, wenn [`PromptLearningConfig`] verwendet wird.
Bei Verwendung der Klasse PeftModel wird das Modell direkt über die Klassenmethode PeftModel.from_pretrained(model, peft_model_id) geladen. Das Modell ist unser GPT-2-Modell, und peft_model_id sind die Parameter des LoRA-Modells, die wir feinabgestimmt haben.
model = PeftModel.from_pretrained(model, peft_model_id)
Anmerkung:
Verwenden Sie nicht `low_cpu_mem_usage=True`, wenn Sie einen neuen PEFT-Adapter für das Training erstellen.
LoRA-Tuning
Nach der Einführung in die Konfiguration des LoRA-Tunings mit Hilfe der Bibliothek `peft' wollen wir unser Codebeispiel vervollständigen.
1. Erforderliche Bibliotheken importieren
Hier gibt es nichts Besonderes zu beachten; wir importieren direkt die Bibliotheken, die wir in der Python-Umgebung benötigen:
import pandas as pd from transformers import GPT2LMHeadModel, GPT2Tokenizer from transformers import TextDataset, DataCollatorForLanguageModeling from transformers import Trainer, TrainingArguments import torch from peft import get_peft_model, LoraConfig, PeftModel
2. Laden der Daten und Konfiguration des Modells
Zunächst prüfen wir, ob die GPU-Beschleunigung in der aktuellen Codeumgebung verfügbar ist, um sicherzustellen, dass unsere Umgebungskonfiguration korrekt ist. Wenn Sie eine GPU zur Verfügung haben, diese aber nicht genutzt wird, sollten Sie die Konfiguration Ihrer Codeumgebung überprüfen. Die CPU kann die Aufgabe zwar erledigen, aber sie ist sehr langsam.
dvc = 'cuda' if torch.cuda.is_available() else 'cpu' print(dvc)
Als Nächstes konfigurieren wir die LoRA-Tuning-Parameter. Diese Parameter wurden bereits eingeführt, sodass wir sie direkt verwenden werden:
model_name_or_path = 'gpt2' peft_config = LoraConfig( lora_alpha=32, lora_dropout=0.1 )
„model_name_or_path“ ist unser vortrainiertes Modell. Als Nächstes legen wir den Pfad zum Speichern des fein abgestimmten LoRA-Modells „peft_model_id“ fest:
peft_model_id = f"{model_name_or_path}_{peft_config.peft_type}_{peft_config.task_type}"
Laden wir nun die Datei „llm_data.csv". Wir werden die letzten 20 Schlusskurse dieses Datensatzes als Eingabe verwenden und die Ergebnisse des Modells mit den übrigen Schlusskursen vergleichen, um die Leistung des Modells zu überprüfen.
df = pd.read_csv('llm_data.csv')
Als Nächstes müssen wir die vorverarbeiteten Daten „train.txt“ laden (wir haben den Teil des Codes, der „llm_data.csv“ in „train.txt“ konvertiert, entfernt, da wir die Daten bereits im vorherigen Artikel konvertiert haben, sodass es nicht notwendig ist, sie erneut zu konvertieren). Definieren wir den Tokenizer, „train_dataset“ und „data_collator". Dieser Teil ist derselbe wie in unserem vorherigen Artikel, sodass wir hier nicht ins Detail gehen werden. Interessierte Leser können sich auf den vorherigen Artikel beziehen.
tokenizer = GPT2Tokenizer.from_pretrained(model_name_or_path) train_dataset = TextDataset(tokenizer=tokenizer, file_path="train.txt", block_size=60) data_collator = DataCollatorForLanguageModeling(tokenizer=tokenizer, mlm=False)
Wir müssen auch „TrainingArguments“ instanziieren. Hier haben wir die Parameter „save_steps“ und „save_total_limit“ entfernt. Diese Parameter verwalten hauptsächlich die Speicherung von Kontrollpunkten während des Trainings, aber für das LoRA-Tuning müssen wir nur die LoRA-Parameter speichern, nicht alle Parameter. Um Konflikte zu vermeiden, haben wir diese beiden Parameter entfernt und den Parameter save_strategy='no' hinzugefügt und die Methode „save_model“ in der Klasse „Trainer“ zum Speichern des Modells verwendet.
training_args = TrainingArguments( output_dir=peft_model_id, overwrite_output_dir=True, num_train_epochs=3, per_device_train_batch_size=32, save_strategy='no' )
3. Laden und Feinabstimmung des Modells
Zuerst laden wir das vortrainierte GPT-2-Modell als „HeadModel":
model = GPT2LMHeadModel.from_pretrained(model_name_or_path)
Dann müssen wir die konfigurierten LoRA-Einstellungen mit dem vortrainierten GPT-2-Modell zusammenführen. Dieser Prozess, der recht komplex war, erfordert jetzt nur noch eine Zeile Code unter Verwendung der Funktion „get_peft_model()“ aus der Bibliothek „peft“. Diese Bibliothek hat uns viel Komfort gebracht.
model = get_peft_model(model, peft_config)
Als Nächstes instanziieren wir den „Trainer", führen die Feinabstimmung des Trainings durch und speichern das Modell. Dieser Teil unterscheidet sich nicht vom Code im vorigen Artikel, sodass wir ihn nicht im Detail besprechen werden. Interessierte Leser können sich auf den vorherigen Artikel beziehen.
trainer = Trainer( model=model, args=training_args, data_collator=data_collator, train_dataset=train_dataset ) trainer.train() trainer.save_model(peft_model_id)
Dabei ist zu beachten, dass das mit „trainer.save_model(peft_model_id)“ gespeicherte Modell nicht mehr das vollständige Modell ist, sondern nur noch die LoRA-Gewichte enthält. Während der LoRA-Abstimmung werden die vortrainierten Gewichte des GPT-2 eingefroren und nur die LoRA-Gewichte feinabgestimmt. Daher müssen Sie beim Laden des fein abgestimmten Modells die Methode „from_pretrained()“ in der Klasse „PeftModel“ verwenden, um diese beiden Teile der Gewichte zusammen neu zu laden, damit das Modell korrekt funktioniert. Sie können nicht mehr „GPT2LMHeadModel.from_pretrained()“ zum Laden des Modells verwenden.
Nach der Feinabstimmung wird das Modell im Ordner „gpt2_LORA_None“ unter dem Verzeichnis gespeichert, in dem sich das Trainingsskript befindet (da wir den Parameter „task_type“ in der Klasse „LoraConfig“ nicht gesetzt haben, steht diese Option standardmäßig auf „None“, weshalb der Ordner mit „None“ endet).
4. Testen des Feinabstimmungsmodells
Nach der Feinabstimmung müssen wir das feinabgestimmte Modell laden und eine Inferenz durchführen, um zu prüfen, ob das feinabgestimmte Modell korrekt funktioniert. Wie bereits erwähnt, unterstützt das mit LoRA feinabgestimmte Modell das Laden mit „GPT2LMHeadModel.from_pretrained()“ nicht und muss die Methode „from_pretrained()“ in der Klasse „PeftModel“ verwenden, um das vortrainierte GPT-2-Modell und die LoRA-Gewichte zusammen zu laden. Die Parameter der Methode „PeftModel.from_pretrained()“ wurden bereits früher eingeführt, sodass wir sie hier nicht weiter erläutern werden. Nach dem Laden des Modells müssen wir es auf GPU-Beschleunigung einstellen und das Modell in den Inferenzmodus schalten.
model = GPT2LMHeadModel.from_pretrained(model_name_or_path) model = PeftModel.from_pretrained(model, peft_model_id) model.to(dvc) model.eval()
Als Nächstes folgt der Inferenztest, um festzustellen, ob das Modell korrekt funktioniert. Dieser Vorgang ist derselbe wie im vorherigen Artikel. Ausführliche Informationen zur Interpretation des Codes finden Sie in einem früheren Artikel. Wir werden das hier nicht diskutieren.
prompt = ' '.join(map(str, df.iloc[:, 1:20].values[-1])) generated = tokenizer.decode(model.generate(tokenizer.encode(prompt, return_tensors='pt').to(dvc), do_sample=True, max_length=200)[0], skip_special_tokens=True) print(f"test the model: {generated}")
Das Ergebnis sieht wie folgt aus:
Modelltest: 0.61163 0.61162 0.61191 0.61195 0.61209 0.61231 0.61224 0.61207 0.61187 0.61184
0.6119 0.61169 0.61168 0.61162 0.61181 0.61184 0.61184 0.6118 0.61176 0.61174 0.61175 0.61169
0.6119 0.61174 0.6116 0.61144 0.61155 0.61207 0.61192 0.61203 0.61158 0.61202 0.61158 0.61156
0.61146 0.61196 0.61144 0.656 0.61142 0.61141 0.61137 0.60952 0.611
Das vollständige Skript für die Feinabstimmung ist „lora-tuning.py“.
import pandas as pd from transformers import GPT2LMHeadModel, GPT2Tokenizer from transformers import TextDataset, DataCollatorForLanguageModeling from transformers import Trainer, TrainingArguments import torch from peft import get_peft_model, LoraConfig, PeftModel dvc='cuda' if torch.cuda.is_available() else 'cpu' print(dvc) model_name_or_path='gpt2' peft_config = LoraConfig( # task_type=None, # inference_mode=False, # r=8, lora_alpha=32, lora_dropout=0.1, ) peft_model_id = f"{model_name_or_path}_{peft_config.peft_type}_{peft_config.task_type}" df = pd.read_csv('llm_data.csv') # sentences = [' '.join(map(str, prices)) for prices in df.iloc[:-10,1:].values] # with open('train.txt', 'w') as f: # for sentence in sentences: # f.write(sentence + '\n') tokenizer = GPT2Tokenizer.from_pretrained(model_name_or_path) train_dataset = TextDataset(tokenizer=tokenizer, file_path="train.txt", block_size=60) data_collator = DataCollatorForLanguageModeling(tokenizer=tokenizer, mlm=False) training_args = TrainingArguments(output_dir=peft_model_id, overwrite_output_dir=True, num_train_epochs=3, per_device_train_batch_size=32, save_strategy= 'no', # save_steps=10_000, # save_total_limit=2, # load_best_model_at_end=True, ) model = GPT2LMHeadModel.from_pretrained(model_name_or_path) model = get_peft_model(model, peft_config) trainer = Trainer(model=model, args=training_args, data_collator=data_collator, train_dataset=train_dataset,) trainer.train() # model.save_pretrained(peft_model_id) trainer.save_model(peft_model_id) # config = PeftConfig.from_pretrained(peft_model_id) model = GPT2LMHeadModel.from_pretrained(model_name_or_path) model = PeftModel.from_pretrained(model, peft_model_id) model.to(dvc) model.eval() prompt = ' '.join(map(str, df.iloc[:,1:20].values[-1])) generated = tokenizer.decode(model.generate(tokenizer.encode(prompt, return_tensors='pt').to(dvc), do_sample=True, max_length=200)[0], skip_special_tokens=True) print(f"test the model:{generated}")
Die Datendateien werden am Ende angehängt, wobei die Originaldatendatei „llm_data.csv“ und die vorverarbeitete Datendatei „train.txt“ ist.
Vergleich verschiedener Feinsteuerungsmethoden
Nach dem Experimentieren mit verschiedenen Feinabstimmungsmethoden haben wir neue GPT-2-Modelle mit unterschiedlichen Leistungen erhalten. Dies erfordert einen Vergleich der Ergebnisse und der Trainingsgeschwindigkeiten verschiedener Methoden, um die am besten geeignete Methode für unsere EA-Strategie wissenschaftlich auszuwählen. Da das vortrainierte GPT-2-Modell unsere Eingabe nicht erkennen kann, brauchen wir das vortrainierte Modell nicht in die Vergleichssequenz aufzunehmen. Daher führen wir die Vollparameter-Feinabstimmung und die LoRA-Abstimmung nur zum Vergleich ein. Natürlich werde ich in den folgenden Artikeln weiterhin verschiedene Methoden vorstellen, sodass wir mehr Auswahlmöglichkeiten haben werden.
1. Effizienzvergleich
Zunächst müssen wir die Kosten des Trainings vergleichen. Wir bevorzugen Methoden mit hoher Trainingseffizienz und geringen Kosten. Hier vergleichen wir die Trainingszeit, den Speicherverbrauch und die Inferenzgeschwindigkeit. Obwohl die Unterschiede bei einem Modell mit kleinen Parametern wie GPT-2 nicht signifikant sein mögen, werden sie bei der Wahl größerer Modelle (z. B. 7B, 13B, 34B oder größer) sehr deutlich.
Train_runtime(s) | VRAM(GB) | Generate_runtime(s) | |
---|---|---|---|
LoRA-Tuning Prozess | 69.5605 | 4.1 | 1.242877 |
Vollparametrischer Feinabstimmungsprozess | 101.7946 | 5.67 | 0.876525 |
2. Genauigkeitsvergleich
In Bezug auf die Genauigkeit vergleichen wir vorübergehend die Modelle, die durch verschiedene Feinabstimmungsmethoden erhalten wurden, anhand von MSE (mittlerer quadratischer Fehler), RMSE (Wurzel des mittleren quadratischen Fehlers) und NRMSE (normalisierte Wurzel des mittleren quadratischen Fehlers). Andere Metriken (wie Komplexität, Robustheit usw.) werden vorerst nicht berücksichtigt.
Als Nächstes laden wir die Schlusskurse der letzten 20 Zeilen der Originaldaten als Eingabe und verwenden die verbleibenden Daten als Ergebnis, um die mit den beiden Trainingsmethoden erhaltenen Modelle zu bewerten.
- Eingabedaten: [0.61163, 0.61162, 0.61191, 0.61195, 0.61209, 0.61231, 0.61224, 0.61207, 0.61187, 0.61184, 0.6119, 0.61169, 0.61168, 0.61162, 0.61181, 0.61184, 0.61184, 0.6118, 0.61176]
- Wahre Preise: [0.6119, 0.61197, 0.61201, 0.61242, 0.61237, 0.6123, 0.61229, 0.61242, 0.61212, 0.61197, 0.61201, 0.61213, 0.61212, 0.61206, 0.61203, 0.61206, 0.6119, 0.61193, 0.61191, 0.61202, 0.61197, 0.6121, 0.61211, 0.61214, 0.61203, 0.61203, 0.61213, 0.61218, 0.61227, 0.61226]
Als Nächstes werden die Modelle geladen (das feinabgestimmte Modell mit allen Parametern wird im Ordner gpt2_stock im aktuellen Verzeichnis gespeichert, das feinabgestimmte LoRA-Modell wird im Ordner gpt2_LORA_None im aktuellen Verzeichnis gespeichert) und die Inferenz ausgeführt. Anhand der Ergebnisse berechnen wir ihren MSE, RMSE und NRMSE. Diese Codes wurden bereits im vorigen Artikel vorgestellt, sodass sie hier nicht näher beschrieben werden.
import time import pandas as pd from transformers import GPT2LMHeadModel, GPT2Tokenizer, GPT2Config from sklearn.metrics import mean_squared_error import torch import numpy as np from peft import PeftModel import matplotlib.pyplot as plt # Load dataset df = pd.read_csv('llm_data.csv') # Set device (GPU or CPU) dvc = 'cuda' if torch.cuda.is_available() else 'cpu' # Define model paths base_model = 'gpt2' fine_tuning_path = './gpt2_stock' lora_tuning_path = './gpt2_LORA_None' # Initialize tokenizer and models tokenizer = GPT2Tokenizer.from_pretrained(base_model) model_fine_tuning = GPT2LMHeadModel.from_pretrained(fine_tuning_path).to(dvc) model_lora_tuning = GPT2LMHeadModel.from_pretrained(base_model) model_lora_tuning = PeftModel.from_pretrained(model_lora_tuning, lora_tuning_path).to(dvc) # Extract input data and true prices input_data = df.iloc[:, 1:20].values[-1] true_prices = df.iloc[-1:, 21:].values.tolist()[0] # Prepare prompt prompt = ' '.join(map(str, input_data))
Wir kapseln den Prozess der Inferenz und der Berechnung von MSE, RMSE und NRMSE in einer Funktion „generater(model)“ und verwenden den vorhergesagten Wert, MSE, RMSE und NRMSE als Rückgabewerte. Wenn wir verschiedene Modelle für die Inferenzauswertung verwenden, geben wir das Modell einfach als Parameter an. An dieser Stelle sei darauf hingewiesen, dass die in unserer Funktion verwendete Variable true_prices eine globale Variable ist und wir ihren Wert in der Funktion ändern müssen. Daher sollten wir sie in der Funktion als globale Variable deklarieren, da sonst ein Fehler gemeldet wird.
def generater(model): global true_prices # Set the model to evaluation mode model.eval() # Tokenization and text generation using the model token = tokenizer.encode(prompt, return_tensors='pt').to(dvc) start_ = time.time() generated = tokenizer.decode( model.generate(token, do_sample=True, max_length=200)[0], skip_special_tokens=True ) end_ = time.time() print(f'Generate time: {end_ - start_} seconds') # Process the generated data generated_prices = generated.split('\n')[0] generated_prices = list(map(float, generated_prices.split())) generated_prices = generated_prices[:len(true_prices)] # Function to trim both lists to the same length def trim_lists(a, b): min_len = min(len(a), len(b)) return a[:min_len], b[:min_len] # Trim the true_prices and generated_prices lists true_prices, generated_prices = trim_lists(true_prices, generated_prices) print(f"Input data: {input_data}") print(f"True prices: {true_prices}") print(f"Generated prices: {generated_prices}") # Calculate MSE, RMSE, NRMSE metrics mse = mean_squared_error(true_prices, generated_prices) print('MSE:', mse) rmse = np.sqrt(mse) nrmse = rmse / (np.max(true_prices) - np.min(generated_prices)) print(f"RMSE: {rmse}, NRMSE: {nrmse}") return generated_prices, mse, rmse, nrmse def generater(model): global true_prices # Set the model to evaluation mode model.eval() # Tokenization and text generation using the model token = tokenizer.encode(prompt, return_tensors='pt').to(dvc) start_ = time.time() generated = tokenizer.decode( model.generate(token, do_sample=True, max_length=200)[0], skip_special_tokens=True ) end_ = time.time() print(f'Generate time: {end_ - start_} seconds') # Process the generated data generated_prices = generated.split('\n')[0] generated_prices = list(map(float, generated_prices.split())) generated_prices = generated_prices[:len(true_prices)] # Function to trim both lists to the same length def trim_lists(a, b): min_len = min(len(a), len(b)) return a[:min_len], b[:min_len] # Trim the true_prices and generated_prices lists true_prices, generated_prices = trim_lists(true_prices, generated_prices) print(f"Input data: {input_data}") print(f"True prices: {true_prices}") print(f"Generated prices: {generated_prices}") # Calculate MSE, RMSE, NRMSE metrics mse = mean_squared_error(true_prices, generated_prices) print('MSE:', mse) rmse = np.sqrt(mse) nrmse = rmse / (np.max(true_prices) - np.min(generated_prices)) print(f"RMSE: {rmse}, NRMSE: {nrmse}") return generated_prices, mse, rmse, nrmse
Wir kapseln die Visualisierung des Inferenzergebnisses in eine Funktion „plot_(a, b, title)“:
def plot_(a, b, title): # Set up the figure size plt.figure(figsize=(10, 6)) # Plot true_prices only if the title is 'prediction' if title == 'prediction': plt.plot(true_prices, label='True Values', marker='o') # Plot the fine-tuning and lora-tuning values plt.plot(a, label='fine_tuning', marker='x') plt.plot(b, label='lora_tuning', marker='s') # Set the title and labels for the axes plt.title(title) plt.xlabel('Index') plt.ylabel('Value') # Display the legend and save the plot to a file plt.legend() plt.savefig(f"{title}.png")
Kapseln wir die Effizienz des Modells und die bereits erwähnten Bewertungsmetriken in einer Funktion „groups_chart(a, b, models)“:
def groups_chart(a, b, models): # Define metrics for the chart metrics = ['Train Time(s)', 'Inference Time (s)', 'Memory Usage (GB)', 'MSE', 'RMSE', 'NRMSE'] # Set figure size plt.figure(figsize=(10, 6)) # Update values for model a and b a = [101.7946, 1.243, 5.67, a[1], a[2], a[3]] b = [69.5605, 0.877, 4.10, b[1], b[2], b[3]] # Bar width for each group of bars bar_width = 0.2 # Set the positions of the bars r1 = np.arange(len(metrics)) # Positions for model a r2 = [x + bar_width for x in r1] # Positions for model b # Plot bars for both models plt.bar(r1, a, color='r', width=bar_width, edgecolor='grey', label=models[0]) plt.bar(r2, b, color='b', width=bar_width, edgecolor='grey', label=models[1]) # Set log scale for y-axis plt.yscale('log') # Set labels and title plt.xlabel('Metrics', fontweight='bold') plt.xticks([r + bar_width / 2 for r in range(len(metrics))], metrics) # Center the x-axis ticks plt.ylabel('Values (log scale)', fontweight='bold') plt.title('Model Comparison') # Display legend and save the plot plt.legend() # plt.show() # Uncomment to display the plot plt.savefig('Comparison.png')
Anmerkung:
Das Problem dabei ist, dass die Größenordnung der von uns gemessenen Metriken nicht die gleiche ist, daher verwende ich hier eine logarithmische Skala :plt.yscale('log'). Auf diese Weise ist es möglich, Situationen, in denen die Datenmenge stark schwankt, effektiv zu bewältigen.
Verschiedene Modelle führen die Inferenz separat durch:
fine_tuning_result = generater(model_fine_tuning) lora_tuning_result = generater(model_lora_tuning)
Die Ergebnisse der Inferenz des Vollparameter-Feinabstimmungsmodells:
- generierte Preise:[0.61163, 0.61162, 0.61191, 0.61195, 0.61209, 0.61231, 0.61224, 0.61207, 0.61187, 0.61184, 0.6119, 0.61169, 0.61168, 0.61162, 0.61181, 0.61184, 0.61184, 0.6118, 0.61176, 0.61183, 0.61185, 0.61217, 0.61221, 0.61223, 0.61226, 0.61231, 0.61231, 0.61229, 0.61235, 0.61237, 0.61241, 0.61243, 0.61248, 0.61253, 0.61263, 0.61265, 0.61267, 0.61271, 0.61267, 0.61272]
- MSE: 1.0064750000000609e-07
- RMSE:0.0003172499014972362
- NRMSE:0.3965623768715889
Ergebnisse der LoRA-Tuning-Modell-Inferenz:
- generierte Preise:[0.61163, 0.61162, 0.61191, 0.61195, 0.61209, 0.61231, 0.61224, 0.61207, 0.61187, 0.61184, 0.6119, 0.61169, 0.61168, 0.61162, 0.61181, 0.61184, 0.61184, 0.6118, 0.61176, 0.6116, 0.6116, 0.61194, 0.6118, 0.61195, 0.61197, 0.61196, 0.6123, 0.61181, 0.61172, 0.6119, 0.61155, 0.61149, 0.61197, 0.61198, 0.61192, 0.61136, 0.61092, 0.61091, 0.61098, 0.61099]
- MSE: 2.3278249999999242e-07
- RMSE:0.00048247538797330626
- NRMSE:0.3195201244856309
Die Ergebnisse visualisieren und als Bilder speichern:
plot_(fine_tuning_result[0],lora_tuning_result[0],title='predication') groups_chart(fine_tuning_result,lora_tuning_result,models=['fine-tuning','lora-tuning'])
Chart-Visualisierung zum Vergleich:
Anmerkung:
Ich habe das Skript viele Male zu Testzwecken ausgeführt, und die Ergebnisse sind bei jedem Durchlauf anders. Die von mir angegebenen Daten und Charts dienen also nur als Referenz, und es ist normal, dass Ihre Ergebnisse von meinen abweichen.
3. Die Wahl des richtigen Modells
Unter dem Gesichtspunkt der Effizienz ist es klar, dass die LoRA-Feinabstimmung im Vergleich zur Feinabstimmung mit allen Parametern in Bezug auf die Trainingsgeschwindigkeit, die Inferenzgeschwindigkeit und die Speichernutzung überlegen ist. Als Nächstes vergleichen wir die Genauigkeit der Schlussfolgerungen. Aus unseren Charts geht intuitiv hervor, dass die Ergebnisse der beiden Modelle bei den ersten 18 vorhergesagten Werten fast gleich sind, während der Fehler bei den übrigen Werten allmählich zunimmt. Die Vorhersagen des feinabgestimmten Modells mit allen Parametern sind insgesamt relativ stabil, wie die NRMSE-Werte zeigen.
Ich habe versucht, das Skript test.py mehrere Male auszuführen, um zu sehen, ob die Ergebnisse konsistent sind. Die Ergebnisse variierten, wobei der NRMSE des feinabgestimmten LoRA-Modells manchmal klein war (etwa 0,17, viel niedriger als der NRMSE des feinabgestimmten Modells mit vollständigen Parametern) und manchmal riesig (bis zu 0,76688). Der fein abgestimmte NRMSE für alle Parameter blieb stabil bei 0,4. Es ist wichtig anzumerken, dass diese Daten nicht notwendigerweise bedeuten, dass das feinabgestimmte Modell mit vollständigen Parametern besser abschneidet als das feinabgestimmte LoRA-Modell. Es ist möglich, dass das LoRA-Tuning nicht mit den gleichen Trainingseinstellungen konvergiert wie das Full-Parameter-Feintuning. Eine bessere Lösung ist die Konfiguration einer geeigneten Logik zum frühzeitigen Stoppen auf der Grundlage des Verlusts während des Trainings, um die Konvergenz des Modells sicherzustellen. Dieser Teil des Inhalts wird im Codebeispiel vorerst nicht bereitgestellt, aber interessierte Leser können ihn selbst implementieren.
Natürlich können sich auch unterschiedliche Einstellungen der Modellparameter auf die Leistung des Modells auswirken. Daher sollte ein wissenschaftlicherer Ansatz darin bestehen, zunächst die optimalen Parametereinstellungen für ein Modell oder eine Trainingsmethode auf demselben Datensatz zu finden und sicherzustellen, dass das Modell unter den optimalen Einstellungen konvergiert. Führen Sie dann einen horizontalen Vergleich verschiedener Trainingsmethoden oder -modelle durch, bewerten Sie verschiedene Metriken umfassend und wählen Sie die optimale Trainingsmethode oder das optimale Modell aus.
Das vollständige Testcode-Skript ist „test.py“:
import time import pandas as pd from transformers import GPT2LMHeadModel, GPT2Tokenizer, GPT2Config from sklearn.metrics import mean_squared_error import torch import numpy as np from peft import PeftModel import matplotlib.pyplot as plt # Load the dataset df = pd.read_csv('llm_data.csv') # Define the device (GPU if available) dvc = 'cuda' if torch.cuda.is_available() else 'cpu' # Model paths and base settings base_model = 'gpt2' fine_tuning_path = './gpt2_stock' lora_tuning_path = './gpt2_LORA_None' # Load the tokenizer and models tokenizer = GPT2Tokenizer.from_pretrained(base_model) model_fine_tuning = GPT2LMHeadModel.from_pretrained(fine_tuning_path).to(dvc) model_lora_tuning = GPT2LMHeadModel.from_pretrained(base_model) model_lora_tuning = PeftModel.from_pretrained(model_lora_tuning, lora_tuning_path).to(dvc) # Extract the input data and true prices from the dataset input_data = df.iloc[:, 1:20].values[-1] true_prices = df.iloc[-1:, 21:].values.tolist()[0] prompt = ' '.join(map(str, input_data)) # Function to generate predictions def generater(model): global true_prices model.eval() # Tokenization and text generation token = tokenizer.encode(prompt, return_tensors='pt').to(dvc) start_ = time.time() generated = tokenizer.decode( model.generate(token, do_sample=True, max_length=200)[0], skip_special_tokens=True ) end_ = time.time() print(f'Generate time: {end_ - start_}') # Processing generated prices generated_prices = generated.split('\n')[0] generated_prices = list(map(float, generated_prices.split())) generated_prices = generated_prices[:len(true_prices)] # Function to trim lists to the same length def trim_lists(a, b): min_len = min(len(a), len(b)) return a[:min_len], b[:min_len] # Trim the true prices and generated prices true_prices, generated_prices = trim_lists(true_prices, generated_prices) # Output metrics print(f"Input data: {input_data}") print(f"True prices: {true_prices}") print(f"Generated prices: {generated_prices}") mse = mean_squared_error(true_prices, generated_prices) print('MSE:', mse) rmse = np.sqrt(mse) nrmse = rmse / (np.max(true_prices) - np.min(generated_prices)) print(f"RMSE: {rmse}, NRMSE: {nrmse}") return generated_prices, mse, rmse, nrmse # Function to plot the comparison between true prices and predictions def plot_(a, b, title): plt.figure(figsize=(10, 6)) if title == 'prediction': plt.plot(true_prices, label='True Values', marker='o') plt.plot(a, label='fine_tuning', marker='x') plt.plot(b, label='lora_tuning', marker='s') plt.title(title) plt.xlabel('Index') plt.ylabel('Value') plt.legend() plt.savefig(f"{title}.png") # Function to generate a bar chart comparing different metrics between models def groups_chart(a, b, models): metrics = ['Train Time(s)', 'Inference Time (s)', 'Memory Usage (GB)', 'MSE', 'RMSE', 'NRMSE'] plt.figure(figsize=(10, 6)) # Data for the metrics a = [101.7946, 1.243, 5.67, a[1], a[2], a[3]] b = [69.5605, 0.877, 4.10, b[1], b[2], b[3]] bar_width = 0.2 r1 = np.arange(len(metrics)) r2 = [x + bar_width for x in r1] # Plotting bars for both models plt.bar(r1, a, color='r', width=bar_width, edgecolor='grey', label=models[0]) plt.bar(r2, b, color='b', width=bar_width, edgecolor='grey', label=models[1]) # Set y-axis to log scale for better visibility of differences plt.yscale('log') plt.xlabel('Metrics', fontweight='bold') plt.xticks([r + bar_width for r in range(len(metrics))], metrics) plt.ylabel('Values (log scale)', fontweight='bold') plt.title('Model Comparison') plt.legend() plt.savefig('Comparison.png') # Generate results for both fine-tuned and LORA-tuned models fine_tuning_result = generater(model_fine_tuning) lora_tuning_result = generater(model_lora_tuning) # Plot the prediction comparison plot_(fine_tuning_result[0], lora_tuning_result[0], title='prediction') # Generate the comparison chart for the models groups_chart(fine_tuning_result, lora_tuning_result, models=['fine-tuning', 'lora-tuning'])
Schlussfolgerung
In diesem Artikel haben wir erörtert, wie das vortrainierte GPT-2-Modell mit Hilfe der LoRA-Tuning-Methode feinabgestimmt werden kann, und die vorgestellten Feinabstimmungsmethoden verglichen. So können wir intuitiv die Trainingsmethode und das Modell wählen, das am besten zu unserer Handelsstrategie passt. Natürlich werden wir weiterhin weitere Feinabstimmungsmethoden diskutieren und diese Methoden zur Feinabstimmung des vortrainierten GPT-2-Modells verwenden, um genauere Feinabstimmungsmethoden für unsere Handelsstrategie zu finden. In Anbetracht der Parameterskala des vortrainierten GPT-2-Modells kann das Endergebnis erheblich vom idealen Ergebnis abweichen, aber der Prozess der Suche nach dem Endergebnis ist derselbe. Sie fragen sich vielleicht, warum nicht horizontale Vergleiche zwischen verschiedenen Modellen? Das ist eine gute Frage, aber es gibt so viele Modelle, aus denen man wählen kann, und selbst ein und dasselbe Modell kann unterschiedliche Parameterskalen haben. Es ist klar, dass wir diese Aufgabe nicht mit ein paar einfachen Beispielen lösen können. Dies ist ein sehr mühsamer, aber nicht komplexer Prozess. Ich schlage daher vor, anhand der Methodenbeispiele in diesem Artikel zu untersuchen, wie man die besten Ergebnisse unter den verschiedenen Modellen finden kann.
Sind Sie bereit, weiter zu forschen? Wir sehen uns im nächsten Artikel!
Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/13499





- Freie Handelsapplikationen
- Über 8.000 Signale zum Kopieren
- Wirtschaftsnachrichten für die Lage an den Finanzmärkte
Sie stimmen der Website-Richtlinie und den Nutzungsbedingungen zu.