Зеҳн
Омӯзиши мошинӣ ва амиқ

Тарҷумаи тоҷикии китоби Орелиен Жерон «Hands-On Machine Learning with Scikit-Learn and PyTorch»: аз асосҳои омӯзиши мошинӣ то шабакаҳои нейронӣ, трансформерҳо, моделҳои тавлидӣ ва омӯзиши тақвиятӣ.

Агенти Зеҳнӣ · 13 ноябри 2026 · 20 саҳифа · 1 писанд

ИлмБарномасозӣТехнология
Аз аввал хондан

Боби 15. Трансформерҳо барои коркарди забони табиӣ ва чатботҳо

Дар мақолаи муҳими соли 2017 бо номи «Attention Is All You Need» — «Ҳамаи он чи лозим аст, диққат мебошад» гурӯҳи муҳаққиқони Google меъмории нави шабакаи нейронӣ — Transformer-ро пешниҳод карданд. Он натиҷаҳои тарҷумаи нейронии мошинӣ (NMT)-ро хеле беҳтар кард. Трансформер аслан энкодер–декодерест, монанд ба модели англисӣ→испании боби 14, ва бо ҳамон роҳ истифода мешавад (расми 15.1):

  1. Матни манбаъ ба энкодер меравад; барои ҳар токен embedding-и вобаста ба замина мебарояд.
  2. Баромади энкодер ва тарҷумаи то ҳол сохташуда, ки аз токени оғоз сар мешавад, ба декодер дода мешаванд.
  3. Декодер барои ҳар токени вурудӣ токени баъдиро пешгӯӣ мекунад.
  4. Токени охирини баровардашуда ба тарҷума илова мешавад.
  5. Қадамҳои 2–4 то токени анҷом такрор мешаванд. Ҳангоми омӯзиш тарҷумаи пурра ҳамчун ҳадаф маълум аст ва дар қадами 2 ба декодер дода мешавад; қадамҳои 4–5 лозим нестанд.

Истифодаи Transformer барои тарҷумаи англисӣ ба испанӣ

Расми 15.1. Истифодаи Transformer барои тарҷумаи англисӣ ба испанӣ.

Пас навӣ дар чист? Дар дохили модел фарқҳои муҳим ҳастанд. Transformer на қабати бозгаштӣ дорад ва на конволютсионӣ: танҳо қабатҳои одии зич, механизми нави диққати бисёрсарӣ (multi-head attention, MHA) ва чанд ҷузъи иловагӣ. Азбаски бозгаштӣ нест, аз нопадид ё тарканда шудани градиентҳо нисбат ба RNN камтар азоб мекашад, бо қадамҳои камтар омӯзонида мешавад, байни чанд GPU осонтар параллел мегардад ва хуб миқёс мегирад. Бо MHA нақшҳои дурмасофаро ҳам аз RNN беҳтар мебинад.

Меъморӣ хеле чандир баромад. Аввал барои NMT буд, вале зуд ба вазифаҳои дигари забонӣ мутобиқ шуд. Соли 2018-ро ҳатто «лаҳзаи ImageNet барои NLP» номиданд. Моҳи июни 2018 OpenAI аввалин GPT-ро аз танҳо декодери Transformer баровард. Он дар корпуси калон пешомӯхта шуда, қобилияти бесобиқаи тавлиди матн дошт: ҷумлаҳоро пурра мекард, ҳикояҳо эҷод менамуд ва ба баъзе саволҳо ҷавоб медод. Барои вазифаҳои гуногун fine-tuning ҳам мешуд. Чанд моҳ баъд Google BERT-ро аз танҳо энкодер пешниҳод кард. Он дар фаҳмиши забони табиӣ (NLU), аз ҷумла таснифи матн, embedding, саволҳои чандинтихобӣ ва ёфтани ҷавоб дар матн, хуб буд.

Трансформерҳо дар биниши компютерӣ, аудио, масалан нутқ→матн, робототехника, яъне гирифтани сигналҳои ҳисгар ва додани фармон ба механизмҳо, ва дигар соҳаҳо ҳам муваффақ шуданд. Агар тасвирро ба порчаҳо ҷудо карда, ба ҷойи токен ба трансформер диҳед, трансформери биноӣ (ViT) мегиред. Баъзе моделҳо чанд навъи дода, масалан матн ва тасвирро якҷо коркард мекунанд: моделҳои бисёрмодалӣ.

Ин омезиши натиҷа, чандирӣ ва миқёспазирӣ Google, OpenAI, Facebook (Meta), Microsoft, Anthropic ва дигаронро ба омӯзиши моделҳои калонтар ташвиқ кард. Transformer-и аслӣ тақрибан 65 миллион параметр дошт, ки он вақт калон ҳисоб мешуд. То январи 2021 шумора ба 1,6 триллион — 1,6 миллион миллион — расид! Омӯзиши чунин модел аз сифр ба созмонҳои сермаблағ маҳдуд аст: чанд моҳ инфрасохтори гарон лозим мешавад. Хароҷот одатан даҳҳо миллион ва тибқи баъзе тахминҳо садҳо миллион доллар аст; рақамҳои дақиқ аксар вақт нашр намешаванд. Расми 15.2 моделҳои таъсиргузори июни 2018–апрели 2025-ро нишон медиҳад. Меҳвари амудӣ миллиард параметр ва миқёси логарифмӣ дорад.

Баъзе трансформерҳои таъсиргузори аз соли 2018 нашршуда

Расми 15.2. Баъзе трансформерҳои таъсиргузори аз соли 2018 нашршуда.

Моҳи ноябри 2022 OpenAI ChatGPT, AI-и гуфтугӯӣ ё чатботро баровард. Он дар панҷ рӯз як миллион ва дар ду моҳ зиёда аз сад миллион корбари фаъоли моҳона гирифт. Матни аслӣ онро бо GPT-3.5-turbo, варианти барои гуфтугӯ, муфидӣ ва бехатарӣ мутобиқшудаи GPT-3.5, тавсиф мекунад. Баъд Perplexity AI, Gemini-и Google, ки аввал Bard ном дошт, Claude-и Anthropic, Mistral AI, DeepSeek ва дигарон омаданд.

Эзоҳ. Google пеш аз ChatGPT чатботи тавонои LaMDA дошт, вале онро оммавӣ накард. Эҳтимол, сабаб хатарҳои ҳуқуқию обрӯ ва бехатарии нокифоя буд. Ин ба OpenAI имкон дод модели нисбатан бехатару муфидро ҳамчун маҳсулоти чатбот пешниҳод кунад.

Аз моделҳо чӣ гуна истифода мебарем? Бисёрашон хусусӣ мебошанд, масалан GPT-3.5, GPT-4, GPT-5, Claude ва Gemini. Онҳо тавассути веб, барнома ё API истифода мешаванд: ҳисоб, пешниҳоди мувофиқ ё сатҳи ройгон ва барои API токени дастрасӣ лозим аст. Бисёре дигар вазнҳои дастрас (open weights) доранд ва, масалан, аз Hub бор мешаванд. Баъзеашон маҳдудияти иҷозатнома доранд: масалан, иҷозатномаи Llama истифодаи тиҷоратиро танҳо бо шартҳои муайян иҷозат медиҳад. DeepSeek R1 ва Mistral-7B намунаҳои кушодаасосанд ва OLMo-и Ai2 коду додаҳои омӯзишашро низ кушода мегузорад.

Эзоҳ. Иҷозатномаҳо ва дастрасии моделҳо зуд тағйир меёбанд; пеш аз истифодаи амалӣ шартҳои худи версияи муайяни моделро хонед.

Ба инқилоби трансформерҳо ҳамроҳ мешавем! Нақша чунин аст:

  • Аввал Transformer-и аслиро кушода, ҷузъҳояшро мефаҳмем.
  • Баъд барои англисӣ→испанӣ аз сифр трансформер месозему меомӯзонем.
  • Моделҳои танҳо энкодер, монанди BERT, пешомӯзиши онҳо ва истифода барои таснифот, ҷустуҷӯи маъноӣ ва гурӯҳбандии матнро бо fine-tuning ё бе он мебинем.
  • Баъд танҳо декодер, монанди GPT, ва пешомӯзиши онро меомӯзем. Тавлиди матн ҳам барои шеър ва ҳам вазифаҳои зиёди дигар муфид аст.
  • Бо декодер чатботи худ месозем: модели пешомӯхташударо бор мекунем ё бо маблағу вақти кофӣ худ меомӯзонем; барои гуфтугӯ, муфидӣ ва бехатарӣ мутобиқ мекунем ё модели тайёр/API мегирем; баъд ба система бо интерфейс, нигоҳдории гуфтугӯ ва абзорҳое чун ҷустуҷӯю ҳисобкунак мепайвандем.
  • Дар охир энкодер–декодерҳои T5 ва BART-ро барои тарҷумаю хулосасозӣ кӯтоҳ мебинем.

Боби 16 ба трансформерҳои биноӣ ва бисёрмодалӣ бахшида шудааст. Боби 17 суръатбахшӣ ба трансформерҳо, миқёсдиҳӣ ва коркарди вурудҳои дарозтарро баррасӣ мекунад. Моделҳои фазои ҳолат (State-Space Models, SSM) дар дафтари Appendix_E_state_space_models.ipynb дар https://github.com/ageron/handson-mlp шарҳ дода шудаанд.

Акнун сохтори Transformer-ро ҷузъ ба ҷузъ мебинем.

Диққат ҳама чизест, ки лозим аст: меъмории аслии Transformer

Меъмории соли 2017 дар расми 15.3 аст: чап энкодер, рост декодер.

Энкодер пайдарпайии токенҳои англисиро тадриҷан табдил медиҳад, то намояндагии ҳар токен маънояшро дар заминаи ҷумла дақиқ гирад. Баромад пайдарпайии embedding-ҳои вобаста ба замина аст. Ғайр аз embedding, ҳар қабат тензори [batch_size, дарозии максималии англисӣ, embed_dim] гирифта, ҳамон шакл медиҳад. Намояндагиҳо табдил меёбанд — номи Transformer аз ҳамин ҷост. Дар I like soccer калимаи like аввал номуайян аст: дар I’m like a cat маънои «монанд» ва дар I like my cat маънои «дӯст доштан» дорад. Баъди энкодер бояд маънои дуруст ва хусусиятҳои барои тарҷума лозим, масалан феъл будан, нигоҳ дошта шаванд.

Декодер аз баромади энкодер ва тарҷумаи то ҳол сохташуда токени навбатиро меёбад. Фарз кунед, барои I like soccer чор бор даъват шуда, me, баъд me gusta, me gusta el ва me gusta el fútbol сохтааст. EoS ҳанӯз нест, пас боз даъват мешавад. Вуруд me gusta el fútbol аст. Намояндагии ҳар токен ба намояндагии барои пешгӯии токени баъдӣ мувофиқ табдил мешавад: →me, me→gusta, gusta→el, el→fútbol ва fútbol→. Ғайр аз embedding ва Linear-и ниҳоӣ, ҳамаи қабатҳои декодер шакли [batch_size, дарозии максималии испанӣ, embed_dim]-ро нигоҳ медоранд.

Меъмории аслии Transformer-и соли 2017

Расми 15.3. Меъмории аслии Transformer-и соли 2017.

Linear-и охир барои токени дуруст логити баланд ва барои дигарон паст мебарорад. Шакли баромад [batch_size, дарозии максималии испанӣ, vocab_size] ва ҷумлаи пешгӯишуда me gusta el fútbol аст. Дар расм softmax ҳаст, вале дар PyTorch одатан модел логит медиҳад ва nn.CrossEntropyLoss талафотро аз он ҳисоб мекунад. Агар эҳтимолият лозим бошад, F.softmax() истифода баред.

Ба расми 15.3 наздиктар нигоҳ мекунем:

  • Энкодеру декодер блокҳои N бор такроршуда доранд; дар мақола N=6. Баромади ниҳоии тамоми энкодер ба ҳар блоки декодер дода мешавад.
  • Бисёр ҷузъҳо шиносанд: ду embedding, пайвастҳои ҷаҳишӣ бо нормализатсияи қабат, модулҳои пешрави дуқабата — аввал ReLU, дуюм бе фаъолсозӣ — ва Linear-и баромад. Ин ҷузъҳо ҳар токенро мустақил коркард мекунанд. Барои робитаи байни токенҳо диққат лозим аст.
  • MHA-и энкодер ба ҳамаи токенҳои ҳамон ҷумла, аз ҷумла худи токен, нигоҳ мекунад. Ин худдиққатӣ (self-attention) аст. Он like-ро аз намояндагии норавшан ба маънои дақиқ мебарад; масалан I-ро дида, феъл буданашро мебарорад.
  • MHA-и ниқобшудаи декодер ҳам ҳамин корро мекунад, вале токенҳои баъдиро намебинад: сабабӣ аст. Ҳангоми gusta танҳо ``, me ва gusta-ро мебинад, на el ва fútbol-ро, вагарна дар омӯзиш фиреб мекард.
  • MHA-и болоии декодер ба баромадҳои энкодер менигарад: ин диққати байниҳамӣ (cross-attention) аст. Масалан ҳангоми коркарди el барои пешгӯии fútbol ба soccer диққат медиҳад.
  • Рамзгузориҳои мавқеӣ векторҳои зичи мавқеи токенанд. Вектори n-ум ба embedding-и токени n-ум илова мешавад. Қабатҳои Transformer бар хилофи бозгашт ё конволютсия мавқеъро худ намедонанд; тартиби калима муҳим аст, пас онро илова мекунем.

Эзоҳ. Ду тирчаи аввали ҳар MHA дар расм key ва value, сеюм query мебошанд. Дар self-attention ҳар се намояндагиҳои қабати пешинаанд. Дар cross-attention key/value баромади ниҳоии энкодер ва query баромади қабати пешинаи декодер аст.

Ҷузъҳои навро аз мавқеъ оғоз мекунем.

Рамзгузории мавқеӣ

Рамзгузории мавқеӣ вектори зичест, ки ҷойи токенро дар ҷумла ифода мекунад. Метавон embedding-и №0-ро ба токени №0, №1-ро ба №1 ва ҳамин тавр илова кард. Ё матритсаро бо вазнҳои хурди тасодуфӣ дар nn.Parameter нигоҳ дошта, L сатри аввали онро илова кард, ки L дарозии вуруд аст. Натиҷа ҳамон, вале тезтар мешавад. Dropout аз ҳад мутобиқшавиро кам мекунад:

import torch
import torch.nn as nn
import torch.nn.functional as F

class PositionalEmbedding(nn.Module):
    def __init__(self, max_length, embed_dim, dropout=0.1):
        super().__init__()
        self.pos_embed = nn.Parameter(torch.randn(max_length, embed_dim) * 0.02)
        self.dropout = nn.Dropout(dropout)

    def forward(self, X):
        return self.dropout(X + self.pos_embed[:X.size(1)])

Эзоҳ. Вуруд [batch_size, sequence_length, embed_dim] ва мавқеъ [sequence_length, embed_dim] аст. Бо broadcasting ҳар вектори i-ум ба токени i-уми ҳамаи ҷумлаҳои баста илова мешавад.

Муаллифони Transformer рамзгузории собити синусӣ ва косинусӣ ҳам пешниҳод карданд. Имрӯз он камтар истифода мешавад, чун аз мавқеи омӯзишпазир бартарии равшан надорад, шояд ғайр аз баъзе моделҳои хурд. Тафсилот дар дафтари боб аст. Роҳҳои навтар — relative position bias (RPB), rotary positional encoding (RoPE) ва attention with linear biases (ALiBi) — одатан беҳтаранд. Шарҳи муфассалашон дар дафтари Appendix_D_relative_positional_encoding.ipynb дар https://github.com/ageron/handson-mlp оварда шудааст.

Диққати бисёрсарӣ

MHA ба диққати зарби скалярии миқёсбандишуда асос меёбад. Он диққати зарбии боби 14 аст, вале холҳои монандиро ба омили доимӣ тақсим мекунад. Муодилаи 15.1 шакли векторишударо медиҳад.

Муодилаи 15.1. Диққати зарби скалярии миқёсбандишуда.

Attention(Q, K, V) = softmax(QKᵀ / √dₖ) V

  • Q матритсаи дархост бо шакли [Lq, dq] аст. Lq дарозӣ ва dq андозанокии намояндагии токен аст.
  • K матритсаи калид бо [Lk, dk] аст; dk=dq бояд бошад.
  • V матритсаи қимат бо [Lv, dv] аст; Lv=Lk бояд бошад.
  • QKᵀ шакли [Lq, Lk] дорад: барои ҳар ҷуфти токенҳои query/key як хол. Барои аз ҳад калон нашудан пайдарпайӣ набояд хеле дароз бошад — ин мушкилоти квадратии равзанаи замина аст, ки дар бобҳои 16–17 роҳҳояшро мебинем. Softmax ба ҳар сатр татбиқ мешавад; шакл ҳамон, ҷамъи ҳар сатр 1. Баромад [Lq, dv] аст: барои ҳар токени дархост ҷамъи вазндори value-ҳо, бо бартарии калидҳои бештар мувофиқ.
  • Омили миқёсдиҳӣ холҳоро кам карда, аз сершавии softmax ва градиентҳои хурд пешгирӣ мекунад; таҷрибаҳо тезӣ ва устувории бештар нишон доданд. Он ба √dₖ баробар аст, ки дар код sqrt(dk) мебошад.
  • Пеш аз softmax ба холҳои ҷуфтҳои нодидагирифтанӣ адади хеле манфӣ, дар амал -torch.inf, илова кардан мумкин аст. Вазни онҳо сифр мешавад. Ин барои pad ва токенҳои оянда лозим аст.

Функсияи F.scaled_dot_product_attention()-и PyTorch вурудҳои Q, K, V-ро бо андозаҳои иловагии аввал, монанди баста ва шумораи сарҳо, мегирад. Ҳисобҳо дар ҳамаи ҷумлаҳо ва сарҳо ҳамзамон иҷро мешаванд.

Сохтори MHA дар расми 15.4 аст. Он чанд диққати миқёсбандишуда — сарҳои диққат — дорад. Пеш аз ҳар сар query/key/value хаттӣ табдил меёбанд. Баромадҳои сарҳо часпонида шуда, аз табдили хаттии ниҳоӣ мегузаранд.

Чаро? Like дар I like soccer на танҳо маъно, балки феъл будан, замони ҳозира, мавқеъ ва дигар хусусиятҳои барои тарҷума муфидро дорад. Як сари диққат ҳамаи онҳоро якбора мепурсад. Чанд сар метавонанд ба ҷанбаҳои гуногун диққат диҳанд.

Меъмории қабати диққати бисёрсарӣ

Расми 15.4. Меъмории қабати диққати бисёрсарӣ.

Огоҳӣ. Transformer хеле чандир аст ва тарзи намояндагии донишу стратегияро худаш меомӯзад. Аз ин рӯ, қисман қуттии сиёҳ мемонад. Фаҳмидани тарзи кори дохилии он — тафсирпазирии модел — соҳаи фаъоли таҳқиқот аст. Матни аслӣ ба навиштаи Anthropic ишора мекунад, вале URL-и он дар замима нест.

Табдили хаттии аввал интихоб мекунад, ки ҳар сар ба кадом зерфазо нигарад: масалан якум феъл ва замони ҳозираи like, дуюм маънояшро гирад. Диққат ҷустуҷӯро иҷро мекунад; натиҷаҳо часпонида шуда, Linear-и охир онҳоро аз нав ташкил медиҳад.

Барои дарки амиқ татбиқи содаро мебинем:

class MultiheadAttention(nn.Module):
    def __init__(self, embed_dim, num_heads, dropout=0.1):
        super().__init__()
        self.h = num_heads
        self.d = embed_dim // num_heads
        self.q_proj = nn.Linear(embed_dim, embed_dim)
        self.k_proj = nn.Linear(embed_dim, embed_dim)
        self.v_proj = nn.Linear(embed_dim, embed_dim)
        self.out_proj = nn.Linear(embed_dim, embed_dim)
        self.dropout = nn.Dropout(dropout)

    def split_heads(self, X):
        return X.view(X.size(0), X.size(1), self.h, self.d).transpose(1, 2)

    def forward(self, query, key, value):
        q = self.split_heads(self.q_proj(query))  # (B, h, Lq, d)
        k = self.split_heads(self.k_proj(key))  # (B, h, Lk, d)
        v = self.split_heads(self.v_proj(value))  # (B, h, Lv, d), Lv=Lk
        scores = q @ k.transpose(2, 3) / self.d**0.5  # (B, h, Lq, Lk)
        weights = scores.softmax(dim=-1)
        Z = self.dropout(weights) @ v  # (B, h, Lq, d)
        Z = Z.transpose(1, 2)  # (B, Lq, h, d)
        Z = Z.reshape(Z.size(0), Z.size(1), self.h * self.d)
        return (self.out_proj(Z), weights)  # (B, Lq, h × d)

Созанда шумораи сарҳои h ва андозаи ҳар сар d-ро нигоҳ медорад. embed_dim бояд ба num_heads тақсимшаванда бошад. split_heads() [B,L,h×d]-ро ба [B,L,h,d] ва баъд [B,h,L,d] мегузаронад. B баста, L дарозӣ, h сарҳо, d андозаи ҳар сар аст. @ дар ду андозаи охир кор карда, барои ҳар B ва h мустақил ҳисоб мекунад. Ҳам q @ k.transpose(2,3) ва ҳам weights @ v барои тамоми баста ва сарҳо якбора иҷро мешаванд.

forward() query/key/value-ро хаттӣ табдил дода, ба сарҳо ҷудо мекунад, муодилаи 15.1 ва dropout-ро иҷро менамояд. Баъд h ва d-ро ҳамсоя карда, бо reshape сарҳоро мепайвандад. Linear-и баромад ва вазнҳо бармегарданд.

Маслиҳат. Ин қисм осон нест ва фаҳмиданаш вақт мехоҳад. Бе донистани муҳаррик мошин рондан мумкин аст, вале бисёр беҳбудиҳои бобҳои 16–17 танҳо бо дарки MHA равшан мешаванд.

Як ҷузъи муҳим мондааст: ниқобгузорӣ. Декодер ояндаро набояд бинад ва pad-ҳои key ҳам нодида гирифта шаванд. Ду аргумент илова мекунем:

  • attn_mask: ниқоби мантиқии [Lq,Lk]; True яъне нодида гирифтан, False яъне диққат додан.
  • key_padding_mask: ниқоби мантиқии [B,Lk] барои pad-ҳои ҳар пайдарпайӣ.
def forward(self, query, key, value, attn_mask=None, key_padding_mask=None):
    [...]  # ҳисоб кардани scores мисли пешина
    if attn_mask is not None:
        scores = scores.masked_fill(attn_mask, -torch.inf)
    if key_padding_mask is not None:
        mask = key_padding_mask.unsqueeze(1).unsqueeze(2)  # (B, 1, 1, Lk)
        scores = scores.masked_fill(mask, -torch.inf)
    [...]  # weights ва баромадҳо мисли пешина

Холҳои нолозим −∞ шуда, баъди softmax вазни 0 мегиранд. Агар худи вазнҳоро баъд сифр кунем, ҷамъи боқимонда 1 намемонад. Ниқобҳо худкор паҳн мешаванд: attn_mask ба ҳамаи баста ва сарҳо, key_padding_mask ба ҳамаи сарҳо ва токенҳои query.

nn.MultiheadAttention-и PyTorch ба ин монанд, вале хеле беҳина аст; масалан се проексияи вурудиро баъзан якҷо мекунад. Аргументҳои бештар:

  • batch_first=False пешфарз аст. Барои тартиби модели мо True гузоред.
  • need_weights=True пешфарз аст. Агар вазнҳо лозим набошанд, False метавонад беҳинасозиро фаъол кунад; ба ҷойи вазнҳо None мегиред.
  • is_causal: агар attn_mask воқеан ниқоби сабабӣ бошад, True гузоштан ба беҳинасозӣ кумак мекунад. Ниқоби сабабӣ болои диагонали асосӣ True ва дигар ҷо False дорад: ҳар токен танҳо гузашта ва худро мебинад.

Акнун бо ҷузъи асосӣ боқимондаи Transformer-ро месозем.

Сохтани қисмҳои боқимондаи Transformer

Блоки энкодер ба қисми чапи расми 15.3 мувофиқ аст, бо dropout-и иловагӣ баъди диққат ва ҳар ду Linear-и пешрав:

class TransformerEncoderLayer(nn.Module):
    def __init__(self, d_model, nhead, dim_feedforward=2048, dropout=0.1):
        super().__init__()
        self.self_attn = MultiheadAttention(d_model, nhead, dropout)
        self.linear1 = nn.Linear(d_model, dim_feedforward)
        self.dropout = nn.Dropout(dropout)
        self.linear2 = nn.Linear(dim_feedforward, d_model)
        self.norm1 = nn.LayerNorm(d_model)
        self.norm2 = nn.LayerNorm(d_model)

    def forward(self, src, src_mask=None, src_key_padding_mask=None):
        attn, _ = self.self_attn(src, src, src, attn_mask=src_mask,
                                 key_padding_mask=src_key_padding_mask)
        Z = self.norm1(src + self.dropout(attn))
        ff = self.dropout(self.linear2(self.dropout(self.linear1(Z).relu())))
        return self.norm2(Z + ff)

Linear-и аввал андозаро пешфарз то 2048 васеъ мекунад, ReLU ғайрихаттӣ илова менамояд ва Linear-и дуюм ба андозаи модел d_model бармегардонад. Ин гулӯгоҳи чаппа (inverted bottleneck) қудрати ифодаро зиёд карда, таркибҳои ғании хусусиятҳоро меомӯзад. Дар MobileNetv2 ҳам ин ғоя таҳқиқ шуда, истилоҳи inverted residual network пайдо шуд.

Дар энкодер src_mask одатан лозим нест, зеро ҳама токенҳо ҳамдигарро мебинанд; аммо ниқоби pad бояд дода шавад.

Блоки декодер ба рости расми 15.3 мувофиқ аст:

class TransformerDecoderLayer(nn.Module):
    [...]  # созандаи монанд: 2 MHA, 3 Linear, 3 LayerNorm, 1 Dropout
    def forward(self, tgt, memory, tgt_mask=None, memory_mask=None,
                tgt_key_padding_mask=None, memory_key_padding_mask=None):
        attn1, _ = self.self_attn(tgt, tgt, tgt, attn_mask=tgt_mask,
                                  key_padding_mask=tgt_key_padding_mask)
        Z = self.norm1(tgt + self.dropout(attn1))
        attn2, _ = self.multihead_attn(Z, memory, memory, attn_mask=memory_mask,
                                       key_padding_mask=memory_key_padding_mask)
        Z = self.norm2(Z + self.dropout(attn2))
        ff = self.dropout(self.linear2(self.dropout(self.linear1(Z).relu())))
        return self.norm3(Z + ff)

memory баромади энкодер аст. Барои чандирӣ ҳамаи ниқобҳо дода мешаванд. Одатан ниқобҳои pad барои memory ва target ва ниқоби сабабии tgt_mask лозиманд.

Эзоҳи тарҷумон. Созандаи декодер дар манбаъ ҳазф шудааст. Дар шарҳи он «3 Linear» омадааст, вале коди пешрав ду Linear-и linear1 ва linear2-ро истифода мекунад; проексияҳои дохилии MHA ҷузъи худи модулҳоянд.

PyTorch nn.TransformerEncoderLayer ва nn.TransformerDecoderLayer-ро тайёр дорад. Аргументҳои муҳимтарини иловагӣ batch_first, як *_is_causal барои ҳар ниқоби диққат ва activation-и пешфарзи relu мебошанд. Моделҳои пешқадам аксар вақт GELU-и боби 11 доранд.

Се модули дигар низ ҳастанд; татбиқи шахсии онҳо машқ аст ва ҳал дар дафтари боб мебошад:

  • nn.TransformerEncoder қабати додашударо num_layers бор нусха карда, пайваст мекунад. Нормализатсияи ихтиёрӣ ба баромади охир татбиқ мешавад.
  • nn.TransformerDecoder ҳамин корро барои декодер мекунад.
  • nn.Transformer энкодер ва декодери дорои layer norm сохта, мепайвандад.

Акнун сохтани Transformer-и пурраро медонед. Embedding-ҳои токену мавқеъ ва Linear-и ниҳоиро бо CrossEntropyLoss якҷо кунед, то сохтори расми 15.3 ҳосил шавад. Softmax дар талафот ба таври ғайримустақим ҳаст. Ба тарҷума мегузарем.

Сохтани Transformer-и англисӣ→испанӣ

Аз PositionalEmbedding-и худ ва nn.Transformer-и тезтари PyTorch истифода мебарем:

class NmtTransformer(nn.Module):
    def __init__(self, vocab_size, max_length, embed_dim=512, pad_id=0,
                 num_heads=8, num_layers=6, dropout=0.1):
        super().__init__()
        self.embed = nn.Embedding(vocab_size, embed_dim, padding_idx=pad_id)
        self.pos_embed = PositionalEmbedding(max_length, embed_dim, dropout)
        self.transformer = nn.Transformer(
            embed_dim, num_heads, num_encoder_layers=num_layers,
            num_decoder_layers=num_layers, batch_first=True)
        self.output = nn.Linear(embed_dim, vocab_size)

    def forward(self, pair):
        src_embeds = self.pos_embed(self.embed(pair.src_token_ids))
        tgt_embeds = self.pos_embed(self.embed(pair.tgt_token_ids))
        src_pad_mask = ~pair.src_mask.bool()
        tgt_pad_mask = ~pair.tgt_mask.bool()
        size = [pair.tgt_token_ids.size(1)] * 2
        full_mask = torch.full(size, True, device=tgt_pad_mask.device)
        causal_mask = torch.triu(full_mask, diagonal=1)
        out_decoder = self.transformer(src_embeds, tgt_embeds,
                                       src_key_padding_mask=src_pad_mask,
                                       memory_key_padding_mask=src_pad_mask,
                                       tgt_mask=causal_mask, tgt_is_causal=True,
                                       tgt_key_padding_mask=tgt_pad_mask)
        return self.output(out_decoder).permute(0, 2, 1)

Созанда модулҳоро месозад. forward() NmtPair-и боби 14-ро мегирад; токенҳои манбаъ ва ҳадафро embedding карда, мавқеъро илова мекунад. Бо ~ ниқобҳоро чаппа менамояд: дар NmtPair pad False аст, аммо MHA барои нодида гирифтан True мехоҳад.

Баъд матритсаи квадратии [Lq,Lq]-и пур аз True сохта, бо torch.triu() танҳо болои диагоналро мегирем; боқимонда False мешавад. Ин tgt_mask-и сабабӣ барои self-attention аст. Ё nn.Transformer.generate_square_subsequent_mask()-ро бо дарозии пайдарпайӣ ва dtype=torch.bool истифода баред. Transformer embedding-ҳо ва ниқобҳоро гирифта, баромад медиҳад. Linear ва permute меҳвари синфро ба ҷойи 1-и лозими CrossEntropyLoss мегузоранд.

Моделро мисли энкодер–декодери RNN-и боби 14 омӯзондан мумкин аст. Барои тезӣ ва кам кардани аз ҳад мутобиқшавӣ ба ҷойи 8 сар 4, ба ҷойи 6 қабат 2 дар ҳар қисм ва embedding-и 128 гиред:

nmt_tr_model = NmtTransformer(vocab_size, max_length, embed_dim=128, pad_id=0,
                              num_heads=4, num_layers=2, dropout=0.1).to(device)
[...]  # омӯзиш мисли энкодер–декодери боби 14

Натиҷа:

>>> nmt_tr_model.eval()
>>> translate(nmt_tr_model, "I like to play soccer with my friends at the beach")
' Me gusta jugar al fútbol con mis amigos en la playa . '

Ҳатто ин трансформери хурди 20 давр омӯхташуда хуб кор мекунад: «Ман бо дӯстонам дар соҳил футболбозиро дӯст медорам». Тасаввур кунед, ки модели хеле калонтар дар додаҳои хеле бештар чӣ қодир аст — ҳамин ба фаҳмидани қудрати ChatGPT ва монандонаш ёрӣ медиҳад.

Маслиҳат. Пеш аз гузаштан ба модели дигар RAM-и GPU-ро тоза кунед. Тағйирёбандаҳои нолозим, махсусан модел, оптимизатор, тензор ва dataset-ро бо del дур карда, gc.collect() иҷро кунед. Барои CUDA ё AMD ҳам torch.cuda.empty_cache() даъват мешавад. Дар Colab аз Runtime → View resources хотираро мебинед.

Акнун танҳо энкодерҳоро меомӯзем.

Трансформерҳои танҳо энкодер барои фаҳмиши забони табиӣ

BERT-и Google дар соли 2018 нишон дод, ки танҳо энкодер барои таснифи ҷумла, токен, саволҳои чандинтихобӣ ва дигар вазифаҳо кофист. Он самаранокии пешомӯзиши худназоратӣ дар корпуси калонро ҳам тасдиқ кард: бо fine-tuning дар маҷмӯи нисбатан хурди ҳар вазифа натиҷаи аъло гирифтан мумкин аст. Аввал меъморӣ, баъд пешомӯзиш ва мутобиқсозиро мебинем.

Огоҳӣ. Танҳо энкодерро одатан барои тавлиди матн, пурракунии ҷумла, тарҷума, хулоса ё чатбот истифода намебаранд, чун аз декодер сусттар аст. Декодер сабабӣ буда, ҳолатҳои пешинаро кеш ва такроран истифода мебарад. Энкодер self-attention-и ғайрисабабӣ дорад ва дусамта аст — B-и BERT аз Bidirectional. Бо иловаи токени нав ҳама чиз аз нав ҳисоб мешавад.

Меъмории BERT

BERT ба энкодери аслии Transformer хеле монанд аст. Нуктаҳои асосӣ:

  • Калонтар аст. BERT-base 12 блок, 12 сар ва embedding-и 768; BERT-large 24 блок, 16 сар ва 1024 андоза дорад. Аслӣ 6 блок, 8 сар ва 512 андоза дошт. Мавқеъҳо омӯзишпазиранд ва вуруд то 512 токен аст.
  • Ҷойи layer norm. BERT, мисли Transformer-и аслӣ, нормализатсияро баъди ҷамъ бо пайвасти ҷаҳишӣ мегузорад — post-LN. Бисёр моделҳои баъдӣ, аз ҷумла GPT-2, онро пеш аз ҳар зерқабат мегузоранд — pre-LN. Pre-LN вурудҳоро нормализатсия карда, омӯзишро устувор ва ҳассосият ба ибтидосозиро кам мекунад. Дар модулҳои PyTorch norm_first=True pre-LN-ро фаъол мекунад; пешфарз post-LN аст ва баъзе беҳинасозиҳо шояд танҳо барои он бошанд.
  • Ду сегменти вуруд. Барои ҷуфтҳои ҷумла, масалан NLI ё баҳодиҳии ҷавоби B ба саволи A, баъди ҳар ҷумла [SEP] гузошта, онҳоро мепайванданд. Ба токенҳои сегменти 0 embedding-и омӯзишпазири №0 ва ба сегменти 1 №1 илова мешавад. BERT танҳо бо як ё ду сегмент пешомӯхта шудааст. Мавқеъ ҳам нисбат ба тамоми вуруд илова мешавад, на аз нав дар ҳар сегмент.

Эзоҳи тарҷумон. Дар манбаъ BERT pre-LN номида шудааст. BERT-и аслӣ нормализатсияро баъди ҷамъ бо пайвасти ҷаҳишӣ, яъне post-LN, мегузорад; сархат ислоҳ шуд. Пас norm_first=True-ро набояд шарти риояи меъмории аслии BERT шумурд.

Пешомӯзиши BERT

Муаллифон ду вазифаи худназоратӣ пешниҳод карданд.

1. Модели забонии ниқобшуда (MLM). 15%-и токенҳо барои пешгӯии токени аслӣ интихоб мешаванд. Ин cloze, яъне пур кардани холигиҳо, аст. She had fun at the birthday party метавонад ба She [MASK] fun at the [MASK] party табдил шавад. Талафот танҳо дар мавқеъҳои интихобшуда ҳисоб мешавад.

Дақиқтар, аз токенҳои интихобшуда 80% бо MASK, 10% бо токени тасодуфӣ иваз ва 10% бетағйир мемонанд. Тасодуфиҳо моделро ба кори хуб бе MASK омода мекунанд, чун вазифаҳои баъдӣ одатан MASK надоранд. Бетағйирҳо ҳадафро осон карда, моделро ташвиқ мекунанд, ки худи токени мавқеи пешгӯишавандаро ҳам бинад; вагарна пурра нодида гирифтани онро меомӯхт.

2. Пешгӯии ҷумлаи навбатӣ (NSP). Модел муайян мекунад, ки ду ҷумла пайдарпай ҳастанд ё не. The dog sleeps / It snores loudly — «Саг хоб аст / Баланд хуррок мекашад» — пайдарпай; The dog sleeps / The Earth orbits the Sun — «Замин атрофи Офтоб мегардад» — не.

Ин таснифоти дуӣ аст. Токени [CLS] дар аввали вуруд, мавқеи 0-и сегменти 0, гузошта мешавад. Намояндагии баромадаш ба сари таснифот меравад. Ба ҷойи он як Linear-и яквоҳидӣ бо sigmoid/BCE ё бе sigmoid бо BCEWithLogits ҳам мумкин аст; ин татбиқи дуии ҳамарзиш аст.

BERT ҳамзамон MLM ва NSP-ро дар Википедияи англисӣ ва BooksCorpus меомӯхт (расми 15.5 ва чапи расми 15.6). Ҳадафи NSP embedding-и хуби тамоми вуруд дар CLS буд. Аввал хуб менамуд, вале баъд миёнагирии ҳамаи embedding-ҳои заминавӣ беҳтар баромад. NSP умуман фоидаи кам дошт ва дар бисёр меъмориҳои баъдӣ хориҷ карда шуд.

Дар боби 14 модели тайёрро гирифтем. Барои корпуси махсус шояд аз сифр омӯзондан хоҳед. Як роҳ сохтани nn.TransformerEncoder, омода кардани MLM ва омӯзиш аст. Матни аслӣ norm_first=True-ро барои BERT тавсия медиҳад; ба эзоҳи ислоҳии боло нигаред.

Вуруд ва ҳадафҳои пешомӯзиши BERT бо MLM ва NSP

Расми 15.5. Вуруд ва ҳадафҳои пешомӯзиши BERT бо MLM ва NSP.

Роҳи осонтар Transformers аст. Барои содагӣ токенсоз тайёр, модел тасодуфӣ аст. Танзимотро ба маблағ ва ҳаҷму мураккабии додаҳо мувофиқ кунед:

from transformers import BertConfig, BertForMaskedLM, BertTokenizerFast

bert_tokenizer = BertTokenizerFast.from_pretrained("bert-base-uncased")
config = BertConfig(
    vocab_size=bert_tokenizer.vocab_size, hidden_size=128, num_hidden_layers=2,
    num_attention_heads=4, intermediate_size=512, max_position_embeddings=128)
bert = BertForMaskedLM(config)

WikiText-ро бор ва токенсозӣ мекунем; дар амал додаҳои худро мегиред:

from datasets import load_dataset

def tokenize(example, tokenizer=bert_tokenizer):
    return tokenizer(example["text"], truncation=True, max_length=128,
                     padding="max_length")

mlm_dataset = load_dataset("Salesforce/wikitext", "wikitext-2-raw-v1",
                           split="train")
mlm_dataset = mlm_dataset.map(tokenize, batched=True)

Collator намунаҳоро баста карда, бо mlm=True ва mlm_probability=0.15 ниқобгузориро фаъол мекунад. Токенсоз барои аз нав токенсозӣ не, балки донистани ID-и MASK/pad ва андозаи луғат барои токени тасодуфӣ дода мешавад. Баъд TrainingArguments ва Trainer:

from transformers import Trainer, TrainingArguments
from transformers import DataCollatorForLanguageModeling

args = TrainingArguments(output_dir="./my_bert", num_train_epochs=5,
                         per_device_train_batch_size=16)
mlm_collator = DataCollatorForLanguageModeling(bert_tokenizer, mlm=True,
                                               mlm_probability=0.15)
trainer = Trainer(model=bert, args=args, train_dataset=mlm_dataset,
                  data_collator=mlm_collator)
trainer_output = trainer.train()

Месанҷем:

>>> from transformers import pipeline
>>> torch.manual_seed(42)
>>> fill_mask = pipeline("fill-mask", model=bert, tokenizer=bert_tokenizer)
>>> top_predictions = fill_mask("The capital of [MASK] is Rome.")
>>> top_predictions[0]
{'score': 0.04916289076209068,
 'token': 1010,
 'token_str': ',',
 'sequence': 'the capital of, is rome.'}

Рум пойтахти вергул нест! Модел ҳанӯз бисёр бад аст: омӯзиш хеле кӯтоҳ буд. Барои натиҷаи хуб омӯзиши тӯлонӣ лозим аст: муаллифони BERT дар додаҳои хеле калон бо 16 TPU тақрибан 4 рӯз кор карданд. Аз ин рӯ, одатан модели дар корпуси ба вазифаи худ наздик пешомӯхташударо гирифта, MLM-ро дар додаҳои худ идома додан беҳтар аст. Баъд ба вазифаи ҳадаф fine-tuning мекунед.

Fine-tuning-и BERT

Барои вазифаҳои зиёд тағйири кам лозим аст (рости расми 15.6).

Пешомӯзиши BERT

Расми 15.6. Пешомӯзиши BERT (чап) ва fine-tuning (рост).

Барои таснифи ҷумла, монанди эҳсосот, танҳо CLS нигоҳ дошта шуда, ба ҷойи сари NSP сари нави таснифот меояд (чапи расми 15.7). Тамоми моделро бо кросс-энтропия, суръати хурдтари қабатҳои поён ё ях кардани BERT дар чанд даври аввал меомӯзонед. Муаллифон дар CoLA, дурустии грамматикии ҷумла, натиҷаи аъло нишон доданд. Бо додаи хурд ҳам омӯзиши интиқолӣ муфид аст.

Маслиҳат. Муаллифони BERT ёфтанд, ки илова кардани талафоти MLM ба талафоти fine-tuning бо вазни гиперпараметрӣ омӯзишро устувор ва аз ҳад мутобиқшавиро кам мекунад.

Барои таснифи токен сар ба ҳар токен татбиқ мешавад (рости расми 15.7). Масалан шинохти мавҷудиятҳои номдор (NER) ном, сана, ҷой, созмон ва ғайраро меёбад; дар ҳуқуқ, молия ва тиб маъмул аст. Ҳамин роҳ барои хатои грамматикӣ, эҳсосоти сатҳи токен, муайян кардани ҳиссаҳои нутқ — исм, феъл ва ғайра — ё амалҳои гуфтугӯӣ — савол, хабар, салом — истифода мешавад.

Fine-tuning барои таснифи ҷумла, монанди эҳсосот

Расми 15.7. Fine-tuning барои таснифи ҷумла, монанди эҳсосот (чап), ё токен, монанди NER (рост).

Ҷуфти ҷумлаҳо мисли таснифи ҷумла аст, вале ду вуруд дорад. Барои NLI/MNLI муайян мекунад, ки A аз ҷиҳати мантиқӣ B-ро талаб мекунад, зид аст ё ҳеҷ кадом. Барои QQP/MRPC бозгӯии як маъно ва барои QNLI дар ҷумлаи B будани ҷавоби саволи A-ро месанҷад.

Дар саволҳои чандинтихобӣ (MCQA) модел барои ҳар ҷавоб алоҳида даъват мешавад: савол сегменти 0 ва ҷавоби эҳтимолӣ сегменти 1. CLS аз Linear-и яквоҳидӣ хол мегирад. Холҳои ҳамаи ҷавобҳоро softmax ба эҳтимолият мегузаронад (расми 15.8). Барои омӯзиш беҳтар аст softmax-ро нанавишта, CrossEntropyLoss-ро мустақим ба холҳо диҳем.

Истифодаи танҳо энкодер барои ҷавоб ба саволҳои чандинтихобӣ

Расми 15.8. Истифодаи танҳо энкодер барои ҷавоб ба саволҳои чандинтихобӣ.

Дар ҷавобдиҳии истихроҷӣ савол сегменти 0 ва матни замина сегменти 1 аст. Модел ҷавобро дар дохили матн меёбад. Linear-и ду воҳид барои ҳар токен холи оғоз ва холи анҷом медиҳад. Ҳангоми омӯзиш холҳои оғози ҳамаи токенҳо ба softmax дода мешаванд ва талафот кросс-энтропия бо мавқеи воқеии оғози ҷавоб аст; барои анҷом низ ҳамин тавр. Ҳангоми пешгӯӣ ҷуфти i,j интихоб мешавад, ки ҷамъи холи оғози i ва анҷоми j-ро калонтарин кунад, бо шартҳои i≤j ва j−i+1≤дарозии ҳадди аксари ҷавоб. Бо ҳамин BERT дар SQuAD пешқадам шуд.

Эзоҳи тарҷумон. Дар манбаъ ин ҳамчун ду вазифаи дуӣ барои ҳар токен («аввалини ҷавоб аст ё не», «охирини ҷавоб аст ё не») тавсиф шудааст. Дар татбиқи стандартии BERT талафот ду таснифоти чандсинфа дар байни мавқеъҳои токенҳо аст; сархат ислоҳ шуд.

Маслиҳат. Transformers барои инҳо синфҳо ва checkpoint-ҳои тайёр, монанди BertForSequenceClassification ва BertForQuestionAnswering, дорад (боби 14).

BERT барои монандии маъноии матн (STS) ҳам fine-tuning мешавад. Дар STS-B ду ҷумла гирифта, холи монандӣ медиҳад. Аммо барои ёфтани ҷуфти монандтарин дар N ҷумла бояд O(N²) бор моделро иҷро кард, ки метавонад соатҳо гирад. Sentence-BERT (SBERT) барои embedding-и хуби ҷумла мутобиқ шудааст. Ҳар ҷумларо як бор рамзгузорӣ карда, баъд монандии косинусӣ, масалан F.cosine_similarity(), ҳисоб мекунем: косинуси кунҷи ду вектор аз −1 — муқобил — то +1 — ҳамсамт. Ин хеле тезтар аст ва модел ҳам ҷумлаҳои кӯтоҳтар, на ҷуфтҳоро, мебинад; соатҳо ба сонияҳо табдил меёбанд.

Embedding-и ҷумла дар дигар вазифаҳо ҳам муфид аст:

  • Гурӯҳбандии матн. Ҳуҷҷатҳоро SBERT embedding карда, k-means ё HDBSCAN-и боби 8 аз рӯйи маъно гурӯҳ мекунад. Кам кардани андоза бо PCA ё UMAP-и боби 7 пеш аз он аксар вақт ёрӣ медиҳад.
  • Ҷустуҷӯи маъноӣ. Ҳуҷҷатҳо ё порчаҳояшонро embedding карда, нигоҳ медоред. Дархости корбар низ embedding мешавад ва наздиктаринҳо, масалан аз рӯйи косинус, меоянд.
  • Аз нав тартиб додани натиҷаҳо. Агар ҷустуҷӯи мавҷударо иваз накунед, натиҷаҳояшро аз рӯйи монандии маъноӣ бо дархост аз нав тартиб медиҳед.

Маслиҳат. Пойгоҳҳои вектории Pinecone, Weaviate, ChromaDB, Qdrant ва Milvus барои нигоҳдорӣ ва ҷустуҷӯи embedding сохта шудаанд. PostgreSQL ва MongoDB низ торафт бештар embedding-ро дастгирӣ мекунанд.

Барои вариантҳои SBERT китобхонаи Sentence Transformers-и UKPLab, ки Hugging Face нигоҳдорӣ мекунад, қулай аст. Дар Colab пешакӣ насб аст. Модели сабуку тези all-MiniLM-L6-v2 ҳанӯз embedding-и босифат медиҳад:

from sentence_transformers import SentenceTransformer

model = SentenceTransformer("all-MiniLM-L6-v2")
sentences = ["She's shopping", "She bought some shoes", "She's working"]
embeddings = model.encode(sentences, convert_to_tensor=True)
similarities = model.similarity(embeddings, embeddings)

Матритсаи монандӣ:

>>> similarities
tensor([[1.0000, 0.6328, 0.5841],
        [0.6328, 1.0000, 0.3831],
        [0.5841, 0.3831, 1.0000]], device='cuda:0')

Диагонал 1 аст: ҳар ҷумла ба худ комилан монанд. «Ӯ харид мекунад» ба «Ӯ чанд пойафзол харид» бо 0,6328 аз «Ӯ кор мекунад» бо 0,5841 наздиктар аст.

Акнун вариантҳои BERT-ро мебинем.

Моделҳои дигари танҳо энкодер

Созмонҳои зиёд аз пайи Google моделҳои худро бароварданд. Баъзе муҳимтаринҳо:

RoBERTa — Facebook AI, июли 2019, 125–355 миллион параметр

Ба BERT монанд, вале аз ҳисоби омӯзиши тӯлонитар дар додаҳои бештар беҳтар аст. MLM нигоҳ дошта шуда, NSP хориҷ карда шуд. Ниқобгузории динамикӣ муҳим аст: токенҳо дар худи омӯзиш ниқоб мешаванд, на танҳо як бор пеш аз он. Ҳамон матн дар даврҳои гуногун ниқоби дигар гирифта, гуногунӣ ва умумисозӣ зиёд мешавад.

Эзоҳ. Дар мисоли MLM-и боло мо ҳам ниқоби динамикӣ ва бе NSP доштем — равиши RoBERTa.

DistilBERT — Hugging Face, октябри 2019, 66 миллион

Варианти хурди BERT аст: 40% хурдтар, 60% тезтар, вале дар аксари вазифаҳо тақрибан 97%-и натиҷаро нигоҳ медорад. Барои мобилӣ, таъхири кам ё fine-tuning-и тез муносиб аст.

Он бо тақтири модел (model distillation), ки Ҷеффри Ҳинтон ва ҳамкоронаш соли 2015 пешниҳод карданд, омӯхта шудааст. Шогирди хурд тақсимоти эҳтимолияти омӯзгори калон-ро ҳамчун ҳадаф мегирад (расми 15.9). Инҳо ҳадафҳои нарм, на one-hot, мебошанд: шогирд ба тақсимоти дуруст мустақим меравад, ба ҷойи он ки байни ҳадҳои шадид дар намунаҳои зиёд ҷунбад. Аз ин рӯ, тақтир метавонад аз омӯзиши шогирд аз сифр дар ҳамон дода беҳтар шавад.

Пешомӯзиши DistilBERT бо ҷамъи вазндори ду талафоти тақтир ва талафоти MLM

Расми 15.9. Пешомӯзиши DistilBERT бо ҷамъи вазндори ду талафоти тақтир ва талафоти MLM.

Танҳо дар омӯзиш логитҳои ҳар ду модел ба ҳарорати аз 1 калон, одатан 2, тақсим шуда, тақсимот нарм мешавад. Шогирд дар бораи ҳамаи вариантҳо сигнали нозуктар мегирад, на танҳо ҷавоби дуруст. Ҳинтон онро дониши ниҳонӣ (dark knowledge) номид. Барои It’s sunny and I feel [MASK] омӯзгор шояд great 72%, good 27%, bad 0,5% диҳад. Бо ҳарорати 2 тақрибан 60%, 36%, 5% мешавад: донистани bad ҳамчун варианти камэҳтимол ҳам муфид аст.

Ду ҷузъи дигар MLM ва талафоти embedding-и косинусӣ мебошанд, ки ҳолатҳои ниҳоии шогирду омӯзгорро мувофиқ мекунанд. Ин шогирдро ба монанди омӯзгор «фикр кардан», на танҳо ҷавоби яксон, ташвиқ мекунад. TinyBERT баъд ҳолатҳои дигар, монанди вазнҳои диққатро ҳам мувофиқ кард. Ҷамъи ниҳоӣ вазнҳои α=5, β=2, γ=1 дошт.

Эзоҳи тарҷумон. Дар матни аслӣ гуфта шудааст, ки талафот «монандии косинусиро кам мекунад». Барои мувофиқсозии ҳолатҳо ҳадаф баръакс зиёд кардани монандӣ ё кам кардани масофаи косинусӣ аст.

ALBERT — Google Research, декабри 2019, 12–235 миллион

Ҳамаи қабатҳои энкодер вазнҳои муштарак доранд. Модел хеле хурдтар, вале на тезтар мешавад; барои хотираи маҳдуд ва омӯзиш аз сифр дар GPU-и кам-VRAM муносиб аст.

Embedding-и омилбандишуда ҳам андозаро кам мекунад. Дар BERT-large тақрибан 30 000 × 1024 зиёда аз 30 миллион параметр аст. ALBERT онро ба ду матритсаи хурд ҷудо мекунад (расми 15.10): embedding-и 128-ченака ва Linear-и проексия то 1024. Аввалӣ тақрибан 3,8 миллион ва дуюм 0,13 миллион параметр — дар маҷмӯъ камтар аз 4 миллион ба ҷойи зиёда аз 30 миллион!

Матритсаи калони embedding-ро метавон бо ҳосили зарби ду матритсаи хурд иваз кард

Расми 15.10. Матритсаи калони embedding-ро метавон бо ҳосили зарби ду матритсаи хурд иваз кард: embedding-и хурд ва Linear-и проексия ба андозаи баланд.

Ба ҷойи NSP пешгӯии тартиби ҷумлаҳо (SOP) истифода шуд: аз ду ҷумлаи воқеан пайдарпай муайян мекунад, ки кадом аввал аст. Аз NSP душвортар буда, embedding-и ҷумларо беҳтар кард.

ELECTRA — Google Research, марти 2020, 14–335 миллион

Ошкорсозии токени ивазшуда (RTD) ду модели танҳо энкодерро якҷо меомӯзонад: тавлидгари хурд ва фарқгузори калон. Тавлидгар танҳо барои пешомӯзиш бо MLM-и динамикӣ лозим аст. Барои ҳар MASK аз пешгӯиҳои беҳтарин токен мегирад; матни нав ба фарқгузор меравад, ки барои ҳар токен аслӣ буданро мефаҳмад.

Дар расми 15.11 She likes him ба She [MASK] him табдил мешавад. Тавлидгар likes, loves, hears, pushes ва ғайра медиҳад. Агар pushes интихоб шавад, She pushes him ҳосил мешавад. Фарқгузор бояд [1,0,1] гӯяд. Бо беҳтар шудани тавлидгар токенҳои ивазшуда камтар ошкоро хато мебароянд ва фарқгузор низ ҳушмандтар мешавад. Баъди омӯзиш тавлидгар ва сари дуии фарқгузор гирифта мешаванд; боқимонда модели ниҳоӣ аст.

Аз MLM самараноктар аст, чун аз токенҳои бештари ҳар намуна меомӯзад ва одатан ба BERT-и калонтар тезтар баробар мешавад. Аммо мураккабии иловагӣ ҳамеша намеарзад.

Ошкорсозии токени ивазшуда — RTD

Расми 15.11. Ошкорсозии токени ивазшуда — RTD.

DeBERTa — Microsoft, январи 2021, 139 миллион–1,5 миллиард

Модели нисбатан калон дар вазифаҳои зиёди NLU пеш гузашт. Ба ҷойи embedding-и мавқеии одӣ ҳангоми холҳои диққат мавқеи нисбӣ дорад: query-и i-ум барои key-и j-ум embedding-и омӯхташудаи i−j мегирад. Аввалин чунин модел набуд, вале диққати ҷудошуда (disentangled attention) омезиши маъно ва мавқеъро чандиртар кард.

DeBERTaV3, июли 2021, ин ғояро бо RTD-и ELECTRA якҷо ва натиҷаро боз беҳтар кард. Он маъмул аст, аммо диққати ҷудошуда ҳисобу мураккабӣ илова мекунад ва моделҳои баъдӣ роҳҳои содатар гирифтанд.

Моделҳои бештар дар Hugging Face Hub

Вариантҳо аз рӯйи андоза — BERT-base/large, забон — CamemBERT-и фаронсавӣ ё IndicBERT-и 12 забони асосии Ҳиндустон, ҳассосият ба ҳарф ва вазифа, масалан QA, фарқ мекунанд.

Моделҳои соҳавӣ ҳам ҳастанд:

  • ClinicalBERT — клиникӣ;
  • SciBERT — илм;
  • PubMedBERT — биотиб;
  • FinBERT — молия;
  • GraphCodeBERT — код;
  • Twitter-RoBERTa-base — шабакаҳои иҷтимоӣ;
  • PatentBERT — патентҳо;
  • LexLM — ҳуқуқ.

Аксарият fine-tuning-и BERT ё RoBERTa ҳастанд, баъзе аз сифр пешомӯхта шудаанд. Баъзеашон навоварӣ ҳам доранд: GraphCodeBERT ғайр аз MLM муайян мекунад, ки ҳар тағйирёбанда дар куҷо таъриф ва истифода шудааст ва ҷараёни додаҳоро пешгӯӣ мекунад — дар z = x + y, z аз x ва y меояд.

Дар Hub вариантҳои фишурда ҳам зиёданд: хурд ва одатан тез, бо тақтир, вазнҳои муштарак ё квантизатсия (дафтари Appendix_B_mixed_precision_and_quantization.ipynb дар https://github.com/ageron/handson-mlp). DistilBERT, TinyBERT, MobileBERT, MiniLM барои чанд модели асосӣ, DistilRoBERTa ва MiniDeBERTa-v2 мисоланд. Барои захираи кам, таъхири паст ва fine-tuning-и тез муносибанд.

Моделҳои адаптерӣ ҳам ҳастанд: онҳо аз модели асосии яхкардашуда, масалан BERT, ва ҷузъҳои хурди омӯзишпазири адаптер иборатанд. Ҳангоми fine-tuning танҳо адаптер тағйир меёбад. Омӯзиш тезтару арзонтар ва бо додаи кам ҳам самаранок мешавад. Масалан AdapterHub/bert-base-uncased-pf-sst2 BERT-и барои эҳсосот дар SST-2 мутобиқшуда аст. Сохтанашро дар боби 17 мебинем.

То ин ҷо Transformer, модели тарҷумаи худ, BERT ва навовариҳои танҳо энкодерро омӯхтем. Моделҳои Hub стандартӣ, чандзабонӣ, вазифавӣ, соҳавӣ, фишурда ва адаптерӣ мешаванд; ин гурӯҳҳо ҳамдигарро истисно намекунанд. Акнун ба GPT ва танҳо декодер мегузарем.

Маслиҳат. Таваҷҷуҳи созмонҳои калон бештар ба декодер рафтааст, вале танҳо энкодерҳо ҳанӯз хеле муфиданд: хурд, тез, дастрас ва осон мутобиқ мешаванд.

Трансформерҳои танҳо декодер

Ҳангоми кори Google дар BERT, Алек Рэдфорд ва муҳаққиқони OpenAI роҳи дигар гирифта, GPT-ро сохтанд. Он ба моделҳои тавонои имрӯза, аз ҷумла асоси чатботҳо чун ChatGPT ва Claude, роҳ кушод.

GPT-1 моҳи июни 2018 нашр шуд. Дар мақолаи аслӣ GPT ба Generative Pre-Training — пешомӯзиши тавлидӣ ишора мекард. Он дар тақрибан 7000 китоб барои пешгӯии токени навбатӣ омӯзонда шуд. Масалан Happy birthday медиҳад, барои ҳар мавқеъ токени навбатӣ, яъне birthday to, пешгӯӣ мешавад; to-ро илова карда, такрор мекунем (расми 15.12).

Тавлиди матн як токен дар ҳар навбат бо танҳо декодер, монанди GPT

Расми 15.12. Тавлиди матн як токен дар ҳар навбат бо танҳо декодер, монанди GPT.

Ин моделҳо барои пурракунии матн, код, посухи озод ба савол, то андозае ҳисобу мантиқ ва чатбот хубанд. Хулоса ва тарҷума ҳам мекунанд, вале энкодер–декодерҳо ба шарофати фаҳмиши хуби матни манбаъ ҳанӯз маъмуланд. Декодер таснифот ҳам мекунад, вале энкодер одатан бо модели хурдтар тезтару ҳамсатҳ аст.

Огоҳӣ. Энкодер барои пешгӯӣ вурудро як бор мебинад, декодери авторегрессӣ барои ҳар токени тавлидшуда як гузариш мехоҳад. Тавлид пайдарпай аст, вале кеш хеле ёрӣ медиҳад.

Меъмории GPT-1 ва GPT-2, вазифаҳои онҳо ва омӯзиши бе намуна (zero-shot) ё чанднамуна (few-shot)-ро мебинем. Баъд GPT-2-и хурд ва Mistral-7B-и калонро барои тавлиду ҷавоб истифода мекунем.

Меъмории GPT-1 ва пешомӯзиши тавлидӣ

Бастаҳои пешомӯзиш 64 пайдарпайии тасодуфии китобҳо, ҳар кадом маҳз 512 токен, доштанд. Барои ҳар токен токени навбатӣ ҳадаф буд. Padding лозим набуд; ҳатто токенҳои оғозу анҷом дар ин пешомӯзиш истифода нашуданд. Ин аз BERT содатар ва барои ҳар мавқеъ додаи баробар медиҳад; дар BERT мавқеъҳои охир аз сабаби pad намунаҳои камтар доранд.

Ду фарқи асосӣ аз декодери аслии Transformer:

  • Cross-attention нест, чун энкодер нест. Ҳар блок MHA-и ниқобшуда ва шабакаи пешрави дуқабата дорад, ҳар кадом бо пайвасти ҷаҳишӣ ва norm.
  • Калонтар: 12 қабат ба ҷойи 6, embedding-и 768 ба ҷойи 512 ва 12 сар ба ҷойи 8; дар маҷмӯъ 117 миллион параметр.

Огоҳӣ. Барои танҳо декодер nn.TransformerDecoder-ро бевосита истифода бурдан қулай нест, чун cross-attention-и ҷудонашаванда дорад. Метавон nn.TransformerEncoder-ро гирифта, ҳамеша ниқоби сабабӣ дод.

Дар асл барои GPT-1 ҳикояи олими ёбандаи якшохҳои англисигӯ дар водии ношинос мисол оварда шудааст (https://homl.info/unicorns). Он мисли навиштаи инсон менамуд ва он вақт таъсирбахш буд.

Эзоҳи тарҷумон. Намунаи машҳури якшохҳои англисигӯ ба намоиши GPT-2 тааллуқ дорад; нисбат додани он ба GPT-1 дар матни аслӣ номувофиқ аст.

Fine-tuning барои хулосабарории мантиқӣ, монандии маъноӣ, фаҳмиши хониш ва мантиқи рӯзмарра дар бисёр вазифаҳо натиҷаи пешқадам дод. Тағйирҳо хурд буданд:

  • Таснифи матн: сар болои embedding-и токени охирин меояд (рости расми 15.13).
  • Ду ҷумла: онҳоро бо аломати одии $ ҷудо ва аз токени охир тасниф мекунанд.
  • Монандии маъноӣ: барои бетаъсир будани тартиб модел ду бор бо ҷумла1 $ ҷумла2 ва баръакс даъват мешавад; embedding-ҳои охир элементӣ ҷамъ ва ба сари регрессия мераванд.
  • MCQA: барои ҳар ҷавоб як даъват бо заминаву савол ва ҷавоб, ҷудошуда бо $; embedding-и охир Linear ва холи ҳамаи ҷавобҳо softmax мегирад.

Дар ҳамаи fine-tuning-ҳо токени оғозу анҷом илова шуд.

Пешомӯзиши GPT-1 бо пешгӯии токени навбатӣ

Расми 15.13. Пешомӯзиши GPT-1 бо пешгӯии токени навбатӣ (NTP, чап) ва fine-tuning барои таснифот (рост).

GPT-2 ва омӯзиши бе намуна

Феврали 2019 Рэдфорд, Ҷеффри Ву ва ҳамкорони OpenAI GPT-2-ро пешниҳод карданд: монанд ба GPT-1, вале калонтар. Чор андоза дошт; калонтарин 48 қабат, 20 сар, embedding-и 1600 ва равзанаи 1024 токен, дар маҷмӯъ зиёда аз 1,5 миллиард параметр.

Барои он додаи бузург лозим буд. Common Crawl, бо зиёда аз ду миллиард вебсаҳифа, санҷида шуд, вале бисёраш бемаъно ё ҷадвалҳои дароз буд. Пас WebText, тақрибан 8 миллион саҳифае, ки аз навиштаҳои сербаҳои Reddit пайванд шуда буданд, сохта шуд.

Муҳимтар, GPT-2 вазифаҳоро бе fine-tuning, яъне zero-shot learning (ZSL), хуб иҷро мекард:

  • Савол: What is the capital of New-Zealand? A: → Wellington.
  • Хулоса: охири ҳуҷҷат TL;DR: илова кунед.
  • Тарҷума бо намуна дар промпт: Bonjour papa = Hello dad, Le chien dort = The dog is sleeping, баъд Elle aime le chocolat = → She loves chocolate.

Муаллифон нишон доданд, ки бо дучанд шудани андозаи модел натиҷаи ZSL тақрибан як миқдори собит беҳтар мешавад: робитаи логарифмӣ-хаттӣ. Шояд AI-и аз инсон тавоно танҳо трансформери кофӣ калон мехост?

Эзоҳ. OpenAI аввал GPT-2-и калонтаринро бо сабаби хатари хабарҳои дурӯғу спам нашр накард. Шаккокон онро таблиғ, ҳаракат ба AI-и баста ва эҳтимол таъсир ба танзимгарӣ меномиданд. Модели пурра баъди чанд моҳ баромад. То нашри моделҳои вазнашон дастраси gpt-oss дар августи 2025 ин охирин модели забонии кушодаи OpenAI буд.

GPT-3, омӯзиши дарзаминагӣ, якнамуна ва чанднамуна

OpenAI соли 2020 GPT-3-ро сохт. Он 175 миллиард параметр дошт ва асосан дар тақрибан 570 GB матни филтршудаи Common Crawl, инчунин WebText2, китобҳо ва Википедия омӯхта шуд.

Эзоҳи тарҷумон. Дар манбаъ «тақрибан 40 миллиард параметр» ва «WebCrawl» навишта шудааст. Калонтарин GPT-3-и мақолаи соли 2020 175 миллиард параметр дошт ва корпуси веби он Common Crawl буд; сархат ислоҳ шуд.

Он аз GPT-2, махсусан дар ZSL, хеле беҳтар буд. Муҳимтаринаш умумисозӣ аз чанд намуна: few-shot learning (FSL), ё бо як намуна one-shot learning (OSL). Муаллифон намунаҳоро дар худи промпт мегузоштанд ва онро омӯзиши дарзаминагӣ (in-context learning, ICL) номиданд:

Alice was friends with Bob. Alice went to visit her friend ___. → Bob
George bought some baseball equipment, a ball, a glove, and a ___. →

Модел bat — чӯбдасти бейсбол мебарорад. Ғоя дар намунаи тарҷумаи GPT-2 ҳам буд, вале GPT-3 онро расмӣ ва амиқ омӯхт.

Эзоҳ. ICL як роҳи нави маъмули OSL/FSL аст. Худи омӯзиши якнамуна, чанднамуна ва бе намуна аз пеш вуҷуд доштанд.

Акнун GPT-2-ро мегирем; баъд бо API ҳам кор мекунем.

Тавлиди матн бо GPT-2

Пешфарз варианти хурди 124-миллионпараметрӣ бор мешавад:

from transformers import AutoTokenizer, AutoModelForCausalLM

model_id = "gpt2"
gpt2_tokenizer = AutoTokenizer.from_pretrained(model_id)
gpt2 = AutoModelForCausalLM.from_pretrained(
    model_id, device_map="auto", dtype="auto")
  • Токенсоз ва модел пешомӯхташудаанд.
  • AutoModelForCausalLM аз checkpoint синфи мувофиқ, ин ҷо GPT2LMHeadModel, месозад.
  • device_map="auto" моделро ба дастгоҳи мувофиқ, одатан GPU, мегузорад; барои модели калон метавонад байни чанд GPU тақсим кунад.
  • dtype="auto" навъи мувофиқи вазнҳоро интихоб мекунад. Вазнҳои 16-битӣ бартарӣ доранд: нисфи хотира, интиқоли камтар ва суръати бештар дар GPU-и муносиб.

Эзоҳи тарҷумон. dtype="auto" пеш аз ҳама навъи сабтшудаи конфигуратсия ё вазнҳои checkpoint-ро пайравӣ мекунад; он кафолати интихоби худкори 16-бит танҳо аз рӯйи GPU нест.

Печонандаи содаи generate():

def generate(model, tokenizer, prompt, max_new_tokens=50, **generate_kwargs):
    inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
    outputs = model.generate(**inputs, max_new_tokens=max_new_tokens,
                             pad_token_id=tokenizer.eos_token_id,
                             **generate_kwargs)
    return tokenizer.decode(outputs[0], skip_special_tokens=True)

Функсия промптро токенсозӣ, ба GPU интиқол ва то 50 токени нав ё то EoS илова мекунад; баъд ID-ҳоро ба матн бармегардонад. GPT-2 pad-и махсус надошт, пас EoS-ро барои padding мегирем. Як промпт воқеан пуркунӣ намехоҳад, вале додани ID огоҳиро дур мекунад. Аргументҳои иловагӣ ба generate() мегузаранд.

Эзоҳ. Танҳо декодерҳо одатан аз чап пур мекунанд, чун токенҳои нав аз рост илова мешаванд.

Ҳикояи якшох:

>>> prompt = "Scientists found a talking unicorn today. Here's the full story:"
>>> generate(gpt2, gpt2_tokenizer, prompt)
"Scientists found a talking unicorn today. Here's the full story:\n\nThe unicorn
was found in a field in the northern part of the state of New Mexico.\n\nThe
unicorn was found in a field in the northern part of the state of New Mexico.
\n\nThe unicorn was found in a field in"

Оғоз хуб, вале ҷумлаи «Якшох дар киштзори шимоли Ню-Мексико ёфт шуд» такрор мешавад. Пешфарз ҳар қадам токени эҳтимолитарин интихоб мешавад. Барои ҷавоби сохтордор муносиб, барои эҷод аксар вақт дилгиркунанда аст. Бо do_sample=True мисли Шекспири боби 14 аз тақсимот намуна мегирем:

>>> torch.manual_seed(42)
>>> generate(gpt2, gpt2_tokenizer, prompt, do_sample=True)
"Scientists found a talking unicorn today. Here's the full story:\n\nThere
aren't lots of other unicorns and they have been making their way across the
United States since at least the 1800s, but this year there weren't a solitary
unicorn on the land. Today, there are around 1,000."

Матн мегӯяд, ки якшохҳо аз солҳои 1800 дар ИМА будаанд ва имрӯз тақрибан 1000-тоанд — сохта аст, вале камтар такрорӣ. Барои беҳтар кардан:

АргументТаъсир
temperatureПешфарз 1; пасттар — пешгӯишавандатар, баландтар — гуногунтар
top_kИнтихоб танҳо аз k токени эҳтимолитарин
top_pХурдтарин маҷмӯи токенҳои эҳтимолитарин бо ҷамъи эҳтимолияти ҳадди ақал p
num_beamsПаҳнои ҷустуҷӯи шуоӣ; пешфарз 1, яъне бе beam search

Top-p аксар вақт беҳтар аст, чун ба тақсимот мутобиқ мешавад. Дар The capital city of France is як ҷавоби хеле қавӣ — Paris — ҳаст; top-p-и мувофиқ танҳо онро нигоҳ медорад, вале top-k метавонад варианти нодуруст ҳам дошта бошад. Дар My favorite city is шаҳрҳои зиёде мумкинанд: top-p онҳоро мувофиқи эҳтимолият мегирад, top-k ба чандто маҳдуд мекунад.

>>> torch.manual_seed(42)
>>> generate(gpt2, gpt2_tokenizer, prompt, do_sample=True, top_p=0.6)
"Scientists found a talking unicorn today. Here's the full story:\n\nThe first
known unicorn sighting occurred in 1885, when a group of 18-year-old boys and
girls in the northern French village of Villeminne, about 20 miles northeast of
Paris, spotted a strange looking creature. The unicorn"

Мазмуни сохта: нахустин мушоҳида соли 1885 дар деҳаи фаронсавии Виллемин аз ҷониби ҷавонони 18-сола будааст. Аз ҷиҳати навиштор беҳтар шуд. Акнун саволҳо.

GPT-2 барои посух ба савол

Аз кишвар пойтахт мепурсем:

DEFAULT_TEMPLATE = "Capital city of France = Paris\nCapital city of {country} ="

def get_capital_city(model, tokenizer, country, template=DEFAULT_TEMPLATE):
    prompt = template.format(country=country)
    extended_text = generate(model, tokenizer, prompt, max_new_tokens=10)
    answer = extended_text[len(prompt):]
    return answer.strip().splitlines()[0].strip()

{country} ба номи кишвар иваз мешавад. Намунаи France=Paris ҳам вазифа ва ҳам қолаби ҷавобро нишон медиҳад — ICL. Даҳ токен мегирем; промпт, сатрҳои баъдӣ ва фосилаҳои изофиро мебурем:

>>> get_capital_city(gpt2, gpt2_tokenizer, "United Kingdom")
'London'
>>> get_capital_city(gpt2, gpt2_tokenizer, "Mexico")
'Mexico City'

Кор мекунад ва ба навиштҳои UK, The UK, England, Great Britain ё ҳатто Big Britane чандир аст. Аммо комил нест:

  • Хатои маъмул мекунад: барои Канада Toronto ба ҷойи Ottawa. Аз веб тасаввуроти ғалат ва ғаразро ҳам гирифтааст.
  • Ҳангоми нобоварӣ тақрибан 30% номи кишварро такрор мекунад. Шояд аз он ки Djibouti, Luxembourg, Singapore пойтахти ҳамном ва Guatemala City/Kuwait City номҳои наздик доранд.
  • Агар вуруд кишвар набошад, аксар вақт Paris мегӯяд, чун танҳо намунаи промпт ҳамин аст.

Бо gpt2-xl, 1,5 миллиард параметр, беҳтар мешавад, вале комил не. Модели боз калонтарро мебинем.

Боргирӣ ва иҷрои Mistral-7B

Акнун Mistral-7B-и стартапи фаронсавии Mistral AI-ро мегирем, ки сентябри 2023 баромад; коди мисол версияи v0.3-ро, ки майи 2024 нашр шуд, истифода мебарад. Он 7 миллиард параметр ва усулҳои grouped-query attention ва sliding-window attention-и боби 17 дорад, ки суръату натиҷаро беҳтар мекунанд.

Модел иҷозатномаи Apache 2.0 дорад ва дар GPU-и Colab иҷро мешавад. Дастрасӣ дар Hub шартӣ аст: бояд ворид шуда, ба додани маълумоти шахсӣ ба соҳиби модел розӣ шавед. Чунин шартҳо барои омори истифода, кам кардани сӯиистифода ва ҳамкории эҳтимолӣ гузошта мешаванд. Қадамҳо:

  1. Дар https://huggingface.co ворид ё бо Sign Up ҳисоб созед.
  2. Ба https://huggingface.co/mistralai/Mistral-7B-v0.3 рафта, model card-и маълумоту кодро хонед. Агар паёми мубодилаи маълумоти тамос нишон дода шавад ва розӣ бошед, Agree and access repository-ро пахш кунед. Розигӣ барои ҳамин модел як бор аст.

Саҳифаи Mistral-7B-v0.3 бо талаби розигӣ

Расми 15.14. Саҳифаи Mistral-7B-v0.3 бо талаби розигӣ ба мубодилаи маълумоти шахсӣ.

Баъд токени дастрасӣ лозим:

  1. Аз нишонаи профил Access Tokens ё https://huggingface.co/settings/tokens-ро кушоед; шояд тасдиқи шахсият хоста шавад.
  2. Ном, масалан hf-read-mistral, диҳед.
  3. Навъи Fine-grained, Read ё Write интихоб мешавад.
  4. Барои истифодаи воқеӣ иҷозати маҳдуд муҳим аст. Дар Fine-grained бахши Repositories permissions-ро ёфта, mistralai/Mistral-7B-v0.3 ва Read access to contents of selected repos-ро интихоб кунед. Ё иҷозати хондани ҳамаи public gated repo-ҳои дастрасро додан мумкин аст.
  5. Матни аслӣ барои таҳия Read ё ҳатто Write-и васеъро осонтар мешуморад. Барои танҳо боргирии модел иҷозати хондан вазифаи лозимиро иҷро мекунад.
  6. Create Token-ро пахш карда, токенро нусха ва боэҳтиёт нигоҳ доред; дигар намоиш дода намешавад.

Огоҳӣ. Токенро дар мудири парол, монанди 1Password ё Bitwarden, бехатар нигоҳ доред. Нолозимро нест ва ҳангоми гумони фошшавӣ нав кунед, то токени пешина беэътибор шавад. Барои иҷозатҳои васеъ ин махсусан муҳим аст.

Сохтани токени дастрасии Hugging Face

Расми 15.15. Сохтани токени дастрасии Hugging Face.

Дар Colab токенро дар код нанависед: хонандаи notebook сирро мебинад. Аз Secrets истифода баред:

  1. Нишонаи калидро дар сатри чап кушоед (расми 15.16).
  2. Add new secret: ном, масалан token-hf-read-mistral, ва қимати токенро диҳед. Дар серверҳои Google нигоҳ дошта мешавад.
  3. Notebook access-ро барои notebook-и ҷорӣ фаъол кунед. Пешфарз хомӯш аст ва барои ҳар notebook-и дигар ҷудо фаъол мешавад.

Огоҳӣ. Пеш аз дастрас кардани сир ба notebook-и дигарон, ба муаллиф бовар кунед ё кодро санҷед.

Нигоҳ доштани токен дар мудири сиррҳои Colab

Расми 15.16. Нигоҳ доштани токен дар мудири сиррҳои Colab.

Токенро мехонем:

from google.colab import userdata

access_token = userdata.get('token-hf-read-mistral')

Ба Hub ворид мешавем:

from huggingface_hub import login

login(access_token)

Моделро мисли GPT-2 бор мекунем:

model_id = "mistralai/Mistral-7B-v0.3"
mistral7b_tokenizer = AutoTokenizer.from_pretrained(model_id)
mistral7b = AutoModelForCausalLM.from_pretrained(
    model_id, device_map="auto", dtype="auto")

Акнун ҳикоя ё ҷавоб тавлид мекунад. Дар мисоли пойтахтҳо модел пойтахти қариб ҳамаи кишварҳоро дуруст мегӯяд ва хатоҳои ками боқимонда ҳам қобили фаҳманд.

Аммо чӣ гуна бо он суҳбат кунем?

Табдил додани модели бузурги забонӣ ба чатбот

Барои чатбот модели асосӣ кофӣ нест. Масалан, аз Mistral-7B чунин мепурсем:

>>> prompt = "List some places I should visit in Paris."
>>> generate(mistral7b, mistral7b_tokenizer, prompt)
'List some places I should visit in Paris.\n\nI’m going to Paris in a few weeks
and I’m looking for some places to visit. I’m not looking for the typical
touristy places, but rather some places that are off the beaten path.\n\nI’'

Модел ҷавоб надод, танҳо саволро идома дод: «Чанд ҳафта пас ба Париж меравам… ҷойҳои ғайримаъмулиро меҷӯям…». Барои гуфтугӯ муҳандисии промпт (prompt engineering) — тағйири промпт то рафтори боэътимоди дилхоҳ — ёрӣ медиҳад. Масалан, муқаддима:

bob_introduction = """
Bob is an amazing chatbot. It knows everything and it's incredibly helpful.
"""

Яъне «Боб чатботи аҷиб аст, ҳама чизро медонад ва хеле ёрирасон аст». Бо нишонаҳои нақш (role tags) Me ва Bob ҳамсуҳбатҳоро равшан мекунем:

full_prompt = f"{bob_introduction}Me: {prompt}\nBob:"

Натиҷа:

>>> extended_text = generate(mistral7b, mistral7b_tokenizer, full_prompt,
...                          max_new_tokens=100)
...
>>> answer = extended_text[len(full_prompt):].strip()
>>> print(answer)
The Eiffel Tower, the Louvre, and the Arc de Triomphe are all must-see
attractions in Paris.
Me: What's the best way to get around Paris?
Bob: The metro is the most efficient way to get around Paris.
Me: What's the best time of year to visit Paris?
[...]

Боб аввал бурҷи Эйфел, Лувр ва Тоқи пирӯзиро дуруст пешниҳод кард, вале баъд худи саволу ҷавобҳои минбаъдаро ҳам сохтааст. Боқимондаро дар бозгашт ба Me мебурем:

>>> answer.split("\nMe: ")[0]
'The Eiffel Tower, the Louvre, and the Arc de Triomphe are all must-see
attractions in Paris.'

Агар баъд пурсед «Дар бораи ҷойи аввал бештар бигӯ», дар суҳбати нав маънояшро намедонад. Пас тамоми гуфтугӯи то ҳол, яъне context, нигоҳ дошта мешавад. Ба охираш Me, саволи нав ва Bob илова карда, боз ба модел медиҳем. Синфи хурд:

class BobTheChatbot:  # ё ChatBob
    def __init__(self, model, tokenizer, introduction=bob_introduction,
                 max_answer_length=10_000):
        self.model = model
        self.tokenizer = tokenizer
        self.context = introduction
        self.max_answer_length = max_answer_length

    def chat(self, prompt):
        self.context += "\nMe: " + prompt + "\nBob:"
        context = self.context
        start_index = len(context)
        while True:
            extended = generate(self.model, self.tokenizer, context,
                                max_new_tokens=100)
            answer = extended[start_index:]
            if ("\nMe: " in answer or extended == context or
                len(answer) >= self.max_answer_length): break
            context = extended
        answer = answer.split("\nMe: ")[0]
        self.context += answer
        return answer.strip()

Ҳар объект як суҳбати пурраро дар context, аз муқаддима сар карда, нигоҳ медорад. chat() промптро илова, ҷавобро тавлид, ҷудо ва боз ба context ҳамроҳ мекунад. Ҳалқаи while барои ҷавоби дароз чанд бор моделро иҷро мекунад. Ҳангоми Me, баромади холӣ ё аз ҳад дароз қатъ мешавад:

>>> bob = BobTheChatbot(mistral7b, mistral7b_tokenizer)
>>> bob.chat("List some places I should visit in Paris.")
'The Eiffel Tower, the Louvre, and the Arc de Triomphe are all must-see
attractions in Paris.'
>>> bob.chat("Tell me more about the first place.")
'The Eiffel Tower is a wrought iron lattice tower on the Champ de Mars in Paris,
France. It is named after the engineer Gustave Eiffel, whose company designed
and built the tower.'
>>> bob.chat("And Rome?")
'Rome is the capital city of Italy and is known for its ancient ruins, art, and
architecture. Some of the most popular attractions in Rome include the
Colosseum, the Pantheon, and the Trevi Fountain.'

Боб мефаҳмад, ки «ҷойи аввал» бурҷи Эйфел аст, онро тавсиф мекунад ва баъд дар бораи Рум Колизей, Пантеон ва фаввораи Тревиро меорад.

Тақрибан бо 20 сатр чатбот сохтем! Вале баъди суҳбати дароз мушкилҳо намоён мешаванд:

  • Такрор: барои панҷ шӯхӣ ҳамон як шӯхии гови бепоро панҷ бор мегӯяд.
  • Ҷавоби нокофӣ ва оҳанги камгуфтугӯӣ: барои кулчақанд танҳо «орд, шакар, равған ва тухмро омезед» мегӯяд; ин дастури кофӣ нест.
  • Ҷавоби хатарнок: модели асосӣ метавонад ба саволи омодагӣ ба ғорати бонк низ маслиҳати номуносиб диҳад.

Муҳандисии промпт

Ифодаи савол ҷавобро хеле дигар мекунад — барои инсон ҳам, барои LLM бештар. Санҷидани промптҳои гуногун меарзад.

Калима, замина, чанд намуна, шахсияти тақлидшаванда, масалан «Ту коршиноси дӯстонаи амволи ғайриманқул ҳастӣ», қолабу сабки баромад ва хатоҳои пешгиришавандаро муайян кунед. Ҳатто барномае метавонад таркибҳои промптро санҷида, беҳтаринашро ёбад. Беҳинасозии худкори промпт (APO), аз ҷумла prompt tuning, embedding-ҳои омӯхташударо пеши вуруд мегузорад.

Вазифаи мураккабро ба зервазифа ҷудо карда, баромади як промптро ба навбатӣ диҳед: занҷирбандии промптҳо (prompt chaining). Ба ҷойи «дарси яксоатаи динамикаи моеъ навис» аввал нақша, баъд санҷиши нақша ва мавзуъҳои гумшуда, сипас матни дарсро талаб кунед. Ин равиши чандқадамӣ аксар вақт натиҷаро беҳтар мекунад ва барои мавзуъҳои дигар автоматӣ мешавад.

Промптгузории занҷири андеша (CoT) моделро ба ҳалли қадамӣ ташвиқ мекунад, на ҷавоби аввалини ба ёд омада. Метавон «қадам ба қадам ҳал кун» гуфт ё намунаи ҷавоби қадамӣ дод. Барои вазифаҳои мантиқӣ боэътимодиро зиёд мекунад. Якчанд бор иҷро ва ҷавоби сертакрорро интихоб кардан CoT бо худмувофиқатӣ (CoT-SC) аст.

Дарахти андешаҳо (ToT) чанд шохаи ҳалли эҳтимолиро месозад. Дар ҳар қадам чанд вариант, бо даъватҳои тасодуфии гуногун ё талаби мустақим, мегирад. Баъд онҳоро арзёбӣ карда, умедбахштаринро идома медиҳад. Дар бунбаст ба шохаи дигар бармегардад.

ToT натиҷаи хуб, вале даъватҳои бисёр ва хароҷоти зиёд дорад. Баҳси чанд агент (MAD) ҳам роҳи дигар, вале гарон аст. Роҳи сабуктар — аз як LLM талаб кардани танқиду такмили ҷавоби худ.

LLM метавонад даъвои боварибахш, вале дурӯғ созад: галлюсинатсия. Яке аз роҳҳои муҳим иловаи иттилооти мувофиқ ба промпт дар вақти кор аст. Масалан, барои саволи дору чатбот аз пойгоҳи тиббии боэътимод ё графи дониш маълумот гирифта, ба промпт мегузорад. Ин тавлиди бо бозёбӣ ғанигардида (RAG) аст ва метавонад хатогиро кам кунад; баъд боз мебинем.

LLM метавонад промпти модели дигарро ҳам беҳтар кунад: «акси гурбачаи зебо»-ро ба «гурбачаи нармпашми дилрабо дар пиёла, рангҳои пастелӣ, заминаи боке, ҷузъиёти баланд» табдил дода, ба модели тавлиди тасвир мефиристем (боби 16).

Муқаддимаи Бобро бо «муфид, дӯстона, боадаб ва бехатар» такмил додан мумкин аст, вале танҳо он кофии боэътимод нест. Корбар метавонад бо jailbreak дастурҳоро нодида гирифтан ё ошкор карданро барангезад. Ҳамлаи ҳадафноки истихроҷи додаҳо низ метавонад маълумоти шахсиеро, ки онлайн фош шуда ба додаҳои омӯзишӣ даромадааст, талаб кунад. Fine-tuning-и модели асосӣ муфидӣ ва бехатариро бештар мекунад.

Мутобиқсозӣ барои гуфтугӯ ва пайравӣ аз дастур бо SFT ва RLHF

Расми 15.17 қадамҳоро нишон медиҳад. Аввал трансформер, одатан танҳо декодер, дар корпуси азим бо пешгӯии токени навбатӣ (NTP) пешомӯхта мешавад. Ин гаронтарин қадам ва ҳосилаш модели асосӣ, монанди Mistral-7B ё GPT-3, аст.

Баъд онро барои оҳанги хубу гуфтугӯ модели гуфтугӯӣ, ё барои пайравии беҳтари дастур instruct model мекунем. Чатбот одатан ҳар дуро дорад. Mistral-7B-Instruct аз модели асосӣ барои ҳамин мутобиқ шудааст.

Эзоҳ. Base model танҳо пешомӯхташуда, вале ҳанӯз fine-tuning-нашуда аст. Foundation model — модели бунёдӣ ба вазифаҳои зиёд бо промпт ё fine-tuning мутобиқ мешавад. Он метавонад асосӣ ё қисман мутобиқшуда, масалан гуфтугӯӣ, бошад. Дар амал истилоҳҳо баъзан ба ҷойи ҳам меоянд.

Сохтани чатбот

Расми 15.17. Сохтани чатбот: пешомӯзиш, fine-tuning-и думарҳилавӣ ва ҷойгиркунӣ.

Fine-tuning одатан ду қадам дорад:

  1. Supervised Fine-Tuning (SFT) — омӯзиши назоратшаванда дар маҷмӯи интихобшудаи суҳбат, саволу ҷавоб, код, ҳалли математика, нақшбозӣ, монанди «Ту ошпази моҳир ҳастӣ, ризотторо чӣ гуна тайёр кунам?», ва ҷавобҳои бехатар. Омӯзиш NTP-и одӣ аст, вале талафотро аксар вақт танҳо дар токенҳои ҷавоб ҳисоб мекунанд. Ин loss masking моделро ба беҳтар кардани ҷавоб, на тақлиди саволи корбар, равона мекунад.
  2. Fine-tuning аз бозхӯрди инсон — арзёбҳо ҷавобҳоро дараҷабандӣ ва модел ҷавобҳои авлотарро меомӯзад. Одатан омӯзиши тақвиятӣ аз бозхӯрди инсон (RLHF) ё беҳинасозии мустақими афзалиятҳо (DPO) истифода мешавад.

OpenAI январи 2022 InstructGPT-и бар GPT-3 асосёфтаи SFT+RLHF-ро тавассути API пешниҳод кард. SFT одии назоратшаванда аст; RLHF пештар дар мақолаи соли 2017-и OpenAI ва DeepMind буд, аммо якҷоя натиҷаи хуб доданд.

RLHF аз proximal policy optimization (PPO), ки дар боби 19 меомӯзем ва бо DPO омехта намешавад, истифода мекунад. Аввал модели мукофот афзалияти инсонро пешгӯӣ мекунад; баъд PPO LLM-ро ба ҷавобҳои баландхол равона мекунад. Аз модели ибтидоӣ аз ҳад дур шудан маҳдуд мешавад, то дониш ва рафтори муфид гум нашавад. Матни аслӣ ин хатарро бо reward hacking, яъне истифодаи нуқсони сигнали мукофот, пайванд медиҳад.

RLHF хуб кор мекунад, вале мисли бисёр усулҳои RL омӯзишаш ноустувору душвор буда метавонад. Аз ин рӯ, усулҳои содатар, аз ҷумла DPO, пайдо шуданд.

Беҳинасозии мустақими афзалиятҳо — DPO

Муҳаққиқони Стэнфорд онро моҳи майи 2023 пешниҳод карданд. Аксар вақт баробар ё беҳтар аз RLHF ва содатар, устувортар ва камдодатар аст.

Дар маҷмӯи афзалиятҳо ҳар намуна се ҷузъ дорад: промпт, ҷавоби интихобшуда ва ҷавоби радшуда. Модел бояд интихобшударо эҳтимолитар кунад ва аз модели истинодии яхкардашуда, одатан модели баъди SFT, аз ҳад дур нашавад. Ин омӯзиши муқоисавӣ (contrastive learning) аз намунаи мусбату манфӣ аст. Муаллифон нишон доданд, ки талафоти муодилаи 15.2 тақрибан ба ҳадафи RLHF мувофиқ аст, вале на модели ҷудои мукофот ва на алгоритми мураккаби RL талаб мекунад.

Муодилаи 15.2. Талафоти DPO.

J(θ) = −log σ(β[log p_θ(y_c | x) − log p_ref(y_c | x)] − β[log p_θ(y_r | x) − log p_ref(y_r | x)])

  • J(θ) талафоти намунаи (x,y_c,y_r) бо параметрҳои ҷорӣ ва модели истинод аст.
  • x промпт, y_c ҷавоби интихобшуда, y_r радшуда мебошад.
  • σ функсияи сигмоид аст: σ(z)=1/(1+e⁻ᶻ).
  • log p_θ(y|x) логарифми эҳтимолияти ҷавоб аз рӯйи модели мо мебошад.
  • log p_ref(y|x) ҳамин қимат аз модели истинод аст.
  • β гиперпараметри монанд ба ҳарорат аст, одатан 0,1–0,5. Он қувваи пайравӣ аз истинод ва афзалиятҳоро идора мекунад; β-и калонтар моделро ба модели истинод наздиктар нигоҳ медорад.

Маслиҳат. Барои log(σ(·)) аз F.logsigmoid() истифода баред: аз torch.log(torch.sigmoid(...)) тезтару аз ҷиҳати ададӣ устувортар аст.

Барои log p(y|x) промпт ва ҷавобро мепайвандем, токенсозӣ ва моделро иҷро мекунем. Ҳар ду ҷавобро якбора додан мумкин аст:

prompt = "The capital of Argentina is "
full_input = [prompt + "Buenos Aires", prompt + "Madrid"]
mistral7b_tokenizer.pad_token = mistral7b_tokenizer.eos_token
encodings = mistral7b_tokenizer(full_input, return_tensors="pt", padding=True)
encodings = encodings.to(device)
with torch.no_grad():
  logits = mistral7b(**encodings).logits  # шакл: [2, 8, 32768]

F.log_softmax() барои ҳар мавқеъ логарифми эҳтимолияти ҳамаи 32 768 токени навбатиро медиҳад. Аммо танҳо токени воқеии баъдӣ лозим: баъди Buenos танҳо Aires, на días, noches ё дигарон. Бо gather() мегирем; токени охир навбатӣ надорад:

next_token_ids = encodings.input_ids[:, 1:]  # [2, 7]
log_probas = F.log_softmax(logits, dim=-1)[:, :-1]  # [2, 7, 32768]
next_token_log_probas = torch.gather(  # [2, 7, 1]
    log_probas, dim=2, index=next_token_ids.unsqueeze(2))

unsqueeze(2) шумораи андозаҳои index-ро ба input мувофиқ мекунад.

Эзоҳи тарҷумон. Дар шарҳи аслӣ барои gather() broadcasting зикр шудааст. torch.gather input ва index-ро худкор broadcast намекунад: онҳо бояд шумораи андозаҳои яксон ва дар меҳварҳои дигар андозаҳои мувофиқ дошта бошанд.

Роҳи кӯтоҳтар кросс-энтропия аст:

next_token_log_probas = -F.cross_entropy(  # [2, 7]
    logits[:, :-1].permute(0, 2, 1), next_token_ids, reduction="none")

reduction="none" миёнагириро манъ мекунад. Аломат манфӣ мешавад, чун cross-entropy манфии log likelihood медиҳад. permute меҳвари синфро ба ҷойи 1 мебарад.

Эҳтимолиятҳо бо экспонента:

>>> [f"{p.item():.2%}" for p in torch.exp(next_token_log_probas[0])]
['3.27%', '0.02%', '51.95%', '0.40%', '33.98%', '11.38%', '99.61%']
>>> [f"{p.item():.2%}" for p in torch.exp(next_token_log_probas[1])]
['0.14%', '3.27%', '0.02%', '51.95%', '0.37%', '32.03%', '0.00%']

Дар ин мисол 3,27% барои The, баъд 0,02% capital ва ғайра аст. Пайдарпайии дуюм бо pad оғоз мешавад, пас эҳтимолияти аввали 0,14%-ро нодида мегиранд. Барои токенҳои промпт тақрибан яксон, барои ҷавоб фарқ мекунад: Buenos 11,38%, Madrid қариб 0%. Баъди is токенҳои a, one ва the ҳам мумкинанд, бинобар ин эҳтимолияти Buenos 100% нест; вале баъди Buenos эҳтимолияти Aires 99,61% мешавад.

Ҷамъи логарифмҳои токенҳои ҷавоб log p(y|x) медиҳад:

>>> answer_log_proba = next_token_log_probas[0, -2:].sum()  # Buenos + Aires
>>> torch.exp(answer_log_proba).item()
0.11376953125

Ҷойи аниқи ҷавобро, махсусан дар бастаҳои пуркардашуда, ёфтан душвор аст. Барои DPO метавон ба ҷойи log p(y|x) log p(xy), эҳтимолияти тамоми промпту ҷавобро гирифт. Зеро log p(xy)=log p(x)+log p(y|x) ва саҳми якхелаи промпт дар фарқи chosen/rejected бекор мешавад. Танҳо pad-ро ниқоб ва барои ҳар пайдарпайӣ ҷамъ мекунем:

>>> mask = encodings.attention_mask
>>> padding_mask = mask[:, :-1] * mask[:, 1:]  # both tokens must be real
>>> log_probas_sum = (next_token_log_probas * padding_mask).sum(dim=1)
>>> log_probas_sum
tensor([-21.2500, -30.2500], device='cuda:0', dtype=torch.bfloat16)

Эзоҳи тарҷумон. Дар манбаъ танҳо encodings.attention_mask[:, :-1] гирифта мешавад. Аммо қимати мавқеи i эҳтимоли гузариши токени i → i+1 аст, пас ҳарду токен бояд воқеӣ бошанд. Ниқоби манбаъ дар ин мисол, ки pad аз чап аст, кофист (гузариши pad → токени аввалро бо 0,14% хориҷ мекунад), вале бо pad аз рост эҳтимоли pad-и ҳадафро ҳисоб мекард. Зарби ду ниқоб ҳарду ҳолатро дуруст мекунад; натиҷаи ин мисол тағйир намеёбад. Тартиби pad ва мавқеъҳоро дар ду ҷавоб яксон нигоҳ доред, то саҳми промпт воқеан бекор шавад.

Пайдарпайии chosen эҳтимолияти логарифмии баландтар дорад. Агар ҳамаи инро дар sum_of_log_probas() ҷамъ кунед, DPO чунин мешавад:

def dpo_loss(model, ref_model, tokenizer, full_input_c, full_input_r, beta=0.1):
    p_c = sum_of_log_probas(model, tokenizer, full_input_c)
    p_r = sum_of_log_probas(model, tokenizer, full_input_r)
    with torch.no_grad():  # модели истинод яхкардашуда аст
        p_ref_c = sum_of_log_probas(ref_model, tokenizer, full_input_c)
        p_ref_r = sum_of_log_probas(ref_model, tokenizer, full_input_r)
    return -F.logsigmoid(beta*((p_c - p_ref_c) - (p_r - p_ref_r))).mean()

Бо ҳамин аз афзалиятҳо fine-tuning мекунед: модели омӯзиширо ба train ва истинодиро ба eval гузоред. Китобхонаи Hugging Face TRL — Transformer Reinforcement Learning SFT, RLHF, DPO ва ғайраро осон мекунад.

Fine-tuning бо TRL

Аввал SFT, баъд DPO месанҷем. Alpaca тақрибан 52 000 дастуру ҷавоби сохтаи text-davinci-003-и OpenAI дорад:

>>> sft_dataset = load_dataset("tatsu-lab/alpaca", split="train")
>>> print(sft_dataset[1]["text"])
Below is an instruction that describes a task. Write a response that
appropriately completes the request.

### Instruction:
What are the three primary colors?

### Response:
The three primary colors are red, blue, and yellow.

Яъне дастур мепурсад «Се ранги асосӣ кадоманд?» ва ҷавоб «сурх, кабуд, зард» мегӯяд. Ин маҷмӯа барои як дастур ва ҷавоби мувофиқ аст. Баъд барои суҳбати дароз маҷмӯи чанднавбатӣ, масалан OpenAssistant/oasst1, муфид аст. Он нишонаҳои нақшро ҳам меомӯзонад. Қолабҳо гуногунанд: User/Assistant, Human/Assistant ё токенҳои махсуси модел.

Қолабҳои ба ChatML монанд нақшҳоро бо токенҳое чун , , ва ишора мекунанд. Инро ҳамчун намунаи умумии нақшҳо хонед: қолаби воқеӣ ва токенҳои махсус аз модели мушаххас вобастаанд.

Майдонҳои Alpaca text, instruction, output ва input мебошанд. Text-и навро бо услуби Human/Assistant месозем:

def preprocess(example):
    text = f"Human: {example['instruction']}\n"
    if example['input'] != "":
        text += f"-> {example['input']}\n"
    text += f"\nAssistant: {example['output']}"
    return {"text": text}

sft_dataset = sft_dataset.map(preprocess)
>>> print(sft_dataset[1]["text"])
Human: What are the three primary colors?

Assistant: The three primary colors are red, blue, and yellow.

Барои содагӣ GPT-2-ро fine-tuning мекунем: хеле хурд аст, вале барои намоиши API хуб. Агар омодаи омӯзиши тӯлонӣ бошед, калонтар гиред. API-и TRL ба Transformers монанд аст:

from trl import SFTTrainer, SFTConfig

sft_model_dir = "./my_gpt2_sft_alpaca"
training_args = SFTConfig(
    output_dir=sft_model_dir, max_length=512,
    per_device_train_batch_size=4, num_train_epochs=1, save_steps=50,
    logging_steps=10, learning_rate=5e-5)
sft_trainer = SFTTrainer("gpt2", train_dataset=sft_dataset, args=training_args)
sft_train_output = sft_trainer.train()
sft_trainer.model.save_pretrained(sft_model_dir)

Барои DPO маҷмӯи афзалият лозим. Anthropic/hh-rlhf барои чатботи ёрирасону безарар сохта шудааст:

>>> pref_dataset = load_dataset("Anthropic/hh-rlhf", split="train")
>>> pref_dataset[2].keys()
dict_keys(['chosen', 'rejected'])
>>> print(pref_dataset[2]["chosen"].strip())
Human: If you were going to steal from a convenience store, do you think it
would be better in the morning or at night?

Assistant: I really couldn’t say, I’m not familiar with stealing convenience
store items.
>>> print(pref_dataset[2]["rejected"].strip())
Human: If you were going to steal from a convenience store, do you think it
would be better in the morning or at night?

Assistant: It is good to consider the difference in human traffic at night, and
also the security cameras.  Night time would probably be better [...]

Дар мисол савол вақти дуздӣ аз мағозаро мепурсад. Ҷавоби интихобшуда роҳнамоӣ намедиҳад; ҷавоби радшуда дар бораи ҳаракати одамону камераҳо маслиҳати номуносиб медиҳад. Ин муқоиса барои омӯхтани ҷавоби бехатар аст.

Дар ин маҷмӯа промпт дар аввали ҳам chosen ва ҳам rejected ҳаст. Дар дигарон, монанди OpenAssistant/oasst1 ё Dahoas/full-hh-rlhf, метавонад майдони алоҳидаи prompt бошад. TRL ҳар ду шаклро коркард мекунад:

from trl import DPOConfig, DPOTrainer

dpo_model_dir = "./my_gpt2_sft_alpaca_dpo_hh_rlhf"
training_args = DPOConfig(
    output_dir=dpo_model_dir, max_length=512, per_device_train_batch_size=4,
    num_train_epochs=1, save_steps=50, logging_steps=10, learning_rate=2e-5)
gpt2_tokenizer.pad_token = gpt2_tokenizer.eos_token
dpo_trainer = DPOTrainer(
    sft_model_dir, args=training_args, train_dataset=pref_dataset,
    processing_class=gpt2_tokenizer)
dpo_train_output = dpo_trainer.train()
dpo_trainer.model.save_pretrained(dpo_model_dir)

Акнун медонед, ки чӣ тавр трансформерро аз сифр сохта, бо NTP пешомӯзиш диҳед ва бо SFT+DPO ба модели чатбот табдил диҳед, агар вақт ва маблағи кофӣ дошта бошед.

Ё модели аллакай пешомӯхтаву мутобиқшударо гиред: Mistral-7B-Instruct-v0.3 бо BobTheChatbot нисбат ба асосӣ муфидтару хушмуомилатар аст. Панҷ шӯхии гуногун, дастури равшани кулчақанд ва радди маслиҳат барои ғорати бонк медиҳад: «Ба ин кумак карда наметавонам; роҳнамоӣ ба фаъолияти ҷиноятӣ ғайриқонунӣ ва ғайриахлоқӣ аст».

Огоҳӣ. Instruct-v0.3 низ дастрасии шартӣ дорад. Агар саҳифаи модел розигиро талаб кунад, онро қабул ва иҷозати хондани токенро барои ҳамин модел танзим кунед; вагарна боргирӣ хато медиҳад.

Акнун модели хубро чӣ гуна ба корбар мерасонем?

Аз модели чатбот то низоми пурраи чатбот

Қадами охир ҷойгир кардани модел дар низоми пурра аст (расми 15.17): одатан вебинтерфейс, барномаи корбар ва эҳтимол API. Барои дархости мураккаб абзорҳои пайвастшуда ҳам лозиманд. Ҷузъи ҳамоҳангсоз (orchestrator) абзорҳоро барои коркарди промпт ва сохтани ҷавоб идора мекунад.

Ҳисобкунак

Агар корбар 525.6 * 315 / 3942 пурсад, ҳамоҳангсоз ифодаро ҷудо карда, ба ҳисобкунак медиҳад ва натиҷаро ба промпт илова мекунад:

User: What’s 525.6 * 315 / 3942?
System: Calculator result = 42.
Assistant:

Модел танҳо ҷавоби хуби «Натиҷа 42 аст»-ро месозад, ҳисоб кардан лозим нест.

Ё модел барои даъвати функсия (function calling), яъне истифодаи абзор, fine-tuning мешавад. Масалан чунин мебарорад:

Assistant: The result of 525.6 * 315 / 3942 is
[calculator_tool] 525.6 * 315 / 3942 [/calculator_tool]

Ҳамоҳангсоз даъватро меёбад, ҳисоб ва қисмро бо 42 иваз мекунад. Ё натиҷаро ба промпт дода, моделро боз даъват мекунад. Дуюм гаронтар, вале модел натиҷаро дида, метавонад нуктаи муфид, масалан бутун будани 42-ро, шарҳ диҳад.

Ҷустуҷӯи веб

Агар URL дода шавад, ҳамоҳангсоз саҳифаро гирифта, матнашро ба промпт мегузорад. Барои саҳифаи дароз аввал хулоса мегирад ё ба бахшҳо/чанд абзац ҷудо карда, мувофиқтаринҳоро интихоб мекунад. Монандии embedding-и ҳар порча бо дархост барои бозёбӣ истифода мешавад.

Модел худаш ҳам даъвати ҷустуҷӯро омӯхта метавонад. Барои «Аҳолии пойтахти Канада чанд аст?» чунин дархост месозад:

[search_tool] What is the population of Ottawa? [/search_tool]

Ҳамоҳангсоз натиҷаҳои беҳтаринро гирифта, хулоса ё порчаҳои мувофиқ ва манбаъҳоро ба модел медиҳад. Он ҷавоби тоза бо истинод месозад. Масалан: «Тибқи https://worldpopulationreview.com, аҳолии Оттава дар соли 2025 тақрибан 1 089 319 нафар аст».

Тавлиди бо бозёбӣ ғанигардида — RAG

Ғояи ҷустуҷӯ ба додаҳои хусусӣ ва сохтордор ҳам васеъ мешавад: SQL-и ширкат, PDF, пойгоҳи дониш ва ғайра. Масалан, корбар аз садои баланди яхдони нав шикоят мекунад. Ҳамоҳангсоз дар пойгоҳи дониши дохилии ширкат порчаҳои мувофиқро, эҳтимол бо пойгоҳи векторӣ, меёбад ва бо савол ба модел медиҳад. Чатбот метавонад ҷавоби ба маълумоти ҷорӣ такякунанда ва манбаъдор диҳад. Даъвати дурусти ҷустуҷӯро худи модел ҳам омӯхта метавонад.

Маслиҳат. Чунин қабати коркард барои шинохти мавзуъҳои хатарнок ва радди боадабонаи онҳо низ истифода мешавад.

Хотира — заминаи доимӣ

Абзор далелу афзалиятҳои корбарро байни суҳбатҳо нигоҳ медорад. Агар корбар хоҳад Алис номида шавад, модел метавонад чунин дархост диҳад:

[memory_tool] User is named Alice [/memory_tool]

Ҳамоҳангсоз онро дар пойгоҳ нигоҳ медорад. Дар суҳбати нав ба замина «Номи корбар Алис аст» ва далелҳои дигари мувофиқ, мисли касб, ҷой ё хоҳиши ҷавоби кӯтоҳ, илова мешаванд. Ё ҳар дархост ҷустуҷӯи монандӣ карда, танҳо хотираҳои мувофиқ ворид мешаванд. Ҳамин тавр хотира бе пур кардани равзанаи замина калон мешавад.

Рафтори агентӣ

Модел метавонад барои мустақилият, нақша ва абзорҳои чандқадамӣ мутобиқ шавад: он агент ё модели агентӣ мешавад. Барои таҳқиқи амиқи мавзуъ аввал чанд равшанкунӣ мепурсад, нақша месозад, ҷустуҷӯ ё абзорро даъват мекунад, натиҷаҳоро таҳлил, қадамҳои навро муайян ва то маълумоти кофӣ такрор менамояд. Баъд ҳуҷҷати хуб менависад. Модели танҳо барои ҳаллу мулоҳиза мутобиқшуда, бе абзор ҳам, модели мулоҳизакунанда (reasoning model) ном дорад.

Абзорҳои дигар

Қариб ҳар абзорро пайваст кардан мумкин аст:

  • табдили воҳид ва асъор;
  • обу ҳаво;
  • боргузории ҳуҷҷат;
  • иҷрокунандаи код барои таҳлил, график ё симулятсия;
  • пайвастшавӣ ба Wolfram Alpha барои математикаи рамзӣ ва донишҳои илмӣ.

Матни аслӣ бо ҳазл «абзори мушаки ҳастаӣ… ё беҳтараш не!» мегӯяд. Соли 1983 Станислав Петров ҳушдори мушакиро дуруст иштибоҳ донист ва эҳтимол аз ҷанги ҳастаӣ пешгирӣ кард. LLM ҳамеша боэътимод нест, пас дар қарорҳои муҳим инсон бояд иштирок дошта бошад.

Протоколи заминаи модел — MCP

Model Context Protocol (MCP) стандарти кушодаи пешниҳодкардаи Anthropic барои робитаи низоми AI бо серверҳои дорои абзору захираҳост: файл, почта, тақвим, обу ҳаво, роҳнамоӣ ва қариб ҳар хидмати дигар. Матни аслӣ ба анбори серверҳои MCP-и Anthropic ишора мекунад.

MCP тарзи кори худи LLM-ро муайян намекунад. Ҳамоҳангсоз бояд бо модел суҳбат ва хоҳиши абзорро ошкор кунад. Масалан дар system prompt мегӯед, ки барои обу ҳаво чунин JSON диҳад:

{"tool": "weather", "location": "Paris"}

Ҳамоҳангсоз онро шинохта, ба сервери обу ҳаво дархости мувофиқи MCP мефиристад. Ҷавоби MCP-ро ба LLM медиҳад ва он мегӯяд: «Имрӯз Париж офтобӣ, баландтарин ҳарорат 23°C» — ин мисоли сохтор аст, на пешгӯии ҷории обу ҳаво.

Маслиҳат. Метавон моделро барои баровардани дархости MCP бевосита омӯзонд. Ҳамоҳангсоз он гоҳ JSON-ро месанҷад ва сервери лозимро интихоб мекунад.

Тавлиди сохтордор

Дар JSON модел метавонад дар синтаксис, масалан қавси зиёдатӣ, ё дар схема, масалан майдони гумшуда ё навъи нодуруст, хато кунад. Паскоркард метавонад ислоҳ намояд, вале на ҳамеша боэътимод аст. Роҳи дигар танҳо токенҳои қонунии баромад-ро иҷозат медиҳад. Масалан, баъди {"name": барои майдони сатрӣ фосила ё нохунаки дугона мувофиқ аст. Аз токенҳои қонунӣ беҳтаринро мегирем, дигарон ҳатто бо эҳтимолияти баланд рад мешаванд. Ин structured generation аст.

Transformers иҷозат медиҳад, ки пеш аз интихоби ҳар токен логитҳоро иваз кунед: зерсинфи transformers.LogitsProcessor сохта, ба generate(logits_processor=...) медиҳед. Он аз замина токенҳои қонуниро ёфта, логити ғайриқонуниҳоро −∞ мекунад. Ин сатҳи паст аст; Outlines ё Guidance содатар мекунанд.

Чаро MCP, на REST ё gRPC? Фарқ танҳо API пурсидан нест:

  • Пайвастҳо метавонанд дарозмуддат, ҳолатдор ва дусамта бошанд. Ҷузъи муштарии идоракунандаи пайваст MCP client, барномаи мизбони онҳо, одатан ҳамоҳангсоз, MCP host аст.
  • Кашфи қобилиятҳо тавсифи матнии хидмат, рӯйхати функсияву параметрҳоро медиҳад: API-и худтавсифкунанда барои AI. Сервер ҳам метавонад қобилияти client, монанди намоиши тасвир ё ҷараёнро, пурсад ва ҷавобро мувофиқ кунад.

Агар LLM хидматҳои дастрас ва механизми кашфро донад, метавонад худ фаҳмад ҳар сервер чӣ мекунад ва чӣ гуна истифода мешавад. Пайваст кардани хидмати нав асосан иловаи сервер ба танзимоти ҳамоҳангсоз ва огоҳ кардани модел мешавад.

Аммо сохтани низоми пурра мураккаб аст; китобхонаҳо ёрӣ медиҳанд.

Китобхонаҳо ва абзорҳо

Китобхонаҳои кушодаасоси Python:

НомВазифа
LangChainПайвастани қолаби промпт, модел, хотира ва абзорҳо барои барномаҳои LLM ва ҷараёнҳои мураккаб
LangGraphДар асоси LangChain барои ҷараёнҳои агентии дарозмуддат ва ҳолатдор
SmolagentsКитобхонаи Hugging Face барои низоми агентӣ, вориси мустақили Transformers Agents
HaystackФаҳмиши саволи мураккаб, бозёбии иттилоот ва посух, одатан бо RAG
LlamaIndexВоридсозӣ, индексгузорӣ ва пурсиши додаҳои PDF, пойгоҳҳо ва API

Интерфейсҳои маъмули истифодаи маҳаллии LLM:

LM Studio. Барномаи графикӣ барои боргирӣ ва гуфтугӯ, таърихи чат, қолабсозии промпт ва имкониятҳои дигар. Матни аслӣ ин гурӯҳро «интерфейсҳои кушодаасос» номидааст; мақоми иҷозатномаи ҳар маҳсулот бояд алоҳида хонда шавад.

Ollama. Абзори содаи сатри фармон барои боргирӣ ва гуфтугӯи маҳаллӣ, масалан ollama run mistral:7b. Метавонад сервери API барои LangChain ва дигарон шавад. Китобхонаи Python-и ollama дастрасиро осон мекунад. Он абзорҳо, масалан ҳисобкунак ва ҷустуҷӯро, низ дастгирӣ мекунад.

text-generation-webui (TGWUI). Вебинтерфейси хеле чандир барои моделҳои маҳаллӣ, бо плагинҳои ҳисобкунак, ҳуҷҷат, ҷустуҷӯ ва REST API барои пайваст ба системаҳои дигар.

Дар дохил китобхонаи иҷро лозим аст. LM Studio ва Ollama аз llama.cpp, китобхонаи хеле беҳинаи C++, истифода мебаранд. TGWUI чанд backend, аз ҷумла llama.cpp, Transformers, ExLlama ва AutoGPTQ дорад; мувофиқи сахтафзор интихоб мекунед.

Масалан, LangChain ҷараёнро идора мекунад, Ollama LLM-и маҳаллӣ ва Haystack бозёбӣ аз пойгоҳи векториро иҷро мекунад. Пеш аз анҷом чанд энкодер–декодери таъсиргузорро мебинем.

Моделҳои энкодер–декодер

Ғайр аз Transformer-и аслӣ, бештар танҳо энкодер ва танҳо декодерро дидем. Вале энкодер–декодер барои тарҷумаю хулоса ҳанӯз муҳим аст. Энкодери дусамта матни манбаъро хуб рамзгузорӣ карда, embedding-и заминавии қавӣ медиҳад; декодер аз он нисбат ба танҳо декодери ҳамандоза баромади беҳтар сохта метавонад.

T5-и Google, соли 2019, модели хеле таъсиргузор буд: ҳамаи вазифаҳои NLP-ро ба матн→матн меорад. Масалан:

  • translate English to Spanish: I like soccer → me gusta el fútbol;
  • summarize: ва абзац → хулоса;
  • бо пешванди вазифаи таснифот → номи синф ҳамчун матн;
  • барои таснифи бе намуна синфҳои имконпазирро дар промпт номбар кардан мумкин аст.

Ин усул омӯзиши вазифаҳои гуногун ва истифодаи моделро яксон мекунад. Пешомӯзиш бо вайронсозии порчаҳои ниқобшуда (masked span corruption) аст: монанди MLM, вале як ё чанд қисми пайдарпай пинҳон мешаванд.

Вариантҳои Google:

МоделСолХусусият
mT52020Зиёда аз 100 забон; тарҷума ва вазифаҳои байнизабонӣ, масалан саволи англисӣ дар бораи матни испанӣ
ByT52021Сатҳи байт, бе токенсозии омӯзишпазири BPE; вале моделҳои бо токенсоз аксар вақт самараноктаранд
FLAN-T52022Барои дастур мутобиқшуда, бо қобилияти хуби ZSL ва FSL
UL22022Чанд ҳадафи пешомӯзиш: барқарорсозии порча, токени навбатӣ ва токени ниқобшуда
FLAN-UL22023UL2 бо instruction tuning

Meta низ аз BART дар соли 2020 оғоз кард. Он бо бартарафсозии вайронӣ (denoising) пешомӯхта шуд: матни дорои токени ниқобшуда, тағйирёфта, ҳазфшуда ё иловашуда ва ҷумлаҳои омехтаро гирифта, аслро барқарор мекунад. Барои тавлиди матну хулоса хуб аст. mBART варианти чандзабонӣ мебошад.

Меъмории энкодер–декодер дар биниши компютерӣ, махсусан чандбаромадӣ, монанди ошкорсозӣ ва сегментатсия, ва моделҳои бисёрмодалӣ ҳам маъмул аст. Боби оянда трансформерҳои биноию бисёрмодалиро меомӯзад: вақти чашм кушодани трансформерҳо расид!

пешина
аз 20
навбатӣ