چیتشیت
نظریه اطلاعات و پایداری عددی
Information Theory and Numerical Stability
آنتروپی، آنتروپی متقاطع و واگرایی کولبک-لایبلر، سافتمکس پایدار و log-sum-exp، فرمتهای ممیز شناور، PCA و انتخاب معیار فاصله.
فهرست مطالب
فرمولهای اطلاعات
مفهومها- غافلگیری (Surprise)
- $I(x) = -\log p(x)$. پایه 2 برحسب بیت؛ پایه e برحسب نات.
- آنتروپی
- $H(P) = -\sum_x p(x) \log p(x)$. سکه سالم 1 بیت؛ سکه با احتمال 99٪ معادل 0.08 بیت.
- آنتروپی متقاطع
- $H(P,Q) = -\sum_x p(x) \log q(x)$. برچسب تکداغ (one-hot) خروجی $-\log q(\text{true class})$ میدهد.
- واگرایی کولبک-لایبلر
- $D_{KL}(P \Vert Q) = H(P,Q) - H(P)$. متقارن نیست.
- اطلاعات متقابل
- $I(X;Y) = H(X) + H(Y) - H(X,Y)$. مقدار صفر یعنی مستقل هستند.
- آنتروپی شرطی
- $H(Y \mid X) = H(X,Y) - H(X)$. انشعابهای درخت تصمیم آن را کمینه میکنند.
- پرپلکسیتی
- $e^{H(P,Q)}$ برحسب نات. پرپلکسیتی 50 یعنی انتخاب یکنواخت از میان 50 توکن.
- هموارسازی برچسبها
- $(1-\epsilon)\,\text{hard} + \epsilon / K$. با 0.1 و 4 کلاس، کلاس درست 0.925 میگیرد.
- واحدها
- 1 نات معادل 1.4427 بیت است. PyTorch و TensorFlow از نات استفاده میکنند.
مسیر پایدار تابع زیان
معماریسافتمکس پایدار، LSE و آنتروپی متقاطع
کدpython
def logsumexp_stable(values):
c = max(values) # بزرگترین نما 0 میشود
return c + math.log(sum(math.exp(v - c) for v in values))
def log_softmax_stable(logits):
c = max(logits)
lse = c + math.log(sum(math.exp(z - c) for z in logits))
return [z - lse for z in logits] # لگاریتم احتمالات، بدون سرریز
def cross_entropy_stable(true_class, logits):
log_probs = log_softmax_stable(logits)
return -log_probs[true_class] # هرگز log(0) را فراخوانی نمیکند
وظایف در کد
کار و کد| وظیفه | کد |
|---|---|
| آنتروپی برحسب بیت | entropy(probs, base=2) |
| واگرایی کولبک-لایبلر | kl_divergence(p, q, base=2) |
| پرپلکسیتی بر اساس میانگین آنتروپی متقاطع | perplexity(avg_cross_entropy, base="e") |
| سافتمکس امن | softmax_stable(logits) |
| گرادیان عددی | numerical_gradient(f, x, h=1e-5) |
| مقایسه با پسانتشار | check_gradient(analytical, numerical) |
| برش نُرم گرادیان | clip_by_norm(gradients, max_norm) |
| واریانس با میانگین بزرگ | welford_variance(values) |
فرمتهای ممیز شناور و محدودیتها
پیشفرضها| تنظیم | پیشفرض | نکته |
|---|---|---|
float64 max | 1.8e308 | 11 بیت نما، حدود 15 تا 16 رقم اعشار |
float32 max | 3.4028235e+38 | 8 بیت نما، حدود 7 تا 8 رقم اعشار |
float32 min normal | 1.175e-38 | اعداد غیراستاندارد (Denormals) تا 1.401e-45 میرسند |
float32 exp overflow | exp(89.0) | خروجی inf میدهد؛ exp(88.7) همچنان جا میشود |
float32 exp underflow | exp(-104) | خروجی 0.0 میدهد |
float16 max | 65,504 | گرادیانهای زیر حدود 6e-8 صفر میشوند |
bfloat16 max | 3.4e38 | 8 بیت نما، 7 بیت مانتیس |
float32 machine epsilon | 1.19e-7 | کوچکترین e که در آن 1.0 + e != 1.0 است |
دقت ترکیبی با مقیاسبندی تابع زیان
گامبهگام- وزنهای اصلی (Master weights)یک نسخه float32 از وزنها نگه دارید.
- گذر رو به جلوبرای سرعت، آن را با float16 اجرا کنید.
- تابع زیان (loss)برای جلوگیری از سرریز، آن را در float32 محاسبه کنید.
- مقیاسبندیتابع زیان را در یک ضریب ضرب کنید؛ مثلاً 1024.
- گام رو به عقببا float16 اجرا کنید. گرادیانها 1024 برابر بزرگترند.
- برش مقیاس (Unscale)پیش از بهروزرسانی، گرادیانها را بر 1024 تقسیم کنید.
- بهروزرسانیوزنهای اصلی float32 را تغییر دهید.
- مقیاسبندی پویااز 65536 شروع کنید. در صورت inf نصف کنید؛ پس از N گام سالم، دو برابر کنید.
باگهای عددی
عیبیابیتابع زیان بعد از چند دوره NaN میشود
- علت
- لاجیتها خیلی بزرگ بودند، سافتمکس سرریز کرد
- راهحل
- سافتمکس پایدار، کاهش نرخ یادگیری (LR)، برش گرادیان
تابع زیان روی log(num_classes) گیر کرده است
- علت
- خروجیهای تقریباً یکنواخت، بدون یادگیری
- راهحل
- بررسی برچسبها، تابع زیان و نورون مردهی ReLU
دقت اعتبارسنجی 1 تا 3 درصد پایینتر است
- علت
- دقت ترکیبی بدون مقیاسبندی تابع زیان
- راهحل
- مقیاسبندی پویای تابع زیان یا استفاده از bfloat16
نُرم گرادیان در برخی لایهها 0.0 است
- علت
- نورون مردهی ReLU یا زیرریز float16
- راهحل
- استفاده از LeakyReLU یا GELU، مقیاسبندی گرادیان
نتایج بین GPUها متفاوت است
- علت
- جمع ممیز شناور خاصیت شرکتپذیری ندارد
- راهحل
torch.use_deterministic_algorithms(True)
exp()در تابع زیان inf برمیگرداند- علت
- لاجیتهای خام بدون تفریق مقدار بیشینه
- راهحل
torch.nn.functional.log_softmax()
واگرایی پس از سوییچ به float16
- علت
- گرادیانهای زیر 6e-8، مقادیر بالای 65,504
- راهحل
- AMP همراه با مقیاسبندی تابع زیان، یا bfloat16
واریانس اشتباه برای مقادیر بزرگ
- علت
- حذف فاجعهبار
- راهحل
welford_varianceیا مرکززدایی از دادهها
پیچهای تنظیم و آستانهها
پیشفرضها| تنظیم | پیشفرض | نکته |
|---|---|---|
Gradient check `h` | 1e-5 | محدوده معمول 1e-5 تا 1e-7 |
Gradient check pass | 1e-7 | بالای 1e-3 مشکلی وجود دارد |
max_norm | 1.0 | ترنسفورمرها؛ 0.5 برای RL، 5.0 برای شبکههای ساده |
LayerNorm `epsilon` | 1e-5 | جلوگیری از تقسیم بر صفر |
Epsilon in log and divide | 1e-8 | log(x + 1e-8) |
t-SNE perplexity | 5-50 | درس از مقدار 30 استفاده میکند |
UMAP `n_neighbors` | 15 | همراه با min_dist برابر با 0.1 |
PCA cumulative variance | 0.95 | یا یک آستانه 90 تا 95 درصدی |
انتخاب معیار فاصله
دستورها| دستور | کاربرد |
|---|---|
cosine_similarity(a, b) | متن و امبدینگها؛ اندازه بردار را نادیده میگیرد |
dot_product(a, b) | سیستمهای توصیهگر؛ اندازه نشاندهنده محبوبیت است |
l2_distance(a, b) | پیکسلها و دادههای مکانی در مقیاسهای قابلمقایسه |
l1_distance(a, b) | ویژگیهای اسپارس با ابعاد بالا؛ مقاوم در برابر دادههای پرت |
linf_distance(a, b) | بدترین انحراف در یک بعد |
mahalanobis_distance(x, y, cov_matrix) | دادههای پرت با ویژگیهای همبسته |
jaccard_similarity(set_a, set_b) | مجموعهها و تگها؛ معیار IoU برای بخشبندی (segmentation) |
edit_distance(s1, s2) | رشتهها؛ درج، حذف یا جایگزینی |
کاهش ابعاد
مفهومها- نفرین ابعاد
- در 1000 بعد، نسبت بیشینه به کمینه فاصله حدود 1.02 است.
- PCA
- مرکززدایی، کوواریانس،
np.linalg.eigh، مرتبسازی بر اساس مقدار ویژه، نگه داشتن k تای برتر. - نسبت واریانس تبیینشده
- یک مقدار ویژه تقسیم بر مجموع همه مقادیر ویژه.
- انتخاب k
- حفظ 90 تا 95٪ واریانس، یافتن نقطه زانویی، یا آزمون k روی وظیفه.
- خطای بازسازی
- مجموع مقادیر ویژه حذفشده؛ خطای بالا نشانگر داده پرت است.
- t-SNE
- همسایگیهای محلی را حفظ میکند؛ تصادفی و با پیچیدگی $O(n^2)$؛ فواصل خوشهها معنایی ندارند.
- UMAP
- سریعتر از t-SNE؛ ساختار سراسری بیشتری را حفظ میکند.
- Kernel PCA
- انجام PCA در فضای ویژگی کرنل؛ کرنل RBF دایرههای هممرکز را تفکیک میکند.
پرسشها
پرسش و پاسخ- چرا مقدار بیشینه تفریق میشود؟
- بزرگترین جمله exp(0) = 1 میشود؛ حاصلجمع حداقل 1 خواهد بود.
- چرا bfloat16 برای آموزش؟
- دامنه عددی float32 را دارد؛ مقیاسبندی تابع زیان معمولاً لازم نیست.
- چرا کمینهسازی آنتروپی متقاطع؟
- با منفی درستنمایی لگاریتمی برابر است؛ H(P) مقداری ثابت است.
- چرا واگرایی KL یک فاصله نیست؟
- متقارن نیست و در نامساوی مثلثی صدق نمیکند.
- چرا فاصله واسراشتاین در GANها؟
- حتی در صورت عدم همپوشانی توزیعها، گرادیان تولید میکند.
- چرا جریمه L1 باعث وزنهای اسپارس میشود؟
- خطوط تراز تابع زیان در گوشهها با لوزی L1 برخورد میکنند.
- چرا تفاضل مرکزی؟
- خطای آن $O(h^2)$ است؛ تفاضل پیشرو خطای $O(h)$ دارد.
نکات کاربردی
نکتهها- اعداد ممیز شناور را با
==مقایسه نکنید؛ ازmath.isclose()استفاده کنید. - هنگام اشکالزدایی پس از هر گذر رو به جلو nan و inf را بررسی کنید:
math.isfinite(x). - ورودیهای تابع exp را محدود کنید:
exp(clamp(x, -80, 80)). - برش بر اساس نُرم را با
torch.nn.utils.clip_grad_norm_()انجام دهید؛ جهت گرادیان را حفظ میکند. - هر لایه یا تابع زیان جدید را با
torch.autograd.gradcheck()بررسی کنید. - با امبدینگهای نرمالشده بر اساس L2، شباهت کسینوسی و ضرب داخلی نتیجه یکسانی میدهند.