Import Datenklassen

Import Datensätze

Import Fackel

Import Fackel.nn als nn

Import tqdm

@Datenklassen.Datenklasse

Klasse BertConfig:

„“„Konfiguration für BERT-Modell.“„“

vocab_size: int = 30522

num_layers: int = 12

versteckte_Größe: int = 768

Anzahl_Köpfe: int = 12

dropout_prob: schweben = 0,1

pad_id: int = 0

max_seq_len: int = 512

Anzahl_Typen: int = 2

Klasse BertBlock(nn.Modul):

„“„Ein Transformatorblock in BERT.“„“

def __init__(selbst, versteckte_Größe: int, Anzahl_Köpfe: int, dropout_prob: schweben):

tremendous().__init__()

selbst.Aufmerksamkeit = nn.MultiheadAchtung(versteckte_Größe, Anzahl_Köpfe,

ausfallen=dropout_prob, batch_first=WAHR)

selbst.attn_norm = nn.LayerNorm(versteckte_Größe)

selbst.ff_norm = nn.LayerNorm(versteckte_Größe)

selbst.ausfallen = nn.Ausfallen(dropout_prob)

selbst.Feed_Forward = nn.Sequentiell(

nn.Linear(versteckte_Größe, 4 * versteckte_Größe),

nn.GELU(),

nn.Linear(4 * versteckte_Größe, versteckte_Größe),

)

def nach vorne(selbst, X: Fackel.Tensor, pad_mask: Fackel.Tensor) -> Fackel.Tensor:

#Selbstaufmerksamkeit mit Polstermaske und Postnorm

attn_output, _ = selbst.Aufmerksamkeit(X, X, X, key_padding_mask=pad_mask)

X = selbst.attn_norm(X + attn_output)

# Feed-Ahead mit GeLU-Aktivierung und Publish-Norm

ff_output = selbst.Feed_Forward(X)

X = selbst.ff_norm(X + selbst.ausfallen(ff_output))

zurückkehren X

Klasse BertPooler(nn.Modul):

„“„Pooler-Schicht für BERT zur Verarbeitung der (CLS-)Token-Ausgabe.“„“

def __init__(selbst, versteckte_Größe: int):

tremendous().__init__()

selbst.dicht = nn.Linear(versteckte_Größe, versteckte_Größe)

selbst.Aktivierung = nn.Tanh()

def nach vorne(selbst, X: Fackel.Tensor) -> Fackel.Tensor:

X = selbst.dicht(X)

X = selbst.Aktivierung(X)

zurückkehren X

Klasse BertModel(nn.Modul):

„“„Rückgrat des BERT-Modells.“„“

def __init__(selbst, config: BertConfig):

tremendous().__init__()

# Ebenen einbetten

selbst.word_embeddings = nn.Einbetten(config.vocab_size, config.versteckte_Größe,

padding_idx=config.pad_id)

selbst.type_embeddings = nn.Einbetten(config.Anzahl_Typen, config.versteckte_Größe)

selbst.position_embeddings = nn.Einbetten(config.max_seq_len, config.versteckte_Größe)

selbst.Einbettungen_norm = nn.LayerNorm(config.versteckte_Größe)

selbst.einbettungen_dropout = nn.Ausfallen(config.dropout_prob)

# Transformatorblöcke

selbst.Blöcke = nn.Modulliste((

BertBlock(config.versteckte_Größe, config.Anzahl_Köpfe, config.dropout_prob)

für _ In Reichweite(config.num_layers)

))

# (CLS) Pooler-Schicht

selbst.pooler = BertPooler(config.versteckte_Größe)

def nach vorne(selbst, input_ids: Fackel.Tensor, token_type_ids: Fackel.Tensor, pad_id: int = 0

) -> Tupel(Fackel.Tensor, Fackel.Tensor):

# Aufmerksamkeitsmaske zum Auffüllen von Token erstellen

pad_mask = input_ids == Unterlage_Ausweis

# Ganzzahl-Token in Einbettungsvektoren umwandeln

Batch_Größe, seq_len = input_ids.Kind

position_ids = Fackel.arrangieren(seq_len, Gerät=input_ids.Gerät).ausdrücken(0)

position_embeddings = selbst.position_embeddings(position_ids)

type_embeddings = selbst.type_embeddings(token_type_ids)

token_embeddings = selbst.word_embeddings(input_ids)

X = token_embeddings + type_embeddings + Place_Einbettungen

X = selbst.Einbettungen_norm(X)

X = selbst.einbettungen_dropout(X)

# Verarbeiten Sie die Sequenz mit Transformatorblöcken

für Block In selbst.Blöcke:

X = Block(X, pad_mask)

# Poolen Sie den verborgenen Standing des „(CLS)“-Tokens

pooled_output = selbst.pooler(X(:, 0, :))

zurückkehren X, pooled_output

Klasse BertPretrainingModel(nn.Modul):

def __init__(selbst, config: BertConfig):

tremendous().__init__()

selbst.Bert = BertModel(config)

selbst.mlm_head = nn.Sequentiell(

nn.Linear(config.versteckte_Größe, config.versteckte_Größe),

nn.GELU(),

nn.LayerNorm(config.versteckte_Größe),

nn.Linear(config.versteckte_Größe, config.vocab_size),

)

selbst.nsp_head = nn.Linear(config.versteckte_Größe, 2)

def nach vorne(selbst, input_ids: Fackel.Tensor, token_type_ids: Fackel.Tensor, pad_id: int = 0

) -> Tupel(Fackel.Tensor, Fackel.Tensor):

# Verarbeiten Sie die Sequenz mit dem BERT-Modell-Spine

X, pooled_output = selbst.Bert(input_ids, token_type_ids, pad_id)

# Sagen Sie die maskierten Token für die MLM-Aufgabe und die Klassifizierung für die NSP-Aufgabe voraus

mlm_logits = selbst.mlm_head(X)

nsp_logits = selbst.nsp_head(pooled_output)

zurückkehren mlm_logits, nsp_Protokolle

# Trainingsparameter

Epochen = 10

Lernrate = 1e4

Batch_Größe = 32

# Datensatz laden und Dataloader einrichten

Datensatz = Datensätze.Datensatz.from_parquet(„wikitext-2_train_data.parquet“)

def collate_fn(Cost: Liste(dict)):

„“„Benutzerdefinierte Sortierfunktion zur Verarbeitung von Sequenzen variabler Länge im Datensatz.“„“

# immer mit maximaler Länge: tokens, segment_ids; immer Singleton: is_random_next

input_ids = Fackel.Tensor((Artikel(„Token“) für Artikel In Cost))

token_type_ids = Fackel.Tensor((Artikel(„segment_ids“) für Artikel In Cost)).Bauchmuskeln()

is_random_next = Fackel.Tensor((Artikel(„is_random_next“) für Artikel In Cost)).Zu(int)

# variable Länge: masked_positions, masked_labels

maskierte_pos = ((idx, Pos) für idx, Artikel In aufzählen(Cost) für Pos In Artikel(„maskierte_positionen“))

maskierte_labels = Fackel.Tensor((Etikett für Artikel In Cost für Etikett In Artikel(„masked_labels“)))

zurückkehren input_ids, token_type_ids, is_random_next, maskierte_pos, maskierte_labels

Datenlader = Fackel.Dienstprogramme.Daten.Datenlader(Datensatz, Batch_Größe=Batch_Größe, Shuffle=WAHR,

collate_fn=collate_fn, num_workers=8)

# Trainiere das Modell

Gerät = Fackel.Gerät(„Cuda“ Wenn Fackel.cuda.ist_verfügbar() anders „CPU“)

Modell = BertPretrainingModel(BertConfig()).Zu(Gerät)

Modell.Zug()

Optimierer = Fackel.optimum.AdamW(Modell.Parameter(), lr=Lernrate)

Planer = Fackel.optimum.lr_scheduler.StepLR(Optimierer, Schrittgröße=1, Gamma=0,1)

loss_fn = nn.CrossEntropyLoss()

für Epoche In Reichweite(Epochen):

pbar = tqdm.tqdm(Datenlader, absteigend=F„Epoche {epoch+1}/{epochs}“)

für Cost In pbar:

# Batch-Daten abrufen

input_ids, token_type_ids, is_random_next, maskierte_pos, maskierte_labels = Cost

input_ids = input_ids.Zu(Gerät)

token_type_ids = token_type_ids.Zu(Gerät)

is_random_next = is_random_next.Zu(Gerät)

maskierte_labels = maskierte_labels.Zu(Gerät)

# Ausgabe aus dem Modell extrahieren

mlm_logits, nsp_logits = Modell(input_ids, token_type_ids)

# MLM-Verlust: masked_positions ist eine Liste von Tupeln von (B, S), extrahieren Sie sie

# entsprechende Logits vom Tensor mlm_logits der Kind (B, S, V)

Batch_Indizes, token_positions = Reißverschluss(*maskierte_pos)

mlm_logits = mlm_logits(Batch_Indizes, token_positions)

mlm_loss = loss_fn(mlm_logits, maskierte_labels)

# Berechnen Sie den Verlust für die NSP-Aufgabe

nsp_loss = loss_fn(nsp_logits, is_random_next)

# rückwärts mit Totalschaden

total_loss = mlm_loss + nsp_loss

pbar.set_postfix(MLM=mlm_loss.Artikel(), NSP=nsp_loss.Artikel(), Gesamt=total_loss.Artikel())

Optimierer.null_grad()

total_loss.rückwärts()

Optimierer.Schritt()

Planer.Schritt()

pbar.aktualisieren(1)

pbar.schließen()

# Speichern Sie das Modell

Fackel.speichern(Modell.state_dict(), „bert_pretraining_model.pth“)

Fackel.speichern(Modell.Bert.state_dict(), „bert_model.pth“)

Von admin

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert