Îți amintești călătoria noastră de până acum? Am început cu Simple Lanțuri Markov Arătând cum funcționează predicția statistică a cuvintelor, apoi intră în conceptele de bază ale cuvântului încorporari, Auto-atențieși Predicția cuvântului următor. Acum, este timpul pentru marea finală: dacă doriți să vă construiți propria lucrare transformator Model de limbă în R, citiți mai departe!
Vei spune, în niciun caz!?! Dar da, potrivit mantrei că ați înțeles doar ce v-ați construit de la zero, vom crea un mini-chatgpt care învață să scrie ca „Alice în Țara Minunilor” și „Vrăjitorul din Oz”!
Sosul secret: adunându -l pe toate
Ce am învățat până acum:
- Rețele neuronale Construiți o reprezentare a lumii pe baza datelor lor de formare
- Lanțuri Markov ne -a arătat că generarea de text se referă fundamental la prezicerea următorului cuvânt
- Îngrăștări de cuvinte convertiți cuvintele în vectori numerici care surprind sensul
- Auto-atenție Permite modelului să se concentreze pe cuvintele relevante atunci când face predicții
O transformator Combină toate aceste concepte într -o arhitectură puternică. Gândiți -vă la el ca la un lanț sofisticat Markov care nu se uită doar la câteva cuvinte anterioare, ci poate participa la orice cuvânt în întregul context, înțelegând relațiile și modelele pe întregul text!
De la teorie la practică: implementarea R
Să construim un transformator complet pas cu pas, folosind același fișier alice_oz.txt din exemplul nostru de lanț Markov:
Pasul 1: Tokenizare la nivel de cuvânt
library(torch) # install from CRAN # Create word-level tokenizer create_tokenizer <- function(text) { text <- tolower(text) words <- unlist(strsplit(text, "\s+")) words <- words(words != "") unique_words <- sort(unique(words)) vocab <- c("", " ", unique_words) word_to_idx <- setNames(seq_along(vocab), vocab) idx_to_word <- setNames(vocab, seq_along(vocab)) list(word_to_idx = word_to_idx, idx_to_word = idx_to_word, vocab_size = length(vocab)) }
Spre deosebire de lanțul nostru Markov care a lucrat cu N-grame fixe, acest tokenizant pregătește cuvinte pentru ca transformatorul nostru să proceseze secvențe întregi.
Pasul 2: Auto-atenuarea
transformer_layer <- nn_module( initialize = function(d_model, n_heads) { self$d_model <- d_model self$n_heads <- n_heads self$d_k <- d_model %/% n_heads # The Q, K, V matrices for the attention mechanism self$w_q <- nn_linear(d_model, d_model, bias = FALSE) self$w_k <- nn_linear(d_model, d_model, bias = FALSE) self$w_v <- nn_linear(d_model, d_model, bias = FALSE) self$w_o <- nn_linear(d_model, d_model) # Feed-forward neural network self$ff <- nn_sequential( nn_linear(d_model, d_model * 4), nn_relu(), nn_linear(d_model * 4, d_model) ) self$ln1 <- nn_layer_norm(d_model) self$ln2 <- nn_layer_norm(d_model) self$dropout <- nn_dropout(0.1) }, forward = function(x, mask = NULL) { # Multi-head self-attention (exactly like our simple example, but multi-headed!) batch_size <- x$size(1) seq_len <- x$size(2) q <- self$w_q(x)$view(c(batch_size, seq_len, self$n_heads, self$d_k))$transpose(2, 3) k <- self$w_k(x)$view(c(batch_size, seq_len, self$n_heads, self$d_k))$transpose(2, 3) v <- self$w_v(x)$view(c(batch_size, seq_len, self$n_heads, self$d_k))$transpose(2, 3) # Scaled dot-product attention scores <- torch_matmul(q, k$transpose(-2, -1)) / sqrt(self$d_k) if (!is.null(mask)) { scores <- scores + mask$unsqueeze(1)$unsqueeze(1) } attn_weights <- nnf_softmax(scores, dim = -1) attn_output <- torch_matmul(attn_weights, v) # Combine heads and apply output projection attn_output <- attn_output$transpose(2, 3)$contiguous()$view(c(batch_size, seq_len, self$d_model)) attn_output <- self$w_o(attn_output) # Residual connection and layer norm x <- self$ln1(x + self$dropout(attn_output)) # Feed-forward ff_output <- self$ff(x) x <- self$ln2(x + self$dropout(ff_output)) x } )
Acesta este al nostru Mecanism de auto-atenție În acțiune! La fel ca în exemplul nostru simplu 3 × 3, dar acum funcționează cu secvențe întregi și cu mai multe capete de atenție.
Pasul 3: Modelul limbajului transformatorului
toy_llm <- nn_module( initialize = function(vocab_size, d_model = 256, n_heads = 8, n_layers = 4) { # Word embeddings (remember our love/is/wonderful example?) self$token_embedding <- nn_embedding(vocab_size, d_model) self$pos_encoding <- create_positional_encoding(512, d_model, "cpu") # Stack of transformer layers self$transformer_layer_1 <- transformer_layer(d_model, n_heads) if (n_layers >= 2) self$transformer_layer_2 <- transformer_layer(d_model, n_heads) if (n_layers >= 3) self$transformer_layer_3 <- transformer_layer(d_model, n_heads) if (n_layers >= 4) self$transformer_layer_4 <- transformer_layer(d_model, n_heads) self$n_layers <- n_layers # Output projection (back to vocabulary) self$ln_f <- nn_layer_norm(d_model) self$lm_head <- nn_linear(d_model, vocab_size) self$dropout <- nn_dropout(0.1) }, forward = function(x) { seq_len <- x$size(2) # Causal mask (no peeking at future words!) mask <- torch_triu(torch_ones(seq_len, seq_len, device = x$device), diagonal = 1) mask <- mask$masked_fill(mask == 1, -Inf) # Token embeddings + positional encoding x <- self$token_embedding(x) * sqrt(self$d_model) pos_enc <- self$pos_encoding(1:seq_len, )$to(device = x$device) x <- x + pos_enc x <- self$dropout(x) # Pass through transformer layers x <- self$transformer_layer_1(x, mask) if (self$n_layers >= 2) x <- self$transformer_layer_2(x, mask) if (self$n_layers >= 3) x <- self$transformer_layer_3(x, mask) if (self$n_layers >= 4) x <- self$transformer_layer_4(x, mask) # Final layer norm and projection to vocabulary x <- self$ln_f(x) logits <- self$lm_head(x) logits } )
Acesta este nucleul LLM, transformator. Acest rețea neuronală Arhitectura folosește toate conceptele de mai sus, cum ar fi încorporari, Atenţieși Predicția cuvântului următor!
Instruirea mini-chatgpt-ul nostru
Acum vine magia – antrenând transformatorul nostru pe Alice în Țara Minunilor și Vrăjitorul din Oz:
# Load the same text from our Markov chain example txt <- readLines(url("http://paulo-jorente.de/text/alice_oz.txt"), warn = FALSE) training_text <- paste(txt, collapse = " ") training_text <- gsub("(^a-zA-Z0-9 .,!?;:-)", "", training_text) training_text <- tolower(training_text) # Create tokenizer and model tokenizer <- create_tokenizer(training_text) model <- toy_llm(vocab_size = tokenizer$vocab_size, d_model = 256, n_heads = 8, n_layers = 4) # Train the model (this is where the magic happens!) train_model(model, training_text, tokenizer, epochs = 1500, seq_len = 32, batch_size = 4)
Rezultatele
După antrenament, mini-transformatorul nostru produce text de genul acesta:
Prompt „Alice”: Alice s -a uitat la ei și a luat în considerare puțin înainte să se micșoreze în timp și să se întindă
Prompt „Regina”: Regina a spus călăului: adu -o aici. Și călăul a plecat ca o săgeată. Capul pisicilor a început să se estompeze
Solicitați „jos”: Pe coș, și ea și -a spus acum că nu mai pot face, orice s -ar întâmpla. Ce va deveni din mine? din fericire
Comparați acest lucru cu producția noastră originală a lanțului Markov:
Anxios a întors sperietorul, este un sentiment atât de incomod să știi că unul este un cioara sau un bărbat după ce ciorile au plecat, m -am gândit asta și am decis
Transformatorul a învățat:
- Numele de personaje și relațiile (Ducesa, Turtle Mock, Gryphon, regina inimilor, sperietoare, vrăjitor)
- Contextul poveștii și scenarii (Minunea lui Alice, călătoria lui Dorothy în Oz, modelele de dialog)
- Structura adecvată de gramatică și propoziții
- Stilul capricios, narativ atât al scrisului lui Carroll, cât și al lui Baum
Avantajul transformatorului
Spre deosebire de lanțul nostru Markov care a privit doar 2-3 cuvinte anterioare, transformatorul nostru poate:
- Vezi întregul context de sute de cuvinte
- Înțelegeți dependențele de lungă durată (cum ar fi la cine se referă „ea”)
- Aflați modele complexe de gramatică și stil
- Generați narațiuni coerentenu doar predicții cuvânt cu cuvânt
De la jucărie la producție
Ceea ce am construit este în esență o versiune în miniatură a ChatGPT! Aceleași principii se extind:
- GPT-urile la nivel de industrie au până la sute de miliarde de parametri (greutăți) (Modelul nostru are 6 milioane)
- GPT -urile se antrenează pe sute de terabyți (am folosit două cărți)
- GPT -urile se antrenează adesea luni întregi pe clustere de înaltă performanță (Acesta durează mai puțin de 15 minute pe un computer standard cu un anumit GPU)
- Modelele de producție folosesc tokenizatoare sofisticate (am folosit divizarea simplă a cuvintelor)
Dar arhitectura de bază? Exact la fel!
Eficacitatea nerezonabilă a transformatoarelor
Ceea ce este cu adevărat remarcabil este faptul că această arhitectură simplă-care prezice următorul cuvânt folosind auto-atenție-dă naștere unui comportament aparent inteligent. Micuțul nostru model a învățat:
- Reguli gramaticale (fără a fi învățat gramatică)
- Relații de personaje (fără să vi se spună cine este cine)
- Structura poveștii (fără a înțelege „complotul”)
- Stil de scriere (fără lecții în literatură)
Toate din simpla sarcină de „prezice următorul cuvânt”!
Nu este fascinant faptul că atât de mult un comportament aparent inteligent iese din predicția textului statistic? După cum am văzut în postul nostru de lanț Markov, „Multe sarcini care solicită inteligență la nivel uman pot fi, evident, reduse la o formă de predicție a textului (statistică) cu un model suficient de performant!”
Pentru a vă oferi o intuiție, de ce utilizarea unei arhitecturi de rețea neuronală pentru aceasta este atât de puternică: am văzut deja că rețelele neuronale construiesc o reprezentare a lumii lor, a Model mondial (Vezi: Înțelegerea magiei rețelelor neuronale). În acest caz, imaginați -vă o poveste detectivă care se încheie cu „Și acum a fost clar, criminalul a fost…”: pentru a prezice în mod sensibil următorul (și ultimul) cuvânt pe care rețeaua neuronală trebuie să -l aibă cu adevărat înțeles Povestea într -un anumit sens!
Următorii pași: aventura continuă!
Acum v -ați construit propriul model de limbă folosind aceleași principii ca ChatGPT! În continuare, am putea experimenta:
- Texte diferite (Shakespeare? Lucrări științifice? Scrierea ta?)
- Modele mai mari (mai multe straturi, încorporari mai mari)
- Hiperparametre diferite
- Diverse strategii de generare (Temperatură, eșantionare superioară-K)
Amintiți -vă: tocmai am implementat tehnologia de bază din spatele revoluției AI. De la lanțurile Markov la mecanisme de atenție la transformatoare – ați stăpânit călătoria de la statistici simple la inteligență artificială!
Data viitoare când cineva vă întreabă „Cum funcționează Chatgpt?”, Puteți spune cu încredere: „Lasă -mă să vă arăt…” și să construiți unul de la zero (sau să arătați această postare 😉)!