قدرت کمیت: کوچک کردن GPT2 ، سرعت رها کردن

تصور کنید که یک الگوی زبان قدرتمند مانند GPT-2-که قادر به تهیه داستان ، پاسخ دادن به سؤالات و تقلید از متن انسانی است-و فشرده سازی آن را به یک نسخه لاغر و سریعتر بدون اینکه قابلیت های آن را فشرده کنید ، استفاده کنید.
این نوید کمیت است: تکنیکی که دقت محاسبات یک مدل را کاهش می دهد ، و دقت حاشیه ای را برای سودهای بهره وری چشمگیر انجام می دهد.
فاز 0: تنظیم فنی
!pip install torch transformers accelerate bitsandbytes psutil
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
import torch
import time
import gc
def get_memory_usage():
return torch.cuda.memory_allocated() / 1e6 if torch.cuda.is_available() else 0
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model_name = "gpt2"
input_text = "Once upon a time"
فاز 1: پایه – دقت کامل (FP32)
این آزمایش با GPT-2 در وضعیت طبیعی آن آغاز می شود: دقت نقطه شناور 32 بیتی (FP32). این حالت “قدرت کامل” مدل است-بسیار دقیق اما منابع پررنگ.
- حافظه: بارگیری مدل FP32 مصرف می شود 511 مگابایت حافظه پردازنده گرافیکی.
- سرعت: تولید 50 نشانه از سریع “روزی یک بار” برداشتن 1.76 ثانیهبشر
- ردپای پس از تمیز کردن: حتی پس از حذف مدل ، 458 مگابایت حافظه همچنان اشغال شده است.
FP32 کار می کند ، اما حجیم است.
# Load tokenizer and base model
tokenizer = AutoTokenizer.from_pretrained(model_name)
print(f"Pre-load memory: {get_memory_usage()} MB")
# Full precision model
model_fp32 = AutoModelForCausalLM.from_pretrained(model_name).to(device)
print(f"Post-load memory: {get_memory_usage()} MB") # 511.15 MB
# Inference measurement
inputs = tokenizer(input_text, return_tensors="pt").to(device)
start_time = time.time()
output = model_fp32.generate(**inputs, max_length=50)
inference_time = time.time() - start_time # 1.76s
# Cleanup protocol
del model_fp32, inputs
gc.collect()
torch.cuda.empty_cache()
فاز 2: پیرایش چربی-اندازه گیری 8 بیتی (INT8)
کمیت 8 بیتی را وارد کنید ، جایی که وزن و فعال سازی به جای شناورها به عنوان عدد صحیح ذخیره می شوند. تحول فوری است:
- حافظه: مدل int8 فقط با 187 مگابایت–63 ٪ کوچکتر از fp32.
- سرعت: استنتاج شتاب می گیرد 1.38 ثانیه، الف بهبود 22 ٪بشر
- ردپای پس از تمیز کردن: حافظه به 139 مگابایت بعد از حذف
این مدل سبک تر ، سریعتر و هنوز هم کاربردی است. ارتقاء واضح
# 8-bit configuration
quant_config_8bit = BitsAndBytesConfig(load_in_8bit=True)
print(f"Pre-load memory: {get_memory_usage()} MB") # 9.18 MB
model_int8 = AutoModelForCausalLM.from_pretrained(
model_name,
quantization_config=quant_config_8bit
)
# Dynamic input handling
inputs_int8 = tokenizer(input_text, return_tensors="pt").to(model_int8.device)
start_time = time.time()
output = model_int8.generate(**inputs_int8, max_length=50) # 1.38s
فاز 3: لبه بهره وری-کمیت 4 بیتی (INT4)
اکنون ما بیشتر فشار می آوریم. با کمیت 4 بیتی ، وزنه ها به دقت نزدیک به حد متوسط فشرده می شوند و محاسبات از شناورهای 16 بیتی برای ثبات استفاده می کنند.
- حافظه: مدل INT4 وزن دارد 149 مگابایتبا 71 ٪ سبک تر از fp32.
- سرعت: زمان استنتاج به 1.08 ثانیه، الف 39 ٪ سود بیش از FP32.
- ردپای پس از تمیز کردن: حافظه به 58 مگابایت– کسری از اصلی.
این فقط بهینه سازی نیست ؛ این یک مزاحمت است.
# 8-bit configuration
quant_config_8bit = BitsAndBytesConfig(load_in_8bit=True)
print(f"Pre-load memory: {get_memory_usage()} MB") # 9.18 MB
model_int8 = AutoModelForCausalLM.from_pretrained(
model_name,
quantization_config=quant_config_8bit
)
# Dynamic input handling
inputs_int8 = tokenizer(input_text, return_tensors="pt").to(model_int8.device)
start_time = time.time()
output = model_int8.generate(**inputs_int8, max_length=50) # 1.38s
تجارت: دقت در مقابل عملی
کمیت رایگان نیست. کاهش دقت می تواند به طور ظریف دقت مدل را تخریب کند ، اما برای بسیاری از کارها – مانند تولید متن گاه به گاه – تفاوت غیرقابل تصور است. آنچه ما به دست می آوریم بسیار بیشتر از هزینه است:
- راندمان حافظه:FP32: 511 MB → INT8: 187 MB → INT4: 149 MB.
نتیجه: مدل ها در محدودیت های حافظه محکم تر قرار می گیرند و امکان استقرار در GPU های مصرف کننده یا دستگاه های Edge را فراهم می کنند.
- سرعت استنتاج:FP32: 1.76s → Int8: 1.38s → Int4: 1.08s.
نتیجه: پاسخ های سریعتر برای برنامه های زمان واقعی ، از Chatbots گرفته تا تولید محتوای خودکار.
چگونه کار می کند: مکانیک فشرده سازی
در هسته آن ، مقادیر با دقت بالا (مانند شناورهای 32 بیتی) به قالبهای با دقت پایین (عدد صحیح 8- یا 4 بیتی) نقشه می کند. به عنوان مثال:
- fp32 از 32 بیت در هر شماره استفاده می کند ، جزئیات خوب را ضبط می کند اما خواستار منابع سنگین است.
- you8/you4 از بیت های کمتری استفاده کنید ، مقادیر تقریبی با حداقل ضرر.
در bitsandbytes
کتابخانه این کار را به طور خودکار انجام می دهد ، وزن ها را بازپرداخت می کند و محاسبات را برای حفظ ثبات تنظیم می کند.
اثبات بصری
یک مقایسه جانبی این استدلال را مهر می کند:
- استفاده از حافظه (نمودار نوار): برج های FP32 بیش از INT8 و INT4 ، نشان دهنده کاهش شدید خواسته های منابع.
- زمان استنتاج (طرح خط): شیب رو به پایین از FP32 به INT4 دستاوردهای سرعت را برجسته می کند.
غذای آماده؟ کمیت فقط یک پاورقی فنی نیست – این یک ابزار عملی برای دموکراتیک کردن هوش مصنوعی است.
# Visualization setup
import matplotlib.pyplot as plt
quantization_types = ['FP32', 'INT8', 'INT4']
fig, ax1 = plt.subplots(figsize=(8, 6))
bars = ax1.bar(quantization_types, memory_usages, color='blue', alpha=0.7)
ax1.set_ylabel('Memory (MB)', color='blue')
# Annotation logic
for bar in bars:
yval = bar.get_height()
ax1.text(bar.get_x() + bar.get_width()/2, yval+30,
f'{yval:.2f}', ha='center', va='bottom',
color='blue', fontweight='bold')
# Dual-axis formatting
ax2 = ax1.twinx()
ax2.plot(quantization_types, inference_times, color='red',
marker='o', linewidth=2)
ax2.set_ylabel('Time (sec)', color='red')
plt.title('Quantization Trade-offs')
plt.show()
حرف آخر
از طریق کمیت ، ما GPT-2 را از یک Behemoth سنگین منابع به یک ابزار زیرک و کارآمد تبدیل کرده ایم-با بیان اینکه با تکنیک های مناسب ، حتی غول ها می توانند یاد بگیرند که به آرامی حرکت کنند.
این پیاده سازی قدرت کمیت را از طریق کد و اندازه گیری های مشخص نشان می دهد. با اصلاح فقط 10-15 خط پیکربندی و استقرار کمیت ، ما به دست آوردیم:
- 71 ٪ کاهش در ردپای حافظه
- 39 ٪ سرعت استنباط سریعتر
اگر کنجکاو هستید و می خواهید برای آزمایش کامل به نوت بوک کامل بپردازید – به Google Colab بروید.