درس ۲ از ۱۲، بخش ۱: مدل زبانی از درون

ترنسفورمر به زبان ساده

متنی ۳۰ دقیقه به‌روز شده در ۱۱ آبان ۱۴۰۵

در این درس
  1. قبل از ترنسفورمر: شبکه‌های بازگشتی
  2. «توجه تنها چیزی است که لازم دارید»
  3. ۱. توکن‌سازی: متن به عدد
  4. ۲. Embedding: عدد به بردار معنادار
  5. ۳. رمزگذاری جایگاه
  6. ۴. توجه به خود (Self-Attention)
  7. ۵. انکودر و دیکودر
  8. ۶. Softmax و تولید کلمه‌به‌کلمه
  9. مدل‌های امروزی: فقط دیکودر
  10. چرا این‌ها برای برنامه‌نویس مهم است؟
  11. خلاصه

تقریباً همه‌ی LLMهای معروف، از GPT و Gemini تا Claude و Qwen و DeepSeek، بر پایه‌ی معماری‌ای به نام ترنسفورمر (Transformer) ساخته شده‌اند. در این درس نمی‌خواهیم ترنسفورمر را از صفر پیاده کنیم؛ این کار در یک دوره‌ی یادگیری عمیق چند جلسه وقت می‌گیرد. هدف یک دید کلی است تا وقتی در ادامه از embedding، context، softmax یا توکن حرف می‌زنیم، بدانیم منظورمان چیست.

قبل از ترنسفورمر: شبکه‌های بازگشتی#

تا حدود ۲۰۱۷ برای داده‌های ترتیبی، مثل متن، سیگنال قلب یا قیمت سهام، از شبکه‌های عصبی بازگشتی (RNN) و نسخه‌های بهترشان یعنی LSTM و GRU استفاده می‌شد.

RNN یک حافظه‌ی داخلی (hidden state) دارد. اول کار این حافظه برداری از صفرهاست. شبکه کلمه‌ی اول را می‌خواند و حافظه به‌روز می‌شود. بعد کلمه‌ی دوم را می‌خواند و حافظه دوباره به‌روز می‌شود، و همین‌طور تا آخر. اندازه‌ی حافظه ثابت می‌ماند؛ فقط عددهای داخلش عوض می‌شوند. شبیه مغز ما که با خواندن کتاب بزرگ‌تر نمی‌شود، اما اطلاعات داخلش جابه‌جا می‌شود.

در جمله‌ی «the movie was not bad»، وقتی شبکه به «bad» می‌رسد هنوز «not» را در حافظه دارد و می‌فهمد منظور «بد» نیست.

RNNها چهار مشکل جدی داشتند:

  1. فراموشی. وقتی متن طولانی می‌شود، ابتدایش از یاد می‌رود. اگر مدل فراموش کند که در اول متن گفته‌ایم «شیر خراب بود»، جای خالیِ «طعم چای شیرم … بود» را به‌جای «بد» با «عالی» پر می‌کند.
  2. کم‌توجهی به کانتکست. کلمه‌ی «bank» در «I put my money in the bank» یعنی بانک و در «we sat on the river bank» یعنی کنار رودخانه. RNN معنی هر کلمه را بیشتر از روی کلمه‌های قبلی می‌سازد و کلمه‌های بعدی تقریباً اثری ندارند.
  3. سطحی بودن روابط. در «معلم به دانش‌آموز از روی کتاب درس داد»، کتاب مال کیست؟ فاعل کیست و مفعول کیست؟ RNN این روابط را به‌خوبی درنمی‌آورد.
  4. پردازش ترتیبی. تا کلمه‌ی اول پردازش نشود نمی‌شود سراغ دومی رفت، و تا ده‌هزارمی پردازش نشود نمی‌شود ده‌هزار و یکمی را دید. این گلوگاه مانع می‌شود که مدل را روی کل اینترنت آموزش بدهیم یا متن ورودی طولانی به آن بدهیم.
پردازش ترتیبی RNN در برابر پردازش موازی ترنسفورمرRNN: کلمه‌به‌کلمه؛ هر قدم منتظر قدم قبلیtheh1movieh2wash3noth4badh5حافظه (h) در هر قدم به‌روز می‌شود و ابتدای متن‌های بلند کم‌کم فراموش می‌شودترنسفورمر: همه‌ی توکن‌ها هم‌زمان؛ هر توکن به همه‌ی توکن‌ها توجه می‌کندthemoviewasnotbadself-attention (چندسر)
بالا: RNN کلمه‌به‌کلمه جلو می‌رود. پایین: ترنسفورمر همه‌ی توکن‌ها را هم‌زمان می‌بیند و هر توکن به بقیه توجه می‌کند.

«توجه تنها چیزی است که لازم دارید»#

در ۲۰۱۷ گروهی از پژوهشگران گوگل مقاله‌ای با عنوان Attention Is All You Need منتشر کردند که برای ترجمه‌ی ماشینی نوشته شده بود. اگر یادتان باشد، تا مدتی «مثل گوگل ترنسلیت حرف زدن» مسخره‌ی رایجی بود. از یک سال به بعد کیفیت ترجمه‌ی گوگل ناگهان خیلی بهتر شد و دلیلش همین معماری بود.

ترنسفورمر هر چهار مشکل را حل کرد:

  • پردازش موازی: همه‌ی کلمه‌ها هم‌زمان پردازش می‌شوند و کار بین چند سخت‌افزار تقسیم می‌شود. نتیجه، مقیاس‌پذیری است: آموزش روی داده‌ی عظیم و ورودی‌های طولانی ممکن شد.
  • توجه به کانتکست: معنی هر کلمه با کلمه‌های اطرافش، چه قبل و چه بعد، غنی می‌شود.
  • روابط بین کلمات: هر کلمه به همه‌ی کلمه‌های دیگر توجه می‌کند، آن هم از چند جنبه‌ی مختلف.

حالا قدم‌به‌قدم ببینیم یک جمله در ترنسفورمر چه مسیری را طی می‌کند.

۱. توکن‌سازی: متن به عدد#

مدل ریاضی است و «کلمه» برایش معنا ندارد. پس متن اول به تکه‌های کوچک‌تری به نام توکن شکسته می‌شود. بسته به توکنایزر، یک توکن ممکن است یک کلمه باشد، بخشی از کلمه یا حتی یک کاراکتر. هر توکن یک شماره دارد:

text: "من عاشق یادگیری ماشین هستم"
ids:  [512, 79, 912, 32, 698]

این شماره‌ها قراردادیاند. ۳۴۲ هیچ شباهتی به ۳۴۳ ندارد. مثل این است که از روز تولد یک بچه تا سی‌سالگی‌اش به بالش بگوییم «فیثاغورث». او هم از آن به بعد «فیثاغورث» را به معنای بالش می‌فهمد. شبکه هم معنی هر شماره را در طول آموزش یاد می‌گیرد.

۲. Embedding: عدد به بردار معنادار#

چون شماره‌ها خودشان معنایی ندارند، هر توکن به یک بردار تبدیل می‌شود، مثلاً بردار ۵۱۲تایی از اعداد اعشاری. عدد ۵۱۲ را مقاله‌ی اصلی انتخاب کرده و یک ابرپارامتر است؛ می‌توانید ۱۰۰ یا ۴۰۹۶ هم بگذارید. به این کار embedding (تعبیه کردن) می‌گویند.

جادوی embedding این است که وقتی شبکه روی داده‌ی زیاد آموزش ببیند، کلمه‌های هم‌معنی یا هم‌کاربرد بردارهای نزدیک به هم پیدا می‌کنند و کلمه‌های بی‌ربط از هم دور می‌شوند:

  • he و she نزدیک هم‌اند (هر دو در فارسی «او» می‌شوند). eat و drink هم همین‌طور.
  • man و woman، و king و queen، نزدیک هم‌اند. dog و cat و fish هم کنار هم‌اند.
  • در سطحی بالاتر، همه‌ی این‌ها «موجود زنده» هستند و از عدد و میوه و ابزار دورترند.
  • «کیف» و «دایناسور» تقریباً هیچ ربطی به هم ندارند.

حتی می‌شود نشان داد که چند بعد از این بردار با هم چیزی مثل جنسیت، مثبت یا منفی بودن یا صفت تفضیلی بودن را رمز کرده‌اند. همین ایده بعدها در RAG و پایگاه‌داده‌های برداری مستقیم به کارمان می‌آید.

۳. رمزگذاری جایگاه#

ترنسفورمر همه‌ی کلمه‌ها را هم‌زمان می‌بیند، پس ترتیب را خودبه‌خود نمی‌فهمد. «علی به زهرا گل داد» و «زهرا به علی گل داد» برایش یک کیسه از کلمه‌های یکسان است.

راه‌حل position embedding است: برای هر جایگاه (اول، دوم، سوم …) هم یک بردار ۵۱۲تایی قابل‌آموزش در نظر می‌گیریم و آن را با بردار خود کلمه جمع می‌کنیم. حالا «علی» در جایگاه اول با «علی» در جایگاه سوم فرق دارد.

۴. توجه به خود (Self-Attention)#

در این مرحله هر کلمه به همه‌ی کلمه‌های دیگر جمله نگاه می‌کند و بردار خودش را بر اساس آن‌ها به‌روز می‌کند. کلمه‌ی «شیر» را در سه جمله ببینید:

جمله «شیر» بعد از توجه به کانتکست به چه نزدیک می‌شود؟
یک لیوان شیر از یخچال برداشتم نوشیدنی، milk
شیر آب را باز کردم لوله‌کشی، faucet
در جنگل یک شیر به ما حمله کرد حیوان، lion

بردار اولیه‌ی «شیر» در هر سه جمله یکی است. بعد از self-attention، هر کدام معنای مخصوص کانتکست خودش را پیدا می‌کند. در «من عاشق یادگیری ماشین هستم» هم «ماشین» با توجه به «یادگیری» می‌فهمد منظور خودرو نیست.

چند سر توجه#

زبان جنبه‌های زیادی دارد: فاعل و فعل، مالکیت، منفی کردن، اینکه یک قید یا صفت مربوط به کدام کلمه است، مفرد یا جمع بودن و …. یک توجه برای همه‌ی این‌ها کافی نیست. برای همین ترنسفورمر چند سر توجه (attention head) موازی دارد که هر کدام یک نوع رابطه را یاد می‌گیرد. به این Multi-Head Attention می‌گویند.

این روابط به‌صورت دستی برنامه‌نویسی نمی‌شوند. شبکه خودش از داده یادشان می‌گیرد. وقتی بعداً یک مدل آموزش‌دیده را بررسی می‌کنند، می‌بینند یک سر یاد گرفته «not» چه چیزی را منفی کرده و سر دیگری یاد گرفته هر قید به کدام فعل مربوط است.

بعد از توجه، بردارها از چند لایه‌ی تمام‌متصل (fully connected) هم رد می‌شوند تا پردازش غیرخطی و عمیق‌تری رویشان انجام شود. کل این بلوک، یعنی توجه به‌اضافه‌ی لایه‌های تمام‌متصل، چندین بار پشت سر هم تکرار می‌شود.

۵. انکودر و دیکودر#

مقاله‌ی اصلی برای ترجمه بود و دو بخش داشت:

  • انکودر (encoder) زبان مبدأ را کامل «هضم» می‌کند. بدون فهم کامل جمله نمی‌شود ترجمه کرد؛ کسی که زبانش ضعیف است حتی با دیکشنری هم ترجمه‌ی خوبی نمی‌کند.
  • دیکودر (decoder) زبان مقصد را کلمه‌به‌کلمه تولید می‌کند و دو نوع توجه دارد:
    • cross-attention: هنگام تولید هر کلمه به جمله‌ی مبدأ نگاه می‌کند. مترجم هم نمی‌تواند پاراگراف انگلیسی را بعد از خواندن کنار بگذارد؛ تاریخ‌ها و اسم‌ها را باید دوباره نگاه کند.
    • masked self-attention: به کلمه‌هایی که خودش تا الان تولید کرده نگاه می‌کند تا ترجمه یکدست بماند. «masked» یعنی فقط قبلی‌ها را می‌بیند، نه آینده را.

۶. Softmax و تولید کلمه‌به‌کلمه#

خروجی دیکودر در هر قدم یک توزیع احتمال روی کل واژگان است. اگر مدل ۱۵۰ هزار توکن بشناسد، ۱۵۰ هزار احتمال برمی‌گرداند که جمعشان یک می‌شود. به لایه‌ای که این احتمال‌ها را می‌سازد softmax می‌گویند.

فرض کنید می‌خواهیم «من عاشق یادگیری ماشین هستم» را ترجمه کنیم:

  1. انکودر پنج بردار غنی‌شده برای پنج توکن تولید می‌کند.
  2. به دیکودر یک توکن ویژه‌ی «شروع» می‌دهیم.
  3. دیکودر با cross-attention به آن پنج بردار نگاه می‌کند و برای اولین کلمه احتمال حساب می‌کند. محتمل‌ترین گزینه «I» است.
  4. «I» به ورودی دیکودر اضافه می‌شود و دوباره همین کار تکرار می‌شود: «I love» …
  5. این حلقه ادامه پیدا می‌کند تا توکن ویژه‌ی «پایان» تولید شود.

به این شیوه‌ی تولید، که هر خروجی ورودی قدم بعد می‌شود، خودبازگشتی (autoregressive) می‌گویند.

مدل‌های امروزی: فقط دیکودر#

ChatGPT، Gemini، Claude، Grok، Qwen، Gemma و DeepSeek همه فقط دیکودر (decoder-only) هستند. انکودر جداگانه‌ای ندارند. سؤال شما و جوابی که تا الان تولید شده، همه یک دنباله‌ی واحد است و مدل فقط پیش‌بینی می‌کند توکن بعدی چیست. البته استثنا هم هست؛ مثلاً مدل‌هایی که به‌جای ترنسفورمر از معماری diffusion استفاده می‌کنند.

مسیر یک جمله در مدل فقط‌دیکودر تا تولید توکن بعدیمتن ورودی«پایتخت ایران کجاست؟»توکن‌سازیهر تکه‌ی متن یک شماره می‌گیرد: 2, 105, 2364, …Embedding + Positionهر توکن ← بردار مثلاً ۵۱۲تایی، به‌اضافه‌ی بردار جایگاهSelf-Attention چندسرهر توکن به توکن‌های قبلی نگاه می‌کند و معنایش غنی می‌شودلایه‌های تمام‌متصل (× N بلوک)پردازش غیرخطی؛ این دو مرحله ده‌ها بار تکرار می‌شوندSoftmax روی کل واژگانبرای هر توکن ممکن یک احتمال: تهران ۰٫۹۱، شهر ۰٫۰۴، …انتخاب توکن بعدی ← «تهران»توکن جدیدبه ورودیاضافه می‌شود(خودبازگشتی)
یک قدم تولید در مدل فقط‌دیکودر. توکن انتخاب‌شده به ورودی اضافه می‌شود و حلقه تکرار می‌شود.

چرا این‌ها برای برنامه‌نویس مهم است؟#

  • هزینه و سقف ورودی بر حسب توکن است، نه کلمه. در درس بعد می‌بینیم فارسی معمولاً توکن بیشتری مصرف می‌کند.
  • مدل محتمل‌ترین ادامه را تولید می‌کند، نه درست‌ترین را. ریشه‌ی «توهم» همین‌جاست و در بخش مهندسی پرامپت راه‌های کم کردنش را می‌بینیم.
  • embedding پایه‌ی جستجوی معنایی و RAG است.
  • چون تولید توکن‌به‌توکن است، می‌شود پاسخ را هم‌زمان با تولید نمایش داد (streaming). این را در درس‌های Ollama و LiteLLM پیاده می‌کنیم.

خلاصه#

  • RNN متن را ترتیبی می‌خواند، فراموش می‌کند، کانتکست را کم می‌بیند و مقیاس‌پذیر نیست.
  • ترنسفورمر: توکن ← embedding + جایگاه ← self-attention چندسر و لایه‌های تمام‌متصل (چند بار) ← softmax روی واژگان.
  • تولید متن خودبازگشتی است: هر توکن جدید به ورودی اضافه می‌شود.
  • LLMهای امروزی تقریباً همه فقط دیکودرند.