របៀបបង្វឹក Model
មាតិកា
- ការរាប់មិនមែនជារបៀបដែល model ធំរៀនទេ
- Parameter៖ ប៊ូតុងបង្វិលរបស់ model
- Loss៖ ពិន្ទុដែលប្រាប់ថាអ្នកខុសប៉ុនណា
- Gradient Descent៖ បង្វិលប៊ូតុងចុះទៅក្រោម
- Training Loop ក្នុងកូដ
- មើល Loss ធ្លាក់ចុះ
- អ្វីដែល model បានរៀន
- Learning Rate
- ការទន្ទេញ ប្រៀបធៀបនឹងការរៀន៖ អត្ថបទដែលមិនធ្លាប់ឃើញ
- ការពង្រីក៖ រាប់ពាន់លាន Parameter
- Pretraining, Fine-Tuning និង Preference Tuning
- ហេតុអ្វីការបង្វឹកថ្លៃ ហើយ Inference ថោក
- ទិន្នន័យបង្វឹក កម្មសិទ្ធិបញ្ញា និង Bias
- រូបមន្ត៖ Module train
- សាកល្បងដោយខ្លួនឯង
- សំណួរដែលអ្នកនឹងត្រូវគេសួរ
1. ការរាប់មិនមែនជារបៀបដែល model ធំរៀនទេ
នៅក្នុង Build a Tiny Language Model អ្នកបានបង្កើត model មួយដោយ ការរាប់៖ តើពាក្យ "coffee" ដើរតាមពាក្យ "the" ញឹកញាប់ប៉ុនណា? រាប់គ្រប់គូម្តង ចែក រួចចប់។ គ្មាន learning loop គ្មានការទាយអ្វីទេ។
ការរាប់ដំណើរការបានសម្រាប់ប្រដាប់ក្មេងលេង ប៉ុន្តែមិនមែនសម្រាប់ LLM ពិតទេ។ Model ពិតអាន token មុនៗរាប់រយ ឬរាប់ពាន់ ដូច្នេះចំនួន context ដែលអាចមានគឺធំជាង អត្ថបទណាមួយដែលអ្នកអាចរាប់បានយ៉ាងសម្បើម ហើយវាត្រូវតែឆ្លើយបានសមហេតុផលសម្រាប់ context ដែលវាមិនធ្លាប់ឃើញ។
ដូច្នេះ model ពិតមិនរក្សាទុកចំនួនរាប់ទេ។ វារក្សាទុកគំនរ លេខ ដ៏ធំមួយ (ហៅថា parameter ឬ weight) ហើយ កែសម្រួល លេខទាំងនោះបន្តិចម្តងៗ រហូតដល់ model ទាយអត្ថបទបានល្អ។ ដំណើរការបន្ទាប់បន្សំនោះហៅថា ការបង្វឹក (training)។
នៅក្នុងជំពូកនេះ អ្នកនឹងធ្វើរឿងនោះពិតប្រាកដ លើ model តូចល្មមអាចអានយល់បាន។ Model នេះនឹងចុងក្រោយស្ទើរតែដូចតារាងរាប់របស់អ្នក ដែលជាចំណុចសំខាន់៖ អ្នកនឹងឃើញ អ្វីដែលការបង្វឹកធ្វើ ដោយមិនត្រូវការគណិតវិទ្យាអ្វីលើសពីនព្វន្ធថ្នាក់សាលាទេ។
2. Parameter៖ ប៊ូតុងបង្វិលរបស់ model
គិតពីតុលាយសំឡេងដែលមានប៊ូតុងបង្វិលច្រើន៖ ប៊ូតុងនីមួយៗជាលេខមួយ ហើយទីតាំងទាំងអស់ រួមគ្នាកំណត់អ្វីដែលចេញមក។ Model គឺជាសំណុំលេខបែបនោះ។
Model តូចរបស់យើងគឺជា តារាងពិន្ទុ (ស៊េរីនេះហៅពិន្ទុទាំងនោះថា logit ដូចអ្នកបាន ឃើញក្នុង Probabilities, Temperature and Sampling)។ វាមានមួយជួរសម្រាប់រាល់ពាក្យក្នុង vocabulary និងមួយជួរឈរសម្រាប់រាល់ពាក្យដែលអាចមកបន្ទាប់៖
next: coffee tea table ...
current: the ? ? ?
coffee ? ? ?
students ? ? ?
ដើម្បីទាយអ្វីដែលមកបន្ទាប់ពី "the" សូមមើលជួរ "the" បញ្ជូនពិន្ទុតាម softmax
ដើម្បីបានប្រូបាប រួចជ្រើស។ រាល់ក្រឡានីមួយៗគឺជា parameter មួយ។ ជាមួយ vocabulary
ដែលមាន V ពាក្យ តារាងមាន V * V parameter។
តោះមើលទិន្នន័យ ហើយរាប់វា៖
// demo-data.js
import { corpus, words } from "./src/corpus.js";
import { buildVocab, makePairs } from "./src/train.js";
const tokens = words(corpus);
const { vocab, index } = buildVocab(tokens);
const pairs = makePairs(tokens, index);
console.log("tokens:", tokens.length, "vocab:", vocab.length, "pairs:", pairs.length);
console.log("parameters:", vocab.length * vocab.length);
console.log("first pair:", pairs[0], vocab[pairs[0][0]], "->", vocab[pairs[0][1]]);
// tokens: 182 vocab: 67 pairs: 181
// parameters: 4489
// first pair: [ 52, 39 ] sokha -> opens
Corpus មាន 182 ពាក្យ និង 67 ពាក្យខុសគ្នា។ គូជិតគ្នានីមួយៗ (current, next) គឺជា
training example មួយ៖ "បន្ទាប់ពី sokha ពាក្យបន្ទាប់ពិតគឺ opens"។
មាន 181 គូ។ តារាងមាន 67 * 67 = 4,489 parameter។ (កូដរបស់ buildVocab និង
makePairs នៅក្នុងរូបមន្តនៅចុងជំពូក ដែលអ្នកនឹងចម្លងទៅទីនោះ។)
លេខ 52 និង 39 គឺជា index របស់ពាក្យ (vocabulary ត្រូវបានតម្រៀបតាមអក្ខរក្រម)។
Model ធ្វើការលើលេខ មិនមែនលើ string ទេ។
អ្វីដែលមានស្ថេរភាព៖ លេខទាំងបួនមកពី corpus រួមគ្នា ដូច្នេះអ្នកគួរតែឃើញលេខ ទាំងនេះដូចគ្នាបេះបិទនៅលើកុំព្យូទ័រណាក៏ដោយ។
ការធ្វើឲ្យសាមញ្ញ។ ប្រដាប់ក្មេងលេងនេះប្រើពាក្យទាំងមូល ចំណែក model ពិតប្រើ sub-word token ហើយគណនាពិន្ទុពី context ទាំងមូលដោយប្រើស្រទាប់នព្វន្ធ មិនមែនមួយជួរ ក្នុងមួយពាក្យទេ។ ជំពូកទី 6 បង្ហាញរូបភាពមួយភាគ។
3. Loss៖ ពិន្ទុដែលប្រាប់ថាអ្នកខុសប៉ុនណា
ការបង្វឹកត្រូវការវិធីមួយដើម្បីនិយាយថា "ឥឡូវនេះ model អាក្រក់ប៉ុនណា?" ជាមួយលេខតែមួយ។ លេខនោះគឺ loss។ ទាបជាងគឺល្អជាង។
សម្រាប់ការទាយពាក្យបន្ទាប់ loss ត្រូវបានសាងសង់ពីគំនិតសាមញ្ញមួយ។ សម្រាប់ឧទាហរណ៍មួយ សូមមើលប្រូបាបដែល model ផ្តល់ឲ្យពាក្យបន្ទាប់ ពិត៖
- ផ្តល់
0.9៖ ល្អណាស់ ទណ្ឌកម្មតូច។ - ផ្តល់
0.1៖ មិនល្អ ទណ្ឌកម្មធំជាង។ - ផ្តល់
0.001៖ អាក្រក់ណាស់ ទណ្ឌកម្មធំសម្បើម។
ទណ្ឌកម្មគឺ -log(p) ដែល p ជាប្រូបាបនោះ។ អ្នកមិនចាំបាច់ដឹង logarithm ដើម្បីប្រើវាទេ។
គ្រាន់តែចងចាំរូបរាងរបស់វា៖
| ប្រូបាបដែលផ្តល់ឲ្យពាក្យពិត | ទណ្ឌកម្ម -log(p) |
|---|---|
| 1.0 (ប្រាកដ និងត្រឹមត្រូវ) | 0 |
| 0.5 | 0.69 |
| 0.1 | 2.30 |
| 0.01 | 4.61 |
ទណ្ឌកម្មកើនឡើងលឿន នៅពេល model កាន់តែមិនប្រាកដនឹងចម្លើយត្រឹមត្រូវ។ នេះគឺជា cross-entropy loss៖ loss សម្រាប់ dataset ទាំងមូលគឺជា មធ្យមភាគ នៃទណ្ឌកម្ម លើគ្រប់ឧទាហរណ៍។
Model ដែលមិនដឹងអ្វីសោះ ផ្តល់ឱកាសស្មើគ្នា 1/67 ដល់ពាក្យទាំង 67។ Loss របស់វាគឺ
-log(1/67) ដែលស្មើ log(67)៖
// demo-loss.js
import { corpus, words } from "./src/corpus.js";
import { buildVocab, makePairs, lossOf } from "./src/train.js";
const tokens = words(corpus);
const { vocab, index } = buildVocab(tokens);
const pairs = makePairs(tokens, index);
const zero = vocab.map(() => vocab.map(() => 0)); // all scores equal
console.log("start loss:", lossOf(zero, pairs).toFixed(4));
console.log("ln(vocab):", Math.log(vocab.length).toFixed(4));
// start loss: 4.2047
// ln(vocab): 4.2047
ទាំងពីរបន្ទាត់ត្រូវគ្នា៖ model ដែលទាយដោយចៃដន្យមាន loss ស្មើ
log(ទំហំ vocabulary)។ នោះគឺជាលេខដែលត្រូវយកឈ្នះ។ (Math.log ក្នុង JavaScript
ជា logarithm ធម្មជាតិ ដែលជាអ្វីដែលយើងប្រើពេញមួយស៊េរី។)
4. Gradient Descent៖ បង្វិលប៊ូតុងចុះទៅក្រោម
ឥឡូវនេះដល់ផ្នែកឆ្លាត។ យើងមានប៊ូតុង (parameter) និងពិន្ទុ (loss)។ តើយើងបង្វិលប៊ូតុង យ៉ាងដូចម្តេចដើម្បីបន្ថយពិន្ទុ?
ស្រមៃថាអ្នកឈរលើភ្នំមួយដែលមានអ័ព្ទ ហើយចង់ទៅដល់ជ្រលង។ អ្នកមើលមិនឃើញឆ្ងាយទេ ប៉ុន្តែអ្នកអាចដឹងពីជម្រាលនៅក្រោមជើង។ ដូច្នេះអ្នកដើរមួយជំហានតូច ចុះទៅក្រោម ដឹង ជម្រាលម្តងទៀត ដើរម្តងទៀត។ បន្តិចម្តងៗអ្នកទៅដល់បាត។
នោះគឺ gradient descent៖
- ដំណើរការ model លើទិន្នន័យ ហើយគណនា loss។
- សម្រាប់រាល់ parameter គណនា gradient របស់វា៖ "បើខ្ញុំបង្កើនលេខនេះបន្តិច តើ loss កើនឡើង ឬថយចុះ ហើយប៉ុនណា?"
- រុញរាល់ parameter មួយជំហានតូចតាមទិសដែលបន្ថយ loss។
- ធ្វើម្តងទៀត រាប់ពាន់ ឬរាប់លានដង។
ទំហំនៃជំហាននីមួយៗគឺ learning rate៖ តូចគឺសុវត្ថិភាពតែយឺត ធំពេកអាចលោតហួសជ្រលង។
ការគណនា gradient សម្រាប់ network ធំត្រូវការ calculus និងល្បិចមួយឈ្មោះ
backpropagation។ យើងមានសំណាង៖ សម្រាប់តារាងរបស់យើង ដែលប្រើ softmax និង
cross-entropy loss gradient សាមញ្ញល្មមសរសេរបានក្នុងមួយបន្ទាត់។
សម្រាប់ឧទាហរណ៍មួយ ដែលពាក្យបន្ទាប់ពិតគឺ t៖
gradient of the score for word j = probability(j) - (1 if j is t, else 0)
សូមអានវាជាពាក្យសាមញ្ញ។ សម្រាប់ពាក្យពិត gradient គឺ probability - 1 ដែលជា
អវិជ្ជមាន ដូច្នេះជំហានធ្វើឲ្យពិន្ទុរបស់វា កើនឡើង។ សម្រាប់រាល់ពាក្យខុស gradient
គឺ probability ដែលជាវិជ្ជមាន ដូច្នេះជំហានធ្វើឲ្យពិន្ទុរបស់វា ថយចុះ ច្រើនជាងសម្រាប់
ពាក្យដែល model ចូលចិត្តពេក។ Model ត្រូវបានរុញឡើងកន្លែងដែលវាគួរត្រូវ ហើយរុញចុះកន្លែង
ដែលវាខុស។ បន្ទាត់តែមួយនោះគឺជាច្បាប់រៀនទាំងមូលរបស់ប្រដាប់ក្មេងលេងនេះ។
Framework ពិតគណនា gradient ដោយស្វ័យប្រវត្តិសម្រាប់ parameter រាប់ពាន់លាន គំនិតដូចគ្នា៖ ជំហានតូចៗចុះទៅក្រោម។
5. Training Loop ក្នុងកូដ
នេះជាស្នូល សរសេរក្នុងប្រហែល 35 បន្ទាត់។ វាសាងសង់លើ softmax ពីជំពូកមុន។
// src/train.js (core)
import { softmax } from "./sampling.js";
export function lossOf(logits, pairs) {
let total = 0;
for (const [cur, next] of pairs) {
total += -Math.log(softmax(logits[cur])[next]);
}
return total / pairs.length;
}
export function step(logits, pairs, lr) {
const grad = logits.map((row) => row.map(() => 0));
for (const [cur, next] of pairs) {
const probs = softmax(logits[cur]);
for (let j = 0; j < probs.length; j++) {
grad[cur][j] += (probs[j] - (j === next ? 1 : 0)) / pairs.length;
}
}
for (let i = 0; i < logits.length; i++) {
for (let j = 0; j < logits[i].length; j++) logits[i][j] -= lr * grad[i][j];
}
}
សូមអានយឺតៗ៖
lossOfគឺជា cross-entropy ពីផ្នែកទី 3៖ សម្រាប់រាល់ឧទាហរណ៍ យកប្រូបាបដែល model ផ្តល់ឲ្យពាក្យបន្ទាប់ពិត ហើយយកមធ្យមភាគនៃ-logរបស់វា។stepគឺជាមួយជុំនៃ gradient descent។ វាបង្កើតតារាងgradរូបរាងដូចlogitsពេញដោយសូន្យ។ សម្រាប់រាល់ឧទាហរណ៍ វាបូកprobability - onehotទៅក្នុងជួរត្រឹមត្រូវ (ច្បាប់មួយបន្ទាត់ពីផ្នែកទី 4 ចែកនឹងចំនួនឧទាហរណ៍ដើម្បីធ្វើជាមធ្យមភាគ)។- Loop ចុងក្រោយរុញរាល់ parameter ដោយ
-lr * gradient៖ ជំហានតូចមួយតាមទិសចុះក្រោម។
បន្ទាប់មក loop ដែលហៅ step ម្តងហើយម្តងទៀត៖
export function train(tokens, { steps = 200, lr = 5, every = 20 } = {}) {
const { vocab, index } = buildVocab(tokens);
const pairs = makePairs(tokens, index);
const logits = vocab.map(() => vocab.map(() => 0));
const history = [{ step: 0, loss: lossOf(logits, pairs) }];
for (let s = 1; s <= steps; s++) {
step(logits, pairs, lr);
if (s % every === 0) history.push({ step: s, loss: lossOf(logits, pairs) });
}
return { vocab, index, logits, history };
}
រាល់ពិន្ទុចាប់ផ្តើមពី 0 ដូច្នេះ model ចាប់ផ្តើមដោយមិនដឹងអ្វីសោះ។ បន្ទាប់មកវាធ្វើ
step ម្តងហើយម្តងទៀត ដោយកត់ត្រា loss ម្តងម្កាលក្នុង history។ នេះគឺជា
training loop ហើយរូបរាងដូចគ្នានេះមានក្នុង deep learning framework ទាំងអស់៖
ទាយ វាស់ loss គណនា gradient ធ្វើបច្ចុប្បន្នភាព ធ្វើម្តងទៀត។
យើងប្រើការបង្វឹក full-batch៖ រាល់ជំហានប្រើឧទាហរណ៍ទាំង 181។ ការបង្វឹកពិត ប្រើ batch តូចៗចៃដន្យ ព្រោះ dataset ធំខ្លាំង។
6. មើល Loss ធ្លាក់ចុះ
ដំណើរការ training loop 300 ជំហាន ហើយបោះពុម្ព loss រាល់ 50 ជំហាន៖
// demo-train.js
import { corpus, words } from "./src/corpus.js";
import { train } from "./src/train.js";
const tokens = words(corpus);
const model = train(tokens, { steps: 300, lr: 5, every: 50 });
for (const h of model.history) {
console.log(String(h.step).padStart(4), h.loss.toFixed(4));
}
// 0 4.2047
// 50 2.5158
// 100 1.8059
// 150 1.4594
// 200 1.2882
// 250 1.2001
// 300 1.1502
នេះគឺជាអ្វីដែល "ការរៀន" មើលទៅដូចសម្រាប់កុំព្យូទ័រ៖ លេខមួយដែលថយចុះ។ ពី 4.20 (ទាយចៃដន្យក្នុងចំណោម 67 ពាក្យ) ទៅ 1.15 (ល្អជាងចៃដន្យច្រើន) ក្នុង 300 ជំហានតូចៗ។ គ្មាននរណាប្រាប់ model អំពី coffee ឬ students ទេ។ លេខបានផ្លាស់ទី ព្រោះការផ្លាស់ទី ធ្វើឲ្យការទាយលើទិន្នន័យខុសតិចជាងមុន។
សូមកត់សម្គាល់ រូបរាង ផងដែរ៖ វឌ្ឍនភាពលឿននៅដំបូង (4.20 ទៅ 2.52 ក្នុង 50 ជំហាន) យឺតនៅចុងបញ្ចប់ (1.20 ទៅ 1.15 ក្នុង 50 ជំហានចុងក្រោយ)។ ខ្សែកោងបង្វឹកពិតក៏មើលទៅដូច្នេះដែរ។
រាល់បន្ទាត់គឺ deterministic៖ គ្មានលេខចៃដន្យក្នុងកូដនេះទេ ដូច្នេះអ្នកគួរតែឃើញលេខ ទាំងនេះដូចគ្នាបេះបិទ។
7. អ្វីដែល model បានរៀន
បង្វឹកឲ្យយូរជាងនេះ បន្ទាប់មកមើលចូលក្នុងតារាង។ ប្រៀបធៀបប្រូបាប ដែលបានរៀន ជាមួយ ប្រូបាប ដែលបានរាប់ ពី bigram model នៃជំពូកទី 3៖
// demo-learned.js
import { corpus, words } from "./src/corpus.js";
import { train, lossOf, makePairs } from "./src/train.js";
import { softmax } from "./src/sampling.js";
import { trainBigram, nextWordProbs } from "./src/bigram.js";
const tokens = words(corpus);
const model = train(tokens, { steps: 1000, lr: 5, every: 250 });
for (const h of model.history) {
console.log(String(h.step).padStart(4), h.loss.toFixed(4));
}
function learned(word) {
const probs = softmax(model.logits[model.index.get(word)]);
return probs
.map((p, i) => [model.vocab[i], p])
.sort((a, b) => b[1] - a[1])
.slice(0, 4)
.map(([w, p]) => `${w} ${p.toFixed(3)}`);
}
const counts = trainBigram(tokens);
const fmt = ([w, p]) => `${w} ${p.toFixed(3)}`;
console.log("learned after 'the':", learned("the").join(", "));
console.log("counted after 'the':", nextWordProbs(counts, "the").slice(0, 4).map(fmt).join(", "));
console.log("learned after 'dara':", learned("dara").join(", "));
// 0 4.2047
// 250 1.2001
// 500 1.0722
// 750 1.0430
// 1000 1.0305
// learned after 'the': students 0.207, coffee 0.207, app 0.124, river 0.124
// counted after 'the': coffee 0.208, students 0.208, river 0.125, app 0.125
// learned after 'dara': writes 0.280, drinks 0.137, is 0.137, says 0.137
បន្ទាប់ពី 1000 ជំហាន ប្រូបាបដែលបានរៀនបន្ទាប់ពី "the" ស្ទើរតែដូចគ្នាទៅនឹងប្រូបាបដែល
បានរាប់ (0.207 ប្រឆាំង 0.208)៖ coffee និង students ទំនងជាងគេ បន្ទាប់មក river និង
app។ Model បានរកឃើញ ដោយការរុញលេខ នូវអ្វីដែលតារាងរាប់គណនាដោយផ្ទាល់។ សម្រាប់ model
តូចនេះ មានចម្លើយល្អឥតខ្ចោះ (ចំនួនរាប់) ហើយការបង្វឹកគឺកំពុងដើរឆ្ពោះទៅរកវា។
តើវាអាចទាបបានប៉ុនណា? Loss ល្អបំផុតដែលអាចទៅរួចសម្រាប់ model នេះគឺ loss របស់តារាងរាប់ខ្លួនឯង៖
// continue demo-learned.js
let best = 0;
const pairs = makePairs(tokens, model.index);
for (const [c, n] of pairs) {
const row = nextWordProbs(counts, model.vocab[c]);
best += -Math.log(row.find(([w]) => w === model.vocab[n])[1]);
}
console.log("loss of counted model:", (best / pairs.length).toFixed(4));
// loss of counted model: 1.0004
ការបង្វឹកបានដល់ 1.0305 ហើយកំពុងឆ្ពោះទៅ 1.0004។ វាមិនអាចទាបជាងនោះបានទេ ព្រោះ
model ដែលឃើញតែពាក្យមុនមួយមិនអាចមានការច្រឡំតិចជាងចំនួនរាប់បានទេ។ បន្ទាប់ពី
"dara" មានពាក្យបន្ទាប់ស្របច្បាប់ជាច្រើន ហើយការបង្វឹកប៉ុនណាក៏មិនអាចប្រាប់ថាមួយណា
មកបន្ទាប់ដែរ។ កម្រិតទាបបំផុតនោះ គឺភាពមិនប្រាកដដែលមិនអាចជៀសវាងបាន ក៏ជាមូលហេតុដែល
language model ត្រូវការ context ច្រើនជាងដើម្បីបាន loss ទាបជាង៖ មូលហេតុដូចគ្នាដែល
trigram យកឈ្នះ bigram នៅជំពូកទី 3។
សម្គាល់ស្មោះត្រង់មួយទៀត។ ការ sample ពីតារាងនេះផ្តល់អត្ថបទដូចជា "sokha cleans the window dara thinks about" ដែលរាល់គូជិតគ្នាពិតជាមាននៅក្នុង corpus ប៉ុន្តែប្រយោគមិនមែន ជាភាសាអង់គ្លេសល្អទេ ព្រោះ context មួយពាក្យតិចពេក។ Model បានរៀន ទម្លាប់របស់អត្ថបទ មិនមែនអត្ថន័យទេ។ ភាពខុសគ្នានោះសំខាន់នៅក្នុងជំពូក hallucination។
8. Learning Rate
ទំហំជំហាន lr គឺជាការកំណត់សំខាន់បំផុតក្នុងការបង្វឹក។ សាកល្បងតម្លៃប្រាំ ម្នាក់ 100 ជំហាន៖
// demo-lr.js
import { corpus, words } from "./src/corpus.js";
import { train } from "./src/train.js";
const tokens = words(corpus);
for (const lr of [0.5, 5, 50, 500, 5000]) {
const m = train(tokens, { steps: 100, lr, every: 100 });
console.log("lr", String(lr).padEnd(5), "loss after 100 steps:", m.history[1].loss.toFixed(4));
}
// lr 0.5 loss after 100 steps: 3.7206
// lr 5 loss after 100 steps: 1.8059
// lr 50 loss after 100 steps: 1.0300
// lr 500 loss after 100 steps: 4.3847
// lr 5000 loss after 100 steps: 61.9882
អានវាដូចរឿង៖ 0.5 សុវត្ថិភាពតែយឺតពេក។ 5 ធ្វើវឌ្ឍនភាពស្ថិរភាព។ 50 លឿនបំផុតនៅទីនេះ។
នៅ 500 loss អាក្រក់ជាងកន្លែងដែលវាចាប់ផ្តើម (4.38 ប្រឆាំង 4.20)៖ ជំហានធំខ្លាំង
ដល់ model លោតហួសជ្រលង ហើយចុះចតខ្ពស់ជាងនៅម្ខាងទៀត។ នៅ 5000 វា diverge។
Learning rate ល្អគឺ "ធំបំផុតដែលអាចដោយមិន diverge"។ ប្រដាប់ក្មេងលេងរបស់យើងជាបញ្ហា
ទន់ភ្លន់ រលោង ដូច្នេះ 50 ដំណើរការ។ Network ពិតមានដុំៗជាង ហើយត្រូវការជំហានតូចជាង
ច្រើន បូកនឹងល្បិចដូចជាចាប់ផ្តើមតូច ហើយបន្ទាប់មកថយយឺតទៅ។ ការជ្រើស learning rate
គឺជាផ្នែកធំនៃសិប្បកម្មបង្វឹក model ពិត។
9. ការទន្ទេញ ប្រៀបធៀបនឹងការរៀន៖ អត្ថបទដែលមិនធ្លាប់ឃើញ
Loss ទាបលើអត្ថបទបង្វឹកអាចបោកអ្នកបាន។ Model អាចធ្វើបានល្អលើអត្ថបទដែលវា បានឃើញ ព្រោះវាទន្ទេញវាតាមពិត ហើយធ្វើបានអាក្រក់លើអត្ថបទថ្មី។ ការសាកល្បងស្មោះត្រង់គឺ រក្សាទុក ទិន្នន័យខ្លះ មិនដែលបង្វឹកលើវា ហើយវាស់ loss លើវាបន្ទាប់ពីនោះ។
// demo-heldout.js
import { corpus, words } from "./src/corpus.js";
import { train, makePairs, lossOf } from "./src/train.js";
const tokens = words(corpus);
const cut = Math.floor(tokens.length * 0.8);
const m = train(tokens.slice(0, cut), { steps: 1000, lr: 5, every: 1000 });
// Pairs from the last 20% of the text, which the model never saw.
const unseen = makePairs(tokens.slice(cut - 1), m.index);
const usable = unseen.filter(([a, b]) => a !== undefined && b !== undefined);
console.log("train loss: ", m.history[1].loss.toFixed(4));
console.log("unseen pairs: ", usable.length, "usable of", unseen.length);
console.log("unseen loss: ", lossOf(m.logits, usable).toFixed(4));
// train loss: 0.9436
// unseen pairs: 23 usable of 37
// unseen loss: 2.9710
យើងបង្វឹកលើ 80% ដំបូងនៃពាក្យ ហើយសាកល្បងលើសល់។ Loss បង្វឹកគឺ 0.94 ប៉ុន្តែ loss លើ
អត្ថបទដែលមិនធ្លាប់ឃើញគឺ 2.97 អាក្រក់ជាងបីដង។ សូម្បីតែនោះក៏សរសើរ model ហួសដែរ៖
14 ក្នុងចំណោម 37 គូដែលមិនធ្លាប់ឃើញត្រូវបានបោះចោល ព្រោះវាមានពាក្យដែលមិនដែលលេចឡើង
ក្នុងផ្នែកបង្វឹក ដូច្នេះប្រដាប់ក្មេងលេងនេះមិនអាចសូម្បីតែ ដាក់ពិន្ទុ ពួកវាបាន។
គម្លាតធំរវាង loss បង្វឹក និង loss លើអត្ថបទដែលមិនធ្លាប់ឃើញ ហៅថា overfitting។ ក្រុមពិតតែងតែរក្សា validation set ដែល model មិនដែលបង្វឹកលើ ហើយតាមដាន loss នោះផងដែរ។
10. ការពង្រីក៖ រាប់ពាន់លាន Parameter
តារាងរបស់យើងមាន 4,489 parameter។ Language model ពិតត្រូវបានពិពណ៌នាដោយចំនួន parameter របស់វា ឧទាហរណ៍ "7 billion" ឬ "70 billion" (ទាំងនេះជាទំហំគំរូ មិនមែន ជាការអះអាងអំពីផលិតផលជាក់លាក់ណាមួយទេ)។ Parameter មិនមែនជាតារាងរកមើលពាក្យទេ។ វាជាលេខនៅខាងក្នុងស្រទាប់នព្វន្ធជាច្រើន (Transformer ដែលជំពូកទី 6 ណែនាំ) ដែលគណនាពិន្ទុ token បន្ទាប់ពី context ទាំងមូល។
តើចំនួន parameter មានន័យអ្វីក្នុងការអនុវត្ត? ភាគច្រើនគឺ អង្គចងចាំ។ រាល់លេខ ប្រើទំហំ ជារឿយៗ 2 byte ក្នុងទម្រង់ទូទៅ៖
// demo-size.js
for (const p of [4489, 7e9, 70e9]) {
console.log(String(p).padStart(12), "params ->", (p * 2) / 1e9, "GB at 2 bytes each");
}
// 4489 params -> 0.000008978 GB at 2 bytes each
// 7000000000 params -> 14 GB at 2 bytes each
// 70000000000 params -> 140 GB at 2 bytes each
Model 7 ពាន់លាន parameter ត្រូវការប្រហែល 14 GB គ្រាន់តែដើម្បីផ្ទុកលេខរបស់វា (នៅ 2 byte ក្នុងមួយ។ ទម្រង់តូចជាងបង្រួមវា)។ Model 70 ពាន់លានត្រូវការប្រហែល 140 GB ច្រើនជាងអង្គចងចាំរបស់ laptop ធម្មតា ឬកាតក្រាហ្វិកធម្មតាតែមួយ ដែលជាមូលហេតុដែល model ធំដំណើរការលើ server ពិសេស។ Model តូចៗអាចដំណើរការលើកុំព្យូទ័ររបស់អ្នកផ្ទាល់ ដែលជាជម្រើសពិតមួយដែលអ្នកនឹងជួបក្នុងជំពូកចុងក្រោយ។
ធំជាងមិនមែនល្អជាងដោយស្វ័យប្រវត្តិទេ ប៉ុន្តែជាមួយទិន្នន័យ និងកម្លាំងគណនាគ្រប់គ្រាន់ model ធំជាងមានទំនោរទាយអត្ថបទបានល្អជាង។ នោះគឺជានិន្នាការដែលបានសង្កេត មិនមែនការធានាទេ។
11. Pretraining, Fine-Tuning និង Preference Tuning
ការបង្វឹកដែលអ្នកទើបតែធ្វើគឺជា pretraining ក្នុងទម្រង់តូច៖ ទាយ token បន្ទាប់លើគំនរ អត្ថបទដ៏ធំ។ Chat assistant ត្រូវបានបង្កើតជាដំណាក់កាល។ នេះគឺជារូបភាពគំនិត។ មន្ទីរពិសោធន៍ផ្សេងៗខុសគ្នាក្នុងព័ត៌មានលម្អិត ហើយមួយចំនួនធំរក្សាទុកជាសម្ងាត់នូវរូបមន្ត ពិតប្រាកដរបស់ពួកគេ។
ដំណាក់កាលទី 1៖ Pretraining។ បង្វឹក model ពីលេខចៃដន្យ ឲ្យទាយ token បន្ទាប់លើ បណ្តុំអត្ថបទធំខ្លាំង (ទំព័រ web សៀវភៅ កូដ និងអ្វីៗផ្សេងទៀត)។ លទ្ធផលគឺ base model។ វាជាអ្នកបន្តអត្ថបទដ៏ល្អ។ ឲ្យវា "Q: What is the capital of Cambodia? A:" ហើយវាអាច បន្តដោយចម្លើយ ប៉ុន្តែវាក៏អាចបន្តដោយសំណួរប្រាំទៀតដែរ ព្រោះនៅលើអ៊ីនធឺណិតនោះជា អ្វីដែលតែងតែមកបន្ទាប់សំណួរ។ វាមិនដឹងថាវាគួរតែជាជំនួយការដែលមានប្រយោជន៍ទេ។
ដំណាក់កាលទី 2៖ Fine-tuning (instruction tuning)។ បន្តបង្វឹក model ដដែល ឥឡូវលើ សំណុំតូចជាងច្រើននៃឧទាហរណ៍ការសន្ទនាដែលបានបង្កើតយ៉ាងប្រុងប្រយ័ត្ន៖ សំណួរមួយ បន្ទាប់មកចម្លើយល្អ។ Loss ដូចគ្នា gradient descent ដូចគ្នា ទិន្នន័យផ្សេង។ Model រៀន ទម្រង់ និង រចនាប័ទ្ម នៃការជាជំនួយការ។
ដំណាក់កាលទី 3៖ Preference tuning (ឧទាហរណ៍ RLHF)។ បង្ហាញមនុស្ស (ឬ model ផ្សេង) ចម្លើយពីរចំពោះសំណួរដូចគ្នា ហើយសួរថាមួយណាល្អជាង។ បន្ទាប់មកកែ model ឲ្យចម្លើយ ប្រភេទដែលគេពេញចិត្តទំនងកើតឡើងកាន់តែច្រើន។ RLHF មកពី reinforcement learning from human feedback ហើយវាជាគ្រួសារមួយនៃវិធីធ្វើរឿងនេះ។ គោលដៅគឺចម្លើយដែលមានប្រយោជន៍ ជាង ស្មោះត្រង់ជាង និងគ្រោះថ្នាក់តិចជាង។
random numbers
|
| pretraining: predict next token on huge text
v
base model (continues text, not yet an assistant)
|
| fine-tuning: examples of good conversations
v
assistant-style model
|
| preference tuning: learn which answers people prefer
v
chat assistant
ការប្រុងប្រយ័ត្នស្មោះត្រង់ពីរ។ ការ tune ផ្លាស់ប្តូរ អាកប្បកិរិយា ប៉ុន្តែវាមិនដំឡើងអ្នកពិនិត្យ ការពិតទេ៖ model ដែលបាន tune នៅតែអាចខុសដោយទំនុកចិត្ត ដែលជាប្រធានបទនៃជំពូក hallucination។ ហើយ preference tuning បង្រៀនអ្វីដែលអ្នកវាយតម្លៃ ចូលចិត្ត ហើយ អ្នកវាយតម្លៃអាចចូលចិត្តចម្លើយគួរសម និងមានទំនុកចិត្តជាងចម្លើយត្រឹមត្រូវ។ ចាត់ទុកអាកប្បកិរិយា ដែលបាន tune ថា "ជាធម្មតាមានប្រយោជន៍" មិនមែន "ត្រូវជានិច្ច" ទេ។
សម្រាប់ការងារកម្មវិធីភាគច្រើន អ្នកនឹងមិនបង្វឹកអ្វីទេ៖ អ្នកនឹងសរសេរ prompt ល្អ ហើយផ្តល់ព័ត៌មានត្រឹមត្រូវដល់ model។
12. ហេតុអ្វីការបង្វឹកថ្លៃ ហើយ Inference ថោក
អ្នកប្រហែលជាធ្លាប់ឮថា ការបង្វឹក LLM ត្រូវចំណាយច្រើន ចំណែកការប្រើវាចំណាយតិចក្នុងមួយ request។ ប្រដាប់ក្មេងលេងរបស់យើងបង្ហាញមូលហេតុ ដោយការរាប់សាមញ្ញ។
Inference (ការប្រើ model ដែលបានបង្វឹក) មានន័យថា៖ ដំណើរការនព្វន្ធម្តងក្នុងមួយ token ដែលបង្កើត។ Parameter ថេរ។ អ្នកគ្រាន់តែធ្វើវិធីគុណ។
ការបង្វឹក មានន័យថាធ្វើនព្វន្ធដូចគ្នាលើ dataset ទាំងមូល ច្រើនដង បូក ការគណនា gradient (ប្រហែលការងារស្មើគ្នាម្តងទៀត ឬច្រើនជាង) និងធ្វើបច្ចុប្បន្នភាពរាល់ parameter លើរាល់ជំហាន។
ក្នុងប្រដាប់ក្មេងលេងរបស់យើង ជំហានបង្វឹកមួយគឺ softmax 181 បូកការធ្វើបច្ចុប្បន្នភាព parameter 4,489៖ 1,000 ជំហានគឺ softmax 181,000។
សម្រាប់ model ពិត លេខទាំងពីរកើនឡើងយ៉ាងធំសម្បើម៖ dataset គឺ token រាប់ទ្រីលាន រាល់ token ឆ្លងកាត់ parameter រាប់ពាន់លាន ហើយការបង្វឹកធ្វើមួយ ឬច្រើនជុំលើវា។ សរុបគឺជានព្វន្ធច្រើនជាងកុំព្យូទ័រ laptop មួយអាចធ្វើចប់ក្នុងមួយជីវិត ដូច្នេះមន្ទីរពិសោធន៍ ប្រើ chip ឯកទេសរាប់ពាន់ដំណើរការអស់រយៈពេលជាសប្តាហ៍ ឬខែ ជាមួយវិក្កយបត្រអគ្គិសនីធំ។ ការបង្វឹកគឺជា ថ្លៃតែម្តង ដ៏ធំសម្រាប់មន្ទីរពិសោធន៍។
បន្ទាប់ពីនោះ ការបម្រើ request មួយគឺជាពីរបីវិនាទីនៃចំណែកតូចមួយនៃ hardware នោះ។ ថ្លៃបង្វឹកត្រូវបានចែកចាយលើ request រាប់លាន។ នោះជាមូលហេតុដែលមន្ទីរពិសោធន៍អាច ផ្តល់ model ដែលបាន host ក្នុងតម្លៃតូចក្នុងមួយ request ហើយហេតុអ្វី អ្នក ស្ទើរតែមិន គួរបង្វឹក model ផ្ទាល់ខ្លួនពីដើមទេ។ (សេវា host នៅតែគិតថ្លៃតាម token ព្រោះការឆ្លើយ ជាការងារពិត។ អ្នកនឹងប៉ាន់ស្មានថ្លៃនោះក្នុង Tokens and Tokenizers និងម្តងទៀតក្នុងជំពូកចុងក្រោយ។)
Model ដែលបានបង្វឹកក៏ត្រូវបាន បង្កក ដែរ៖ ពេលអ្នកជជែក parameter របស់វាមិនផ្លាស់ប្តូរ ហើយចំណេះដឹងរបស់វាឈប់នៅចុងបញ្ចប់នៃទិន្នន័យបង្វឹករបស់វា។ នោះជាមូលហេតុដែល model តែឯងមិនដឹងព័ត៌មានកាលពីម្សិលមិញ។
13. ទិន្នន័យបង្វឹក កម្មសិទ្ធិបញ្ញា និង Bias
Model អាចរៀនតែគំរូដែលមាននៅក្នុងទិន្នន័យរបស់វា។ នេះមានផលវិបាកដែលគួរនិយាយឲ្យច្បាស់។
ទិន្នន័យមកពីណា។ Model ធំជាធម្មតាត្រូវបានបង្វឹកលើបណ្តុំធំនៃអត្ថបទ web សៀវភៅ និងកូដ។ Dataset ពិតប្រាកដជារឿយៗមិនត្រូវបានផ្សព្វផ្សាយលម្អិតទេ។
កម្មសិទ្ធិបញ្ញា និងការអនុញ្ញាត។ អត្ថបទភាគច្រើននោះត្រូវបានសរសេរដោយមនុស្សដែលមិនដែល ត្រូវបានសួរ។ ថាតើការបង្វឹកលើស្នាដៃមានកម្មសិទ្ធិបញ្ញាត្រូវបានអនុញ្ញាតឬអត់ ហើយក្រោម លក្ខខណ្ឌអ្វី កំពុងត្រូវបានជជែកដេញដោលនៅតុលាការ និងសភានៅប្រទេសផ្សេងៗ ហើយចម្លើយ មិនទាន់ដោះស្រាយទេ។ Model ខ្លះត្រូវបានបង្វឹកលើតែអត្ថបទដែលម្ចាស់បានយល់ព្រម ឬអត្ថបទ ដែលមានអាជ្ញាប័ណ្ណបើកចំហ។ ក្នុងនាមជាអ្នកអភិវឌ្ឍ សូមពិនិត្យអាជ្ញាប័ណ្ណ និងលក្ខខណ្ឌនៃ model ណាមួយដែលអ្នកប្រើ។
Bias។ ប្រសិនបើទិន្នន័យមានគំរូអគតិ ឬតំណាងភាគច្រើនដល់មនុស្ស ភាសា និងទស្សនៈខ្លះ model ស្រូបយកវា។ អត្ថបទជាភាសាអង់គ្លេសមានច្រើនជាងអត្ថបទជាភាសាខ្មែរនៅលើអ៊ីនធឺណិត ដូច្នេះ model ច្រើនខ្លាំងជាងគេក្នុងភាសាអង់គ្លេស ហើយខ្សោយជាងសម្រាប់ភាសាតូចៗ។ ប្រសិនបើអ្នកសាងសង់សម្រាប់អ្នកនិយាយភាសាខ្មែរ សូមសាកល្បងជាមួយឧទាហរណ៍ខ្មែរពិត ហើយកុំសន្មតថាគុណភាពដែលអ្នកឃើញក្នុងភាសាអង់គ្លេសអាចយកមកប្រើបាន។
គ្មានអ្វីនៅទីនេះមានន័យថា "កុំប្រើ LLM" ទេ។ វាមានន័យថាចាត់ទុក model ដូចសហសេវិក ដែលអានច្រើនតែមិនអាចទុកចិត្តបាន ហើយអ្នកមើលមិនឃើញបញ្ជីសៀវភៅដែលគាត់អាន។
14. រូបមន្ត៖ Module train
បង្កើត src/train.js ក្នុង folder llmlab របស់អ្នក។ វាត្រូវការ src/sampling.js
ពី Probabilities, Temperature and Sampling
(សម្រាប់ softmax)។ ចាប់ផ្តើមឯកសារជាមួយ helper ពីរនេះ ហើយបន្ទាប់មកចម្លង
lossOf, step និង train ពីផ្នែកទី 5 ទៅខាងក្រោមវា (ហើយបន្ថែម export នៅមុខ
function នីមួយៗ)៖
// src/train.js
import { softmax } from "./sampling.js";
// Unique words, sorted, plus a word -> index lookup.
export function buildVocab(tokens) {
const vocab = [...new Set(tokens)].sort();
const index = new Map(vocab.map((w, i) => [w, i]));
return { vocab, index };
}
// Every (current word, next word) pair as two index numbers.
export function makePairs(tokens, index) {
const pairs = [];
for (let i = 0; i < tokens.length - 1; i++) {
pairs.push([index.get(tokens[i]), index.get(tokens[i + 1])]);
}
return pairs;
}
Export គឺ buildVocab(tokens), makePairs(tokens, index),
lossOf(logits, pairs), step(logits, pairs, lr) និង
train(tokens, { steps, lr, every })។ តក្កវិជ្ជាស្នូល (loss, step និង loop) មានតិចជាង
40 បន្ទាត់។ រក្សាទុក demo ណាមួយខាងលើជាឯកសារ demo-*.js នៅជាប់ src/
ហើយដំណើរការវាដោយ node demo-train.js។
15. សាកល្បងដោយខ្លួនឯង
- គូរខ្សែកោង។ បង្វឹក 2000 ជំហានជាមួយ
every: 100ហើយបោះពុម្ព loss រាល់ពេល។ តើខ្សែកោងរាបស្មើនៅត្រង់ណា? ប្រៀបធៀបជាមួយចំណុចទាបបំផុត1.0004ពីផ្នែកទី 7។ - ស្វែងរក learning rate។ ដំណើរការ 100 ជំហានជាមួយ
lrកំណត់ជា10,20,100,200,300។ នៅតម្លៃណា loss ឈប់ធ្លាក់ ហើយចាប់ផ្តើមអាក្រក់ជាង loss ចាប់ផ្តើម4.2047? ហេតុអ្វី? - ប្រយោគផ្សេង ទម្លាប់ផ្សេង។ ជំនួសអត្ថបទ corpus ដោយប្រយោគប្រាំអំពីជីវិតផ្ទាល់ខ្លួន
របស់អ្នក (ប្រើ
words()ពីsrc/corpus.js)។ បង្វឹក ហើយបោះពុម្ពការទាយកំពូលទាំងបួន បន្ទាប់ពីពាក្យទូទៅមួយ។ តើវាត្រូវនឹងអ្វីដែលអ្នកបានសរសេរទេ? - ធ្វើឲ្យ overfit។ បង្វឹកលើតែ 40 ពាក្យដំបូងនៃ corpus អស់ 2000 ជំហាន ហើយវាស់ loss លើពាក្យដែលនៅសល់ (ដូចក្នុងផ្នែកទី 9)។ តើមានគូដែលមិនធ្លាប់ឃើញប៉ុន្មានអាចប្រើបាន? តើ loss លើអត្ថបទដែលមិនធ្លាប់ឃើញខ្ពស់ជាង ឬទាបជាងមុន ហើយហេតុអ្វី?
- ប្រៀបធៀបជាមួយចំនួនរាប់។ បន្ទាប់ពីបង្វឹក គណនាមធ្យមភាគនៃភាពខុសគ្នាដាច់ខាតរវាង
ប្រូបាបដែលបានរៀន និងប្រូបាបដែលបានរាប់ (ពី
trainBigram) សម្រាប់ពាក្យដែលមាន ចំនួនរាប់។ តើវាថយចុះនៅពេលអ្នកបន្ថែមជំហានទេ?
16. សំណួរដែលអ្នកនឹងត្រូវគេសួរ
"ដូច្នេះអ្នកណាបង្រៀន model?" គ្មាននរណាបង្រៀនវាដូចគ្រូបង្រៀនសិស្សទេ។ កម្មវិធីមួយបង្ហាញអត្ថបទដល់វាម្តងហើយម្តងទៀត វាស់ថាការទាយរបស់វាខុសប៉ុនណា ហើយរុញលេខរបស់វាឲ្យខុសតិចជាងបន្តិច។ បន្ទាប់ពីការរុញ ចំនួនធំសម្បើម លេខទាំងនោះចាប់យកគំរូជាច្រើននៃអត្ថបទ។
"Parameter គឺជាអ្វី?" វាគឺជាលេខមួយដែលអាចកែបាននៅខាងក្នុង model។ Model ដែលមាន 7 ពាន់លាន parameter មានលេខបែបនោះ 7 ពាន់លាន។ រួមគ្នាវាកំណត់ពីរបៀបដែល model បំប្លែងអត្ថបទដែលវាអាន ទៅជាពិន្ទុសម្រាប់រាល់ token បន្ទាប់ដែលអាចមាន។ ការបង្វឹកគឺជាការស្វែងរកតម្លៃល្អ។
"ហេតុអ្វីការបង្វឹកថ្លៃខ្លាំង ប៉ុន្តែការប្រើ model ថោក?" ការបង្វឹកធ្វើនព្វន្ធរបស់ model លើអត្ថបទចំនួនសម្បើម ម្តងហើយម្តងទៀត ហើយក៏គណនា របៀបកែលម្អរាល់ parameter ផងដែរ។ ការប្រើ model គ្រាន់តែដំណើរការនព្វន្ធទៅមុខម្តង ក្នុងមួយ token។ ការបង្វឹកគឺជាថ្លៃតែម្តងដ៏ធំ ហើយរាល់សំណួរបន្ទាប់ពីនោះគឺជាចំណែកតូចមួយ។
"តើ model បន្តរៀនពីការជជែករបស់យើងទេ?" មិនមែនដោយខ្លួនឯងទេ។ ពេលអ្នកនិយាយ លេខរបស់វាត្រូវបានបង្កក។ វាអាចប្រើអ្វីដែលមាន ក្នុងការសន្ទនាជា context ដែលមានអារម្មណ៍ដូចអង្គចងចាំ ប៉ុន្តែវាដំណើរការខុសគ្នា ដូច ជំពូក context window ពន្យល់។ ក្រុមហ៊ុនអាចជ្រើសរើសប្រើការជជែកដើម្បីបង្វឹកកំណែ អនាគត ដែលជាសំណួរគោលនយោបាយដែលអ្នកអាចអានក្នុងលក្ខខណ្ឌរបស់ពួកគេ។
"តើវាស្របច្បាប់ទេក្នុងការបង្វឹកលើអត្ថបទរបស់អ្នកដទៃ?" វាមិនទាន់ដោះស្រាយ ហើយខុសគ្នាតាមប្រទេស៖ តុលាការ និងអ្នកបង្កើតច្បាប់នៅតែកំពុងដោះស្រាយ។ ចម្លើយល្អសម្រាប់ថ្នាក់រៀន៖ បច្ចេកវិទ្យាអាចធ្វើបាន ច្បាប់ និងក្រមសីលធម៌កំពុងតាមទាន់ ដូច្នេះសូមពិនិត្យអាជ្ញាប័ណ្ណ ហើយប្រុងប្រយ័ត្នអំពីអ្វីដែលអ្នកផ្សព្វផ្សាយ។
"ហេតុអ្វី model ល្អជាងជាភាសាអង់គ្លេសជាងភាសាខ្មែរ?" ភាគច្រើនព្រោះមានអត្ថបទភាសាអង់គ្លេសច្រើនជាងច្រើនសម្រាប់បង្វឹក ហើយ tokenizer ច្រើនត្រូវបានរចនាជុំវិញវា។ Model អាចរៀនតែគំរូដែលវាបានឃើញ។ គម្លាតកំពុងថយចុះក្នុង model ខ្លះ ប៉ុន្តែសូមសាកល្បងជាមួយឧទាហរណ៍ខ្មែរពិតមុនពេលអ្នកពឹងផ្អែកលើវា។
ទៅបន្តទៀត។ ឥឡូវនេះអ្នកបានឃើញ training loop ពេញលេញ៖ តារាងលេខ loss និងជំហាន
តូចៗចុះទៅក្រោម។ ប៉ុន្តែ model របស់យើងចាត់ទុក coffee និង tea ជាស្លាកពីរដែលមិន
ទាក់ទងគ្នា ដែលមិនមែនជារបៀបដែល model ពិតមើលពាក្យទេ។ បន្ទាប់ អ្នកនឹងឃើញរបៀបដែល
ពាក្យក្លាយជាបញ្ជីលេខ ដែល ពាក្យស្រដៀងគ្នាស្ថិតនៅជិតគ្នា និងរបៀបដែល model ឲ្យពាក្យ
មើលគ្នាទៅវិញទៅមក៖ Embeddings and Attention។
ទិញកាហ្វេជូនខ្ញុំ
ចូលចិត្តមេរៀននេះមែនទេ? សូមពិចារណាទិញកាហ្វេជូនខ្ញុំមួយកែវ ដើម្បីគាំទ្រការបង្កើតមាតិកាឥតគិតថ្លៃបន្ថែមទៀត!