Modele și platforme AI

Cadru de inferență Microsoft aduce modelele de limbaj mari de 1 bit pe dispozitive locale

mm
Adaugă Unite.AI la sursele tale preferate pe Google

Pe 17 octombrie 2024, Microsoft a anunțat BitNet.cpp (MSFT ), un cadru de inferență proiectat pentru a rula modele de limbaj mari cuantificate la 1 bit. BitNet.cpp reprezintă o progres semnificativ în Gen AI, permițând implementarea eficientă a modelelor de limbaj mari de 1 bit pe procesoare standard, fără a necesita GPU-uri scumpe. Acest lucru democratizează accesul la modelele de limbaj mari, făcându-le disponibile pe o gamă largă de dispozitive și oferind noi posibilități în aplicațiile de inteligență artificială pe dispozitive.

Înțelegerea modelelor de limbaj mari de 1 bit

Modelele de limbaj mari (LLM) au necesitat în mod tradițional resurse computaționale semnificative din cauza utilizării numerelor cu virgulă mobilă de înaltă precizie (în general FP16 sau BF16) pentru greutățile modelului. Această necesitate a făcut implementarea modelelor de limbaj mari scumpă și consumatoare de energie.

În esență, modelele de limbaj mari de 1 bit utilizează tehnici de cuantificare extremă pentru a reprezenta greutățile modelului utilizând numai trei valori posibile: -1, 0 și 1, de unde și termenul de “1,58 bit” (deoarece necesită puțin mai mult de un bit pentru a codifica trei stări).

Sistemul de greutăți ternar

Conceptul

Cuantificarea la 1 bit în BitNet.cpp este un sistem de greutăți ternar. BitNet funcționează cu numai trei valori posibile pentru fiecare parametru:

  • -1 (negativ)
  • 0 (neutru)
  • 1 (pozitiv)

Acest lucru duce la o cerință de stocare de aproximativ 1,58 biți pe parametru, de unde și numele BitNet b1.58. Reducerea drastică a lățimii bitului parametrului conduce la o reducere impresionantă a utilizării memoriei și a complexității computaționale, deoarece majoritatea multiplicărilor cu virgulă mobilă sunt înlocuite cu simple adunări și scăderi.

Baza matematică

Cuantificarea la 1 bit implică transformarea greutăților și a activărilor în reprezentarea lor ternară prin următorii pași:

1. Cuantificarea greutăților

Cuantificarea greutăților implică centralizarea lor în jurul mediei (α), rezultând o reprezentare ternară. Transformarea este exprimată matematic astfel:

Wf​=Sign(W−α)

Unde:

  • W este matricea de greutăți originală.
  • α este media greutăților.
  • Sign(x) returnează +1 dacă x > 0 și -1 în caz contrar.

2. Cuantificarea activărilor

Cuantificarea activărilor asigură că intrările sunt limitate la o lățime de bit specificată:

x^e​=Quant(x)=Clip(γx×Qb​​,−Qb​+ϵ,Qb​−ϵ)

Unde:

  • Qb = 2(b−1)2^{(b-1)} este nivelul maxim de cuantificare pentru lățimea de b biți.
  • γ este valoarea absolută maximă a lui x (notată cu ∣∣x∣∣∞).
  • ε este un număr mic pentru a preveni depășirea în timpul calculelor.

3. Operația BitLinear

Stratul BitLinear înlocuiește multiplicările matriciale tradiționale cu o operație simplificată:

y=Wf​×x^e​×(Qb​βγ​)

Unde:

  • β este un factor de scalare utilizat pentru a minimiza erorile de aproximare.
  • γ scalează activările.
  • Q_b este factorul de cuantificare.

Această transformare permite calcule eficiente, păstrând în același timp performanța modelului.

Implicații de performanță

Eficiență de memorie

Sistemul de greutăți ternar reduce semnificativ cerințele de memorie:

  • Modelele de limbaj mari tradiționale: 16 biți pe greutate
  • BitNet.cpp: 1,58 biți pe greutate

Această reducere se traduce într-o economie de aproximativ 90% a memoriei comparativ cu modelele tradiționale de 16 biți, permițând modele mai mari să se încadreze în aceleași constrângeri de hardware.

Eficiență energetică

Viteză de inferență, eficiență energetică (Apple M2)

 

Viteză de inferență: Mai rapidă pe ambele procesoare

Viteză de inferență, eficiență energetică (i7-13700H)

1. Viteză de inferență: Mai rapidă pe ambele procesoare

Viteza de inferență este reprezentată ca numărul de tokeni procesați pe secundă. Iată o descriere a observațiilor:

  • Pe Apple M2 Ultra: BitNet.cpp atinge până la 5,07x viteza pentru modele mai mari (30B) comparativ cu Llama.cpp, cu o viteză maximă de 593,43 tokeni pe secundă pentru un model de 125M, ceea ce reprezintă o 1,37x viteză. Pentru modele mai mari, cum ar fi cele de 3,8B și 7B, BitNet.cpp menține o viteză de peste 84,77 tokeni pe secundă, demonstrând eficiența sa la scară largă.
  • Pe Intel i7-13700H: BitNet.cpp atinge îmbunătățiri și mai dramatice ale vitezei. La dimensiunea modelului de 7B, BitNet.cpp oferă o creștere incredibilă de 5,68x a vitezei comparativ cu Llama.cpp. Pentru modele mai mici, cum ar fi cel de 125M, procesează 389,08 tokeni pe secundă, ceea ce reprezintă o 2,37x viteză mai mare decât Llama.cpp.

2. Eficiență energetică: Un joc schimbat pentru dispozitivele de margine

Graficele furnizate includ, de asemenea, comparații de costuri energetice, care arată o reducere semnificativă a consumului de energie pe token procesat:

  • Pe Apple M2 Ultra: Economia de energie a BitNet.cpp este substanțială. Pentru modelul de 700M, consumă 55,4% mai puțină energie pe token comparativ cu Llama.cpp, scăzând de la 0,314 la 0,140. Această tendință continuă pentru modele mai mari, modelul de 70B arătând o reducere de 70,0% a consumului de energie.
  • Pe Intel i7-13700H: BitNet.cpp oferă 71,9% economie de energie pentru modelul de 700M, consumul scăzând de la 1,367 la 0,384. Deși datele despre consumul de energie pentru modelul de 70B în Llama.cpp nu sunt disponibile, BitNet.cpp rămâne eficient, cu un consum de energie de 17,33 pentru modelul de 70B.

3. Depășirea baremului de citire umană

Una dintre cele mai interesante observații din aceste grafice este referirea la viteza de citire umană, marcată la 5-7 tokeni pe secundă. Această linie roșie arată că ambele implementări, în special BitNet.cpp, pot depăși cu ușurință viteza de citire umană chiar și pentru cele mai mari modele:

  • Pe Apple M2 Ultra, BitNet.cpp depășește viteza de citire umană pentru toate dimensiunile modelului, cea mai mică viteză fiind de 8,67 tokeni pe secundă pentru un model de 70B.
  • Pe Intel i7-13700H, modelul de 100B atinge încă 1,70 tokeni pe secundă, aproape atingând gama inferioară a vitezei de citire umană, în timp ce toate modelele mai mici depășesc acest barem.

Considerații de antrenare

Estimatorul Straight-Through (STE)

Deoarece cuantificarea la 1 bit introduce funcții nediferențiate, antrenarea implică o tehnică specializată cunoscută sub numele de Estimatorul Straight-Through (STE). În această abordare, gradientul curge nemodificat prin punctele nediferențiate. Iată o implementare simplificată în Python:

class StraightThroughEstimator(Function):
@staticmethod
def forward(ctx, input):
return input.sign()

@staticmethod
def backward(ctx, grad_output):
return grad_output

Antrenarea cu precizie mixtă

Pentru a menține stabilitatea în timpul antrenării, se utilizează precizie mixtă:

  • Greutăți și activări: Cuantificate la precizie de 1 bit.
  • Gradient și stări ale optimizatorului: Stocate într-o precizie mai mare.
  • Greutăți latente: Menținute într-o precizie ridicată pentru a facilita actualizări precise în timpul antrenării.

Strategia de rată de învățare mare

O provocare unică cu modelele de 1 bit este aceea că actualizările mici nu pot afecta greutățile binarizate. Pentru a contracara acest lucru, rata de învățare este crescută, asigurând o convergență mai rapidă și o optimizare mai bună comparativ cu abordările tradiționale.

Cuantificarea și normalizarea grupului

BitNet.cpp introduce cuantificarea și normalizarea grupului pentru a îmbunătăți paralelismul modelului. În loc de calcularea parametrilor pentru întreaga matrice de greutăți, BitNet împarte greutățile și activările în multiple grupuri (G).
Acest grupare permite procesarea paralelă eficientă fără comunicare suplimentară între grupuri, permițând antrenarea și inferența modelului la scară largă.

Note de implementare și optimizări

Optimizarea CPU

BitNet.cpp utilizează mai multe optimizări de nivel scăzut pentru a atinge performanța maximă a CPU:

  • Operații vectorizate: Utilizează instrucțiuni SIMD pentru manipularea eficientă a biților.
  • Acces la memorie prietenos cu cache-ul: Structurează datele pentru a minimiza ratele de eroare ale cache-ului.
  • Procesare paralelă: Distribuie sarcina de lucru eficient pe multiple nuclee CPU.

Iată un exemplu de funcție cheie care implementează cuantificarea și inferența în BitNet:

def bitlinear_forward(input, weight, scale):
# Cuantifică intrarea utilizând cuantificarea absmax
input_q = quantize(input)

# Realizează multiplicarea matricială binară
output = binary_matmul(input_q, weight)

# Scalează ieșirea pentru a se potrivi cu precizia originală
return output * scale

def quantize(x):
# Realizează cuantificarea absmax
scale = torch.max(torch.abs(x))
return torch.clamp(x / scale, -1, 1) * scale
[/code]

Modele suportate

Lansarea curentă a BitNet.cpp suportă următoarele modele de limbaj mari de 1 bit disponibile pe Hugging Face:

  • bitnet_b1_58-large (0,7 miliarde de parametri)
  • bitnet_b1_58-3B (3,3 miliarde de parametri)
  • Llama3-8B-1.58-100B-tokens (8,0 miliarde de parametri)

Aceste modele sunt disponibile public pentru a demonstra capacitățile de inferență ale cadrului. Deși nu au fost antrenate sau lansate oficial de Microsoft, ele ilustrează versatilitatea cadrului.

Ghid de instalare

Pentru a începe cu BitNet.cpp, urmați pașii de mai jos:

Precondiții

  1. Python >= 3.9
  2. CMake >= 3.22
  3. Clang >= 18
  4. Conda (recomandat)

Pentru utilizatorii Windows, Visual Studio ar trebui să fie instalat cu următoarele componente activate:

  • Dezvoltare de birou cu C++
  • Unelte C++-CMake pentru Windows
  • Git pentru Windows
  • Compilator C++-Clang pentru Windows
  • Suport MS-Build pentru setul de instrumente LLVM (Clang)

Pentru utilizatorii Debian/Ubuntu, este disponibil un script de instalare automată:

bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)"

Instalare pas cu pas

  1. Clonați depozitul:
    git clone --recursive https://github.com/microsoft/BitNet.git

    cd BitNet
  2. Instalați dependențele:
    # Creați un mediu Conda nou (recomandat)
    conda create -n bitnet-cpp python=3.9
    conda activate bitnet-cpp


    pip install -r requirements.txt
  3. Construiți și pregătiți proiectul: Puteți descărca direct un model de pe Hugging Face și să-l convertiți într-un format cuantificat:
    python setup_env.py --hf-repo HF1BitLLM/Llama3-8B-1.58-100B-tokens -q i2_s

    Alternativ, puteți descărca și converti manual modelul:

    huggingface-cli download HF1BitLLM/Llama3-8B-1.58-100B-tokens --local-dir models/Llama3-8B-1.58-100B-tokens

    python setup_env.py -md models/Llama3-8B-1.58-100B-tokens -q i2_s

Rularea inferenței cu BitNet.cpp

Pentru a rula inferența utilizând cadrul, folosiți următoarea comandă:

python run_inference.py -m models/Llama3-8B-1.58-100B-tokens/ggml-model-i2_s.gguf -p "Sandra a călătorit în bucătărie. Unde este Sandra?" -n 6 -temp 0.7

Explicație:

  • -m specifică calea fișierului model.
  • -p definește textul de intrare.
  • -n setează numărul de tokeni de prezis.
  • -temp ajustează aleatoritatea de eșantionare (temperatura) în timpul inferenței.

Exemplu de ieșire

Sandra a călătorit în bucătărie. Unde este Sandra?

Răspuns: Sandra este în bucătărie.

Detalii tehnice ale BitNet.cpp

Stratul BitLinear

BitNet.cpp implementează o arhitectură Transformer modificată, înlocuind multiplicările matriciale standard cu operații BitLinear. Această abordare centralizează greutățile spre zero înainte de cuantificare și le scalează pentru a reduce erorile de aproximare. Funcția de transformare cheie arată astfel:

# Funcție de binarizare pentru greutăți de 1 bit
def binarize_weights(W):
alpha = W.mean()
W_binarized = np.sign(W - alpha)
return W_binarized

Combinația greutăților centralizate și a scalării asigură că eroarea de cuantificare rămâne minimă, păstrând astfel performanța.

Impactul în industrie

BitNet.cpp ar putea avea implicații de anvergură pentru implementarea modelelor de limbaj mari:

  • Accesibilitate: Permite modelelor de limbaj mari să ruleze pe dispozitive standard, democratizând accesul la inteligența artificială puternică.
  • Eficiență costală: Reduce nevoia de GPU-uri scumpe, micșorând bariera pentru adoptare.
  • Eficiență energetică: Economisește energie prin utilizarea inferenței pe bază de CPU.
  • Inovație: Deschide noi posibilități pentru aplicațiile de inteligență artificială pe dispozitive, cum ar fi traducerea în timp real, asistenți vocali și aplicații cu focus pe confidențialitate fără dependențe de cloud.

Provocări și direcții viitoare

Deși modelele de limbaj mari de 1 bit oferă perspective promițătoare, mai există provocări. Acestea includ dezvoltarea de modele robuste de 1 bit pentru diverse sarcini, optimizarea hardware-ului pentru computația de 1 bit și încurajarea dezvoltatorilor să adopte acest nou paradigma. Explorarea cuantificării de 1 bit pentru sarcini de vedere de computer sau audio reprezintă o direcție viitoare interesantă.

Concluzie

Lansarea BitNet.cpp de către Microsoft reprezintă o avansare semnificativă. Prin permiterea inferenței eficiente de 1 bit pe procesoare standard, BitNet.cpp creează accesibilitatea și durabilitatea inteligenței artificiale. Acest cadru stabilește scena pentru modele de limbaj mari mai portabile și mai rentabile, împingând ceea ce este posibil cu inteligența artificială pe dispozitive.

Am petrecut ultimii cinci ani scufundându-mă în lumea fascinantă a Machine Learning și Deep Learning. Pasinea și expertiza mea m-au condus să contribui la peste 50 de proiecte diverse de inginerie software, cu un focus deosebit pe AI/ML. Curiozitatea mea în continuare m-a atras și spre Natural Language Processing, un domeniu pe care sunt dornic să îl explorez mai departe.