Andrej Karpathy je ime koje će mnogi ljudi u svetu AI prepoznati. Bio je profesor na Stanfordu neko vrijeme, kasnije postao je šef Teslinog odjela za AI, radio u OpenAI-u i, po mom mišljenju, on također proizvodi neke od najboljih obrazovnih videa AI dostupnih danas. Njegov najnoviji projekt, Međutim, to je nešto što mogu opisati samo kao umetničko djelo. microGPT microGPT je potpuna implementacija GPT napisana u I to nije neki pametno komprimiran ili zamagljen kod. Naprotiv, kod je čist, dobro strukturiran i temeljito komentiran. Čak izbegava upotrebu vanjskih biblioteka dubokog učenja. Drugim rečima, ne sadrži samo samu neuronsku mrežu, već i minimalni okvir potreban za obuku i upravljanje njom. only about 200 lines of Python code Zapravo, čitav projekat čak i nema punu repozitoriju – jednostavno se objavljuje kao . single GitHub Gist https://gist.github.com/karpathy/8627fe009c40f57531cb18360106ce95?embedable=true U ovom članku, pokušaću da objasnim kako ovaj prekrasan komad koda radi na način koji . anyone with basic Python knowledge can understand Počnimo s imenom . GPT GPT stoji za ChatGPT sam sadrži ovo skraćenje u svom imenu, a većina glavnih alternativa trenutno su izgrađene na istoj osnovnoj ideji. Generative Pretrained Transformer GPT model predviđa based on the previous words in a text. the next word (or token) To je u osnovi ono što svi jezični modeli rade. Oni generiraju odgovore tako što predviđaju jednu reč odjednom. Prvo, predviđaju sljedeću reč, zatim dodaju tu reč u tekst i predviđaju sljedeću, i tako dalje. Na prvi pogled, to može zvučati jednostavno, ali ako razmislimo o tome pažljivije, predviđanje sledeće reči ispravno zahtijeva određeni nivo . understanding of the text and its meaning In neural networks, this “thinking” process is implemented as a . very large mathematical function Uvodne reči se pretvaraju u brojeve i hrane u ovu funkciju, koja zatim izračunava sledeću reč. U principu, bilo koji sistem pravila može biti predstavljen matematički koristeći takve funkcije. Ova funkcija je ono što zovemo . model Problem je što ova funkcija može biti Moderne jezične modele sadrže milijarde parametara, što znači da matematička formula koja ih opisuje može imati milijarde komponenti. extremely complex Srećom, postoji pametan workaround. Umesto da sami napišemo tačnu formulu, definišemo za formulu, strukturu sa mnogim podešavanim parametrima. Ovi parametri se zatim mogu automatski podešavati dok model ne radi dobro. “template” Imamo nekoliko takvih predloška, ovisno o vrsti problema koji želimo riješiti: Konvolucijske mreže se obično koriste za obradu slike are used for general function approximation MLPs (multi-layer perceptrons) are used for language models like ChatGPT Transformers itd Ovi predlošci predstavljaju ogromne matematičke strukture koje mogu približiti složena pravila kada se njihovi parametri pravilno prilagode. Preostalo pitanje je: Ili, drugim rečima: How do we adjust these parameters? How do we “program” a neural network? Ručno podešavanje parametara neuronske mreže očigledno bi bilo nemoguće, pogotovo kada se radi o modelima koji sadrže milijune ili čak milijarde parametara. Srećom, postoji način da se to uradi automatski, koristeći podatke. , a metoda koja čini to mogućim se zove . training gradient descent Ako imamo veliki skup podataka i veliku matematičku formulu (naš model), možemo izračunati grešku modela za svaki primer u skupu podataka. U slučaju transformatora, proces radi otprilike ovako. Riječi su predstavljene kao tačke u visoko-dimenzionalnom vektorskom prostoru, gde se reči sa sličnim značenjima pojavljuju bliže jedna drugoj. Model prima sekvencu reči kao ulaz i pokušava predvidjeti sljedeću reč. Budući da su reči zastupljene kao vektori, možemo izračunati koliko je predviđena reč daleko od ispravne. A sada dolazi magija. Koristeći gradijentni pad, možemo izračunati kako bi se parametri formule trebali promijeniti kako bi se smanjila ta pogreška. Ako imamo dovoljno podataka, dovoljno veliku mrežu i dovoljno dugo je obučavamo, formula se postupno prilagođava uzorcima u skupu podataka i proizvodi sve točnije predviđanja. But how exactly does this “magic” work? How does gradient descent actually find better parameters? Mi možemo vizualizirati grešku kao funkciju u visokim dimenzijama, gde svaka dimenzija odgovara jednom parametru modela. Misliti u mnogim dimenzijama praktički je nemoguće za ljude, tako da umesto toga možemo zamisliti jednostavniju analogiju: krajolik brda i dolina. U ovoj analogiji: Svaka tačka na krajolici predstavlja specifičnu kombinaciju parametara modela. Visina krajolika u tom trenutku predstavlja grešku modela. Na početku obuke, parametri se inicijalizuju slučajno. Ovo je kao da se nalaze na slučajnom mestu na brdu. Naš cilj je da minimiziramo grešku, što znači da pronađemo najnižu tačku u krajoliku. Teškoća je u tome što ne znamo kako izgleda krajolik.To je kao da pokušavamo hodati niz planinu slijepo ili u debelom maglu. To je mjesto na kojem dolazi gradijentni pad. U matematici postoji koncept koji se zove , koji opisuje nagib funkcije u određenoj točki. derivative Ovo je nevjerojatno korisno ovdje. Derivat nam govori . which direction the landscape slopes downward Dakle, algoritam jednostavno radi sljedeće: Izmerite sklonost krajolika. Napravite mali korak u pravcu u kojem greška smanjuje. Ponavljanje Korak po korak, model postupno ide nizbrdo dok ne dostigne nisku tačku u greškom krajoliku. U suštini, to je ono što gradientni pad čini. Preostalo pitanje je: Kako izračunamo nagib tako složene funkcije? Ovde neću ući u sve matematičke detalje, jer Karpathy već ima objašnjavajući to. Odličan video Za naše svrhe, dovoljno je znati sljedeće. Svaka matematička operacija ima odgovarajuće pravilo koje nam omogućuje da izračunamo njegov lokalni gradient.Osim toga, postoji pravilo nazvano pravilo lanca, koje nam omogućuje da kombinujemo ove lokalne gradiente da izračunamo gradient čitave kompozitne funkcije. Ključna ideja je da se krećemo unazad kroz lanac operacija, prikupljajući gradiente na putu. Svi veliki okviri dubokog učenja primjenjuju ovaj mehanizam. Na primer: TensorFlow koristi sistem pod nazivom GradientTape, koji bilježi operacije kao što je snimak tepiha tako da se gradijenti mogu izračunati naknadno. PyTorch povezuje informacije o gradientu direktno sa tenzorima. Svaki tenzor pamti kako je stvoren, što omogućava automatsko izračunavanje gradijenata. Karpathy implementacija slijedi istu osnovnu ideju. # Let there be Autograd to recursively apply the chain rule through a computation graph class Value: __slots__ = ('data', 'grad', '_children', '_local_grads') # Python optimization for memory usage def __init__(self, data, children=(), local_grads=()): self.data = data # scalar value of this node calculated during forward pass self.grad = 0 # derivative of the loss w.r.t. this node, calculated in backward pass self._children = children # children of this node in the computation graph self._local_grads = local_grads # local derivative of this node w.r.t. its children def __add__(self, other): other = other if isinstance(other, Value) else Value(other) return Value(self.data + other.data, (self, other), (1, 1)) def __mul__(self, other): other = other if isinstance(other, Value) else Value(other) return Value(self.data * other.data, (self, other), (other.data, self.data)) def __pow__(self, other): return Value(self.data**other, (self,), (other * self.data**(other-1),)) def log(self): return Value(math.log(self.data), (self,), (1/self.data,)) def exp(self): return Value(math.exp(self.data), (self,), (math.exp(self.data),)) def relu(self): return Value(max(0, self.data), (self,), (float(self.data > 0),)) def __neg__(self): return self * -1 def __radd__(self, other): return self + other def __sub__(self, other): return self + (-other) def __rsub__(self, other): return other + (-self) def __rmul__(self, other): return self * other def __truediv__(self, other): return self * other**-1 def __rtruediv__(self, other): return other * self**-1 def backward(self): topo = [] visited = set() def build_topo(v): if v not in visited: visited.add(v) for child in v._children: build_topo(child) topo.append(v) build_topo(self) self.grad = 1 for v in reversed(topo): for child, local_grad in zip(v._children, v._local_grads): child.grad += local_grad * v.grad U Karpathyjevom kodu, čitava gradientna računalna logika je implementirana u Klasa, koja je samo o . Value 40 lines long Ova klasa je u suštini omotač oko numeričkih vrednosti. Pored pohrane samih podataka, ona također pohranjuje: Koje su vrijednosti izračunane od (njene djece), i lokalne gradiente potrebne za backpropagiranje. Ako pogledamo kod, možemo vidjeti da su standardni operatori redefinisani: • Dodavanje • Mujo i drugih. To znači da svaki put kada izvršimo matematičku operaciju na objekata, program ne samo da izračunava rezultat, već i beleži koje su vrednosti ga proizvele i kako bi se gradijent trebao propagirati. Value Na kraju, The On ide unazad kroz lanac operacija i izračunava ukupni gradient u odnosu na grešku. backward() I to je u suštini cela ideja. Druga važna komponenta obuke je gradijentni pad sam, koji koristi izračunate gradijente za ažuriranje parametara modela. Drugim rečima, ovo je deo koda koji zapravo hoda niz brdo koristeći informacije o nagiba. # Adam optimizer update: update the model parameters based on the corresponding gradients lr_t = learning_rate * (1 - step / num_steps) # linear learning rate decay for i, p in enumerate(params): m[i] = beta1 * m[i] + (1 - beta1) * p.grad v[i] = beta2 * v[i] + (1 - beta2) * p.grad ** 2 m_hat = m[i] / (1 - beta1 ** (step + 1)) v_hat = v[i] / (1 - beta2 ** (step + 1)) p.data -= lr_t * m_hat / (v_hat ** 0.5 + eps_adam) p.grad = 0 U implementaciji Karpathy, ovo je učinjeno sa , koji je jedan od najčešće korišćenih optimizacijskih algoritama u dubokom učenju. Adam optimizer Adam je malo sofisticiraniji od osnovnog gradientnog spuštanja. Umjesto da uzme korake fiksne veličine, dinamički prilagođava veličinu koraka na osnovu povijesti prethodnih gradijenata. . faster and more stable Gradientno izračunavanje opisano ranije i korak optimizacije zajedno formiraju ono što bismo mogli nazvati okvir za duboko učenje deo koda. Svaka neuronska mreža – bez obzira da li pokreće jezični model, generator slika, robotski kontroler ili autonomno vozilo – trenira se koristeći u suštini isti princip. Ove nekoliko redova koda hvata osnovnu ideju iza moderne AI. Veliki okviri kao što su: Tenzorski tokovi Petarčević Džeks pružaju visoko optimizovane implementacije koje se mogu pokrenuti na GPU-ima, TPU-ima i distribuiranim klasterima, i uključuju mnoge dodatne trikove i optimizacije. Ali ako sve obrišemo na bitno, temeljni princip je upravo isti kao i ono što vidimo u ovoj sitni Python implementaciji. Now that we have seen the deep learning framework part of the code, we can move on to the actual neural network, in other words, the GPT model itself. Kao što je ranije spomenuto, cilj GPT-a je predvidjeti sljedeći token na temelju tokena koji su došli prije njega. Ova definicija je malo pojednostavljena, jer unos zapravo ne sastoji se od riječi, već od žetona. Tokeni su vrlo slični rečima, ali nisu isti. Umjesto da se oslanja na unapred definisani rječnik, sistem statistički uči rečnik iz podataka o obuci. Tokeni su stoga nizovi znakova koji se često pojavljuju u skupu podataka. Dakle, obuka ne počinje s fiksnom listom reči u kojima svaka reč već ima broj koji joj je dodijeljen. Ovaj pristup je posebno koristan za aglutinacijske jezike, kao što je mađarski, gde pojedinačna reč može imati mnogo različitih oblika zbog sufiša i gramatičkih završetaka. Uz dovoljno podataka o obuci, jezični model može naučiti bilo koji jezik, bilo prirodni ili veštački. Zapravo, žetoni ne moraju ni da predstavljaju tekst. Delovi slika Fragmenti audio Sensori za čitanje ili praktički bilo koju vrstu podataka Zbog toga, modeli transformatora nisu ograničeni na obradu jezika. Oni se takođe mogu koristiti za stvaranje slika, obradu govora, robotiku i mnoge druge zadatke. Karpathyov model je namjerno vrlo mali, tako da u ovom slučaju žetoni nisu riječi već znakovi. Stoga cilj modela nije generisanje punih rečenica ili odgovora, već jednostavno proizvodnja realističnih imena. Sastav podataka o obuci sastoji se od velike liste imena, a nakon obuke očekujemo da će model generisati nova imena koja statistički liče na primere. To je očigledno daleko od punog jezičnog modela kao što je ChatGPT. Ali u stvarnosti, razlika je uglavnom jedna od skale. Ako bismo proširili ovaj model milion puta, koristili žetone umesto znakova i obučavali ga na ogromnim skupovima podataka prikupljenih s interneta, završili bismo s nečim vrlo sličnim modernom modelu velikog jezika. These large models are typically trained in two stages: Pretraining – obuka o masivnim internetskim skupovima podataka za učenje općih jezičnih uzoraka. Fine-tuning – daljnje osposobljavanje koristeći kurirane ljudske generirane razgovore za poboljšanje odgovora. Proces zahtijeva ogromne računalne resurse i ogromne količine visokokvalitetnih podataka, često koštaju milijune dolara u računanju. Budući da većina nas nema pristup takvim resursima, morat ćemo se dogovoriti za generiranje imena. # Let there be a Dataset `docs`: list[str] of documents (e.g. a list of names) if not os.path.exists('input.txt'): import urllib.request names_url = 'https://raw.githubusercontent.com/karpathy/makemore/988aa59/names.txt' urllib.request.urlretrieve(names_url, 'input.txt') docs = [line.strip() for line in open('input.txt') if line.strip()] random.shuffle(docs) print(f"num docs: {len(docs)}") # Let there be a Tokenizer to translate strings to sequences of integers ("tokens") and back uchars = sorted(set(''.join(docs))) # unique characters in the dataset become token ids 0..n-1 BOS = len(uchars) # token id for a special Beginning of Sequence (BOS) token vocab_size = len(uchars) + 1 # total number of unique tokens, +1 is for BOS print(f"vocab size: {vocab_size}") Na početku koda nalazimo odeljak odgovoran za učitavanje skupova podataka imena i izgradnju vokabula. U ovom slučaju, rečnik se jednostavno sastoji od liste znakova koji se pojavljuju u skupu podataka. Svakom znaku je dodijeljen numerički identifikator, što omogućuje pretvaranje teksta u brojeve koje neuronska mreža može obrađivati. Sljedeći je jedan od najvažnijih koncepata u dubokom učenju: . embeddings The idea is simple but powerful. Umjesto da radimo sa ID-ovima sirovih žetona, mi mapiramo svaki žeton u Ovi vektori su ono što neuronska mreža zapravo obrađuje. point in a high-dimensional vector space Zapravo, svaka neuronska mreža može se smatrati funkcijom koja . maps vectors from one high-dimensional space into another Na primer: Ako obučemo neuronsku mrežu da klasifikuje slike kao pse ili mačke, mreža mapira slikovnu reprezentaciju u dvodimenzionalni prostor, gde jedna dimenzija odgovara "dogness" a druga "catness". Ako zamislimo generator slike kao što je Midjourney, on mapira slučajnu buku u visoko-dimenzionalni prostor gde svaka tačka predstavlja sliku kondicioniranu na prompt. Bez obzira na zadatak, mreža uvek obavlja . vector-to-vector transformation using a large mathematical function Isto važi i za GPT. Dimenzionalnost vektorskog prostora definisana je u kodu konstantom koji je u ovoj provedbi predviđen za . n_embd 16 To znači da je svaki token (u ovom slučaju, svaki znak) predstavljen kao . 16-dimensional vector Matematski, ovaj mapiranje je jednostavno a . matrix multiplication U kodu, matrica odgovorna za ovu transformaciju zove se koji stoji za . wte word/token embedding Međutim, znati koji znakovi se pojavljuju u jednoj riječi nije dovoljno. also matters. position For example, the meaning of a sequence changes if we rearrange the characters. Kako bi se uključile informacije o poziciji, model koristi , implementirana pomoću druge matrice nazvane . positional embeddings wpe Kod mapira i token i njegovu poziciju u 16-dimenzionalnim vektorima, a zatim jednostavno . adds the two vectors together Rezultat je jedan vektor koji kodira oba: the identity of the token its position within the sequence Ranije smo spomenuli da ove vektorske reprezentacije moraju biti značajne, jer će kasnije model izračunati pogreške na osnovu udaljenosti između vektorâ. Ideally: Gotovo ispravne predviđanja bi trebala biti blizu ispravnog vektor should be far away from it Very wrong predictions This raises an interesting question: How do we design a good embedding space? Odgovor je iznenađujuće jednostavan: We don’t. Umjesto toga, inicijalizujemo ugrađene matrice ( i ) with random numbers and allow gradient descent to learn the correct representation during training. wte wpe If we have enough data, the optimization process will gradually adjust the matrices until they represent useful relationships. This can lead to surprisingly powerful emergent properties. For example, in the famous Uključivanje modela, vektorske aritmetike može uhvatiti semantičke odnose. word2vec king − man + woman ≈ queen Ovde već možemo videti da ugradni prostor počinje predstavljati neku vrstu , gde se odnosi između pojmova pojavljuju kao geometrijski odnosi između vektora. simplified model of the world Sada kada smo videli kako se kreiraju vektori, konačno možemo pogledati samu neuronsku mrežu, komponentu koja pretvara te vektore u nove vektore koji predstavljaju sljedeći token. In other words, the network maps vectors from the token embedding space back into the same space, but shifted by one token. For each token, it predicts which token should follow next. By repeatedly applying this process, the model can generate an entire sequence of text — or in this case, a name. The architecture used for this is called the . Transformer Transformer je predstavljen 2017. godine od strane istraživača u Google-u u poznatom članku: “Attention Is All You Need.” Originalna arhitektura je dizajnirana za Sastoji se od dva glavna dijela: machine translation Kodiranje a decoder The encoder processed the input sentence, while the decoder generated the translated output sentence. For generative models like GPT, however, we only need : the . half of the original architecture decoder stack To je razlog zašto su GPT modeli često opisani kao . decoder-only transformers Dekoder prima ulazne žetone i više puta ih obrađuje kroz skup identičnih slojeva.Svaki sloj sadrži dvije glavne komponente: Samopozornost A feed-forward neural network (MLP) Ovi slojevi se ponavljaju mnogo puta u velikim modelima. U diagramima, često vidite ovo predstavljeno kao , meaning the block is stacked multiple times. ×N One of the key innovations of the Transformer architecture is that it processes the . entire sequence at once Stariji jezični modeli, posebno recidivne neuronske mreže (RNN), obrađivali su tekst jednu reč odjednom, sekvencijalno prenoseći informacije duž sekvencije. Oni mogu istovremeno pogledati sve žetone, omogućujući modelu da nauči odnose između bilo kojih dijelova teksta. Ovaj mehanizam se zove , which is why the original paper was titled . attention Pažnja je sve što vam je potrebno Mehanizam pažnje izračunava kako in the sequence. relevant each token is to every other token Za svaki token vektor, model izračunava skup težina koje opisuju koliko pažnje treba obratiti na druge tokene. Stoga dobiveni vektor predstavlja ne samo sam token, već i . its meaning in the context of the entire sequence This may sound complicated, but the intuition is straightforward. Pretpostavimo da pitamo jezik modela: “What is the capital of France?” If we only looked at the word , nismo mogli odrediti odgovor. ali pažnja omogućuje modelu da poveže reč with . “capital” “capital” “France” Rezultirajuća reprezentacija hvata značenje fraze , making it possible for the model to produce the correct answer: . “capital of France” Paris One way to think about transformers is to imagine them as a kind of . soft database Umesto pohranjivanja eksplicitnih činjenica, model pohranjuje znanje u vektorskoj prostornoj reprezentaciji.Budući da neuronske mreže približavaju funkcije, a ne pamte tačna pravila, često mogu odgovoriti na pitanja koja nikada ranije nisu vidjela. Returning to our earlier embedding example: If the training data contains information about kings and women, the model may still be able to answer questions about queens, because the relationships between these concepts are captured in the vector space. If we follow this database analogy, we might say: acts like an , helping the model locate relevant information. Attention index The contain the knowledge itself. MLP layers Ovaj mentalni model je koristan za intuiciju, ali nije doslovno točan. In a real transformer like the one used in ChatGPT, these attention + MLP blocks are repeated many times. Znanje nije pohranjeno na jednoj lokaciji, već je raspodijeljeno preko slojeva. Additionally, each layer includes a residual connection, which mixes the original input vectors with the newly computed vectors. This allows information to flow through the network more effectively and stabilizes training. Kako vektori prolaze kroz slojeve, mogu se pojaviti nove abstrakcije i značenja. Do trenutka kada konačni sloj proizvede svoj izlaz, model je kombinirao informacije iz mnogih različitih nivoa predstavljanja. The full process is far too complex to follow step by step with human intuition. Ipak, unatoč ovoj složenosti, sistem funkcioniše izuzetno dobro u praksi. Now that we have a rough intuition about the transformer architecture, let’s look at one of its most important components in more detail: . attention # 1) Multi-head Attention block x_residual = x x = rmsnorm(x) q = linear(x, state_dict[f'layer{li}.attn_wq']) k = linear(x, state_dict[f'layer{li}.attn_wk']) v = linear(x, state_dict[f'layer{li}.attn_wv']) keys[li].append(k) values[li].append(v) x_attn = [] for h in range(n_head): hs = h * head_dim q_h = q[hs:hs+head_dim] k_h = [ki[hs:hs+head_dim] for ki in keys[li]] v_h = [vi[hs:hs+head_dim] for vi in values[li]] attn_logits = [sum(q_h[j] * k_h[t][j] for j in range(head_dim)) / head_dim**0.5 for t in range(len(k_h))] attn_weights = softmax(attn_logits) head_out = [sum(attn_weights[t] * v_h[t][j] for t in range(len(v_h))) for j in range(head_dim)] x_attn.extend(head_out) x = linear(x_attn, state_dict[f'layer{li}.attn_wo']) x = [a + b for a, b in zip(x, x_residual)] In Karpathy’s implementation, attention is calculated using three matrices called: Q (Želja za) Ključna reč: K V (Value) Te matrice vrše vektorske projekcije. Drugim rečima, svaki tokenski vektor je mapiran u tri različita vektorska prostora. Za svaki token izračunavamo: a query vector a key vector Vektor vrednosti Once we have these vectors, we compare the query vector of one token with the key vectors of all tokens in the sequence. Mathematically, this is done using a dot product. The dot product gives a score that represents how strongly two vectors are related. This produces a set of numbers that represent . how relevant each token is to the current token However, these raw scores are not yet probabilities. To convert them into a probability distribution, we apply the , which transforms the scores into values between 0 and 1 that sum to 1. softmax function These values represent how much attention each token should receive. Konačno, model kombinira vrednosne vektore koristeći ove težine pažnje, stvarajući novi vektor koji sadrži informacije prikupljene iz cijelog konteksta. Formula za skaliranu pažnju na točke proizvoda izgleda ovako: Attention(Q, K, V) = softmax(QKᵀ / √dₖ) V Ovde je: computes the similarity between queries and keys QKᵀ √dk je faktor skaliranja koji stabilizuje obuku softmax pretvara ocene u verovatnoće pažnje V daje informacije koje se kombiniraju prema tim verovatnoćama Rezultat je nova reprezentacija za svaki token koji odražava . its meaning in the context of the entire sequence At this point, it is worth mentioning an important concept: . context length Kao što smo ranije razgovarali, transformatori obrađuju čitavu sekvencu odjednom. . every token with every other token That means the computational cost grows S brojem tokena. quadratically If we double the context length, the amount of computation increases roughly four times. Ovo je jedno od glavnih ograničenja modela transformatora. Za razliku od nekih drugih arhitekture, transformatori nemaju zaseban sistem memorije. Oni mogu samo "videti" žetone koji se uklapaju u njihov kontekstni prozor. Sve izvan tog prozora je zapravo nevidljivo za model. To je razlog zašto je dužina konteksta tako važno svojstvo modernih jezičnih modela. In many modern AI systems, this limitation is addressed by adding an external memory mechanism. A common approach is to use a . vector database Umesto pohrane znanja direktno u modelu, informacije se mogu pohraniti spolja kao vektorske ugrađivanja. When the model receives a question, the system can: Convert the question into a vector. Potražite vektorsku bazu podataka za relevantne informacije. Insert the retrieved information into the model’s context. This means the model sees both: pitanje i relevantno znanje preuzeto iz baze podataka Because both appear in the context window, the model can generate an answer based on that information. This technique is known as and is widely used in modern AI systems and agent frameworks. Retrieval-Augmented Generation (RAG) U ovom podešavanju, glavna uloga jezikovnog modela nije skladištenje znanja, već generisanje koherentnih odgovora na osnovu informacija dostupnih u njegovom kontekstu. But as we can see, this requires space in the context window, which is why context length remains so important. Returning to Karpathy’s implementation, the model uses , što je poboljšan oblik osnovnog mehanizma pažnje. multi-head attention Umesto izračunavanja pažnje pomoću jednog skupa Q, K i V matrica, model koristi više glava pažnje. In this implementation, there are four heads. Each head learns to focus on different kinds of relationships between tokens. For example, one head might focus on grammatical relationships, while another might capture longer-range dependencies. Korištenje više glava poboljšava kvalitet reprezentacije. To keep the computational cost roughly the same, the dimensionality of each head is reduced. Ranije smo kartografirali vektore iz a . 16-dimensional space to another 16-dimensional space With four attention heads, each head instead works in a Rezultati iz glava se zatim kombiniraju nazad u jedan vektor. 4-dimensional space Iako svaka glava radi sa nižim-dimenzionalnim vektorima, kombinirani rezultat je obično izraženiji i precizniji od upotrebe jedne glave pažnje. Sada kada smo obuhvatili mehanizam pažnje, pređimo na drugu glavnu komponentu transformatora: ili . MLP feed-forward neural network In the code, the MLP block looks something like this: # 2) MLP block x_residual = x x = rmsnorm(x) x = linear(x, state_dict[f'layer{li}.mlp_fc1']) x = [xi.relu() for xi in x] x = linear(x, state_dict[f'layer{li}.mlp_fc2']) x = [a + b for a, b in zip(x, x_residual)] MLP je a . If we look at the structure of the weight matrices, we can interpret the rows of the matrix as . classic neural network architecture neurons A neuron is a simple computational unit that: Umnožava svaki unos po težini, sums the results, Zatim primjenjuje ne-linearnu funkciju aktivacije za proizvodnju izlaza. Ovaj model je izvorno bio inspirisan biološkim neuronima u ljudskom mozgu.U tom smislu, neuronske mreže su povijesno bile motivirane pokušajima da oponašaju kako mozak može obrađivati informacije. Međutim, moderni AI sistemi otišli su prilično daleko od ove originalne analogije. U MLP komponenti, još uvijek možemo lako prepoznati nešto što liči na neurone. , postaje mnogo teže održavati interpretaciju inspiriranu mozgom. attention Zbog toga je često bolje misliti na moderne AI sisteme jednostavno kao , umjesto doslovnih modela mozga. trainable mathematical functions MLP blok u kodu sastoji se od tri glavna koraka: linearna transformacija (multiplikacija matrice) a (ReLU), nonlinear activation function another . linear transformation Ovo može izgledati jednostavno, ali strukture poput ove imaju izuzetno moćno matematičko svojstvo. Poznati su kao . universal approximators universal approximators This means that, under certain conditions, a sufficiently large MLP can approximate do arbitrarnog stupnja preciznosti. any mathematical function U principu, jedan ogroman MLP mogao bi naučiti gotovo sve. Zbog toga transformatorske arhitekture kombiniraju više mehanizama, uključujući pažnju i slojeve, kako bi distribuirali izračun učinkovitije. Izlaz mreže nije jedan token, već . probability distribution over all possible tokens Drugim riječima, za svaki token u vokabularu, model izlazi verovatnoću da bi se trebao pojaviti sledeći u nizu. During generation, the algorithm then samples from this probability distribution. To znači da su žetoni s većom verovatnoćom češće odabrani, ali još uvijek postoji element slučajnosti. Ova slučajnost je kontrolisana parametrom koji se zove . temperature Naši parametar određuje koliko će deterministički ili kreativni izlaz modela biti. temperature Niska temperatura - model snažno preferira najvjerojatnije žetone, proizvodeći predvidljivije i točnije odgovore. - the probability distribution becomes flatter, allowing less likely tokens to be selected more often, resulting in more diverse or creative outputs. High temperature Na primer: Ako želimo da model analizira dokument i odgovori na stvarna pitanja, niska temperatura je obično poželjna. If we want the model to generate creative text or explore new ideas, a can produce more interesting results. higher temperature This is roughly what I wanted to explain about this beautiful piece of code, and about GPT models in general. In many places, the explanation necessarily remained somewhat superficial. My goal was to strike a balance between two things: including as much useful insight as possible, while still keeping the discussion within the scope of a single article Za čitaoce koji su pronašli dijelove objašnjenja malo nejasno, ili koji žele istražiti detalje dublje, preporučujem Njegova , and Tamo ćete naći odličan materijal koji objašnjava sve što je potrebno da u potpunosti razumete koncepte o kojima se ovde raspravlja. Andrej Karpathy’s personal website Youtube kanali Vaš blog Nadam se da je ovaj članak bio koristan za mnoge čitatelje. Ako ništa drugo, možda služi kao poziv za istraživanje fascinantan svet AI.