اهلا ياجماعة. نوع الهدف torch.LongTensor
سيعيق التنفيذ مثل بعض الطرق في المرجع . فهل هناك إمكانية لإضافة Arg: label_smoothing
مقابل torch.nn.CrossEntropyLoss()
، أو ربما ببساطة قم بإضافة المستندات لإظهار كيفية تحويل target
إلى one-hot vector
للعمل معها torch.nn.CrossEntropyLoss()
معًا ، أم أي طرق أخرى بسيطة؟ شكرا.
سم مكعبezyanggchanan @ zou3519bdhirshalbanDmruberry
تضمين التغريدة
بالنسبة لـ label_smoothing ، تنظر القط إلى تطبيق NJUNMT-pytorch
في الفصل NMTCritierion
انظر https://discuss.pytorch.org/t/cross-entropy-with-one-hot-targets/13580/5. يجب أن تعمل الوظيفة cross_entropy()
التي تظهر هناك مع تسميات متجانسة لها نفس أبعاد مخرجات الشبكة.
لا أعتقد أن CrossEntropyLoss()
يجب أن يدعم خيار label_smoothing
، نظرًا لأن تجانس الملصق يمكن أن يتم بعدة طرق مختلفة ويمكن أن يتم التنعيم نفسه يدويًا بسهولة بواسطة المستخدم. لكنني أوافق على أنه يجب على الأقل ذكره في المستندات حول كيفية التعامل مع الأهداف التي لا يمكن تمثيلها بقيم عددية ، أو إضافة دعم لتمرير الأهداف (k-hot / السلس) إلى CrossEntropyLoss
.
ربما نحتاج شيئًا مثل NonSparseCrossEntropy
؟ (حسنًا .. من الصعب تسميتها)
هنا هو تطبيق بلدي
class LabelSmoothingLoss(nn.Module):
def __init__(self, classes, smoothing=0.0, dim=-1):
super(LabelSmoothingLoss, self).__init__()
self.confidence = 1.0 - smoothing
self.smoothing = smoothing
self.cls = classes
self.dim = dim
def forward(self, pred, target):
pred = pred.log_softmax(dim=self.dim)
with torch.no_grad():
# true_dist = pred.data.clone()
true_dist = torch.zeros_like(pred)
true_dist.fill_(self.smoothing / (self.cls - 1))
true_dist.scatter_(1, target.data.unsqueeze(1), self.confidence)
return torch.mean(torch.sum(-true_dist * pred, dim=self.dim))
أنا أتفق معmdraw
الخيار الجيد هو القيام بذلك في خطوتين:
def smooth_one_hot(true_labels: torch.Tensor, classes: int, smoothing=0.0):
"""
if smoothing == 0, it's one-hot method
if 0 < smoothing < 1, it's smooth method
"""
assert 0 <= smoothing < 1
confidence = 1.0 - smoothing
label_shape = torch.Size((true_labels.size(0), classes))
with torch.no_grad():
true_dist = torch.empty(size=label_shape, device=true_labels.device)
true_dist.fill_(smoothing / (classes - 1))
true_dist.scatter_(1, true_labels.data.unsqueeze(1), confidence)
return true_dist
CrossEntropyLoss
يدعم أهداف k-hot / المتجانسة.ثم يمكننا استخدامه مثل
Loss = CrossEntropyLoss(NonSparse=True, ...)
. . .
data = ...
labels = ...
outputs = model(data)
smooth_label = smooth_one_hot(labels, ...)
loss = (outputs, smooth_label)
...
بالمناسبة اختبرت تطبيقي على ImageNet ، يبدو الأمر جيدًا
| النموذج | العصور | نوع dtype | حجم الدفعة * | gpus | lr | الحيل | top1 / top5 | تحسين |
|: ----: |: -----: |: -----: |: ---------: |: ----: |: ---: |: ------: |: ---------: |: ------: |
| resnet50 | 120 | FP16 | 128 | 8 | 0.4 | - | 77.35 / - | خط الأساس |
| resnet50 | 120 | FP16 | 128 | 8 | 0.4 | تجانس Lable | 77.78 / 93.80 | +0.43 |
أعتقد أن @ zhangguanheng66 قال أن هذا شيء قد يكون قادرًا على النظر إليه في المستقبل.
فقط استخدم torch.nn.KLDivLoss. نفس الشيء.
التحديث: ليس هو نفسه.
أعتقد أن هذا مشابه لما طبقه Snorkel lib الجديد:
https://snorkel.readthedocs.io/en/master/packages/_autosummary/classification/snorkel.classification.cross_entropy_with_probs.html
فقط بعض المعلومات الإضافية حول كيفية تعامل الأشخاص مع هذه المشكلة
راجع https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Classification/RN50v1.5 للتعرف على كيفية قيام Nvidia بهذا الأمر الذي قد يساعد؟
suanrong شكرا جزيلا.
====
وربما يكون هذا مفيدًا للآخرين الذين قرأوا هذا العدد
لاحظ أن الانتروبيا المتقاطعة للتسميات غير 0/1 ليست متماثلة ، مما قد يكون تفسيرًا لضعف الأداء.
https://discuss.pytorch.org/t/cross-entropy-for-soft-label/16093/2
التنفيذ المقترح:
class LabelSmoothLoss(nn.Module):
def __init__(self, smoothing=0.0):
super(LabelSmoothLoss, self).__init__()
self.smoothing = smoothing
def forward(self, input, target):
log_prob = F.log_softmax(input, dim=-1)
weight = input.new_ones(input.size()) * \
self.smoothing / (input.size(-1) - 1.)
weight.scatter_(-1, target.unsqueeze(-1), (1. - self.smoothing))
loss = (-weight * log_prob).sum(dim=-1).mean()
return loss
لقد تحققت مما يلي:
(1) عند التنعيم = 0.0 ، يكون الناتج هو نفسه nn.CrossEntropyLoss
ضمن الدقة 1e-5
.
(2) عند التسوية> 0.0 ، فإن مجموع الأوزان على الفئات المختلفة weight.sum(dim=-1)
تكون دائمًا 1.
تطبيقات هنا تفتقر ميزة الأوزان الصفية.
((
فقط استخدم torch.nn.KLDivLoss. نفس الشيء.
هل يمكنك توضيح المزيد من فضلك
فقط استخدم torch.nn.KLDivLoss. نفس الشيء.
هل يمكنك توضيح المزيد من فضلك
بافتراض أن لديك بالفعل ملصق مصقول ، يمكنك فقط استخدام torch.nn.KLDivLoss لأن الفرق بينهما هو إنتروبيا الملصق وهو ثابت.
PistonY لماذا لا تستخدم هذه الطريقة في
with torch.no_grad():
confidence = 1.0 - smoothing_factor
true_dist = torch.mul(labels, confidence)
true_dist = torch.add(true_dist, smoothing_factor / (classNum - 1))
print(true_dist)
return true_dist
تطبيقات هنا تفتقر ميزة الأوزان الصفية.
هل يمكنني ضرب أوزان الفصل على موتر الملصق المصقول؟
def Smooth_one_hot (true_labels: torch.Tensor ، الفئات: int ، التنعيم = 0.0):
""
إذا كان التنعيم == 0 ، فهذه طريقة واحدة ساخنة
إذا كانت 0 <التنعيم <1 ، فهي طريقة سلسة""" assert 0 <= smoothing < 1 confidence = 1.0 - smoothing label_shape = torch.Size((true_labels.size(0), classes)) with torch.no_grad(): true_dist = torch.empty(size=label_shape, device=true_labels.device) true_dist.fill_(smoothing / (classes - 1)) true_dist.scatter_(1, true_labels.data.unsqueeze(1), confidence) return true_dist
""
تكمن مشكلة هذا التطبيق في أنه حساس جدًا لعدد الفئات
عندما تكون n_classes 2 ، فإن أي تجانس أعلى من 0.5 سيعكس الملصقات ، وأنا متأكد من أن الشخص لا يريده ؛ عندما تكون n_classes 3 فذلك يعني تجانس أعلى من 2/3 و 0.75 لـ 4 فصول. لذلك ربما:
assert 0 <= smoothing < (classes-1)/classes
سيواجه هذه المشكلة ، لكني أشعر أن التنعيم يحتاج إلى أخذ عدد الفئات في الاعتبار؟
def Smooth_one_hot (true_labels: torch.Tensor ، الفئات: int ، التنعيم = 0.0):
"""
if smoothing == 0, it's one-hot method
if 0 < smoothing < 1, it's smooth method
"""
assert 0 <= smoothing < 1
confidence = 1.0 - smoothing
label_shape = torch.Size((true_labels.size(0), classes))
with torch.no_grad():
true_dist = torch.empty(size=label_shape, device=true_labels.device)
true_dist.fill_(smoothing / (classes - 1))
true_dist.scatter_(1, true_labels.data.unsqueeze(1), confidence)
return true_dist
""
تكمن مشكلة هذا التطبيق في أنه حساس جدًا لعدد الفئات
عندما تكون n_classes 2 ، فإن أي تجانس أعلى من 0.5 سيعكس الملصقات ، وأنا متأكد من أن الشخص لا يريده ؛ عندما تكون n_classes 3 فذلك يعني تجانس أعلى من 2/3 و 0.75 لـ 4 فصول. لذلك ربما:
assert 0 <= smoothing < (classes-1)/classes
سيواجه هذه المشكلة ، لكني أشعر أن التنعيم يحتاج إلى أخذ عدد الفئات في الاعتبار؟
أعتقد أنها فكرة حكيمة.
شكرا على المناقشة. هناك بعض النقاط التي لا تزال غير واضحة ويبدو لي أنها أخطاء:
تنص ورقة تجانس الملصق على y_k = smoothing / n_classes + (1 - smoothing) * y_{one hot}
. لذا فإن قيمة الوزن هي smoothing / n_classes
للمؤشرات بخلاف الهدف ، وهي smoothing / n_classes + (1 - smoothing)
للفئة المستهدفة. ومع ذلك ، في تطبيقPistonY ، تقوم الوظيفة torch.scatter_
بالكتابة فوق قيمة الهدف إلى (1 - smoothing)
(ويختفي المصطلح الثابت).
علاوة على ذلك ، لا أفهم حقًا سبب استخدامنا n_classes -= 1
في الحساب (؟)
تقرأ خسارة الانتروبيا عبر الملصق ، مع y
الأوزان المذكورة أعلاه ،
LS(x, y) = - sum_k {y[k] * log-prob(x)}
= - sum_k {y[k] * log(exp(x[k]) / (sum_j exp(x[j])))}
= - sum_k {y[k] * (x[k] - log-sum-exp(x))}
= - sum_k {y[k] * x[k]} + log-sum-exp(x)
حيث يستخدم السطر الثالث إلى الرابع حقيقة أن sum_k y[k] = smoothing / n_classes * n_classes + (1 - smoothing) = 1
.
تقرأ خسارة التباعد KL ،
KL(x, y) = - sum_k {y[k] * x[k] - y[k] * log(y[k])
= - sum_k {y[k] * x[k]} - sum_k {y[k] * log(y[k])}
= - sum_k {y[k] * x[k]} - Const.
لذا في النهاية لدينا LS(x, y) = KL(x, y) + log-sum-exp(x) + Const.
، حيث Const.
هو المصطلح الثابت المقابل للإنتروبيا y
، وهو بالفعل ثابت في إعدادات الطبقات المتعددة. ولكن ماذا عن مصطلح log-sum-exp؟
لقد أجريت بعض العمليات الحسابية باستخدام دالة إنتروبيا مخصصة تقبل الأهداف اللينة ، وتوضح أنها تساوي بالفعل خسارة KLDiv
بالإضافة إلى log-sum-exp
، حتى المصطلح الثابت المقابل لنتروبيا y
. هل هناك أي افتراض في السجلات يجعل من المعقول إسقاط هذا المصطلح؟
شكرا جزيلا على التوضيحات.
هتافات !
شكرا antrec !
انت على حق. لقد تجاهلت وظيفة logsoftmax وأخطأت.
تنفيذ تسمية تنعيم دالة فقدان الانتروبيا:
import torch.nn.functional as F
def linear_combination(x, y, epsilon):
return epsilon*x + (1-epsilon)*y
def reduce_loss(loss, reduction='mean'):
return loss.mean() if reduction=='mean' else loss.sum() if reduction=='sum' else loss
class LabelSmoothingCrossEntropy(nn.Module):
def __init__(self, epsilon:float=0.1, reduction='mean'):
super().__init__()
self.epsilon = epsilon
self.reduction = reduction
def forward(self, preds, target):
n = preds.size()[-1]
log_preds = F.log_softmax(preds, dim=-1)
loss = reduce_loss(-log_preds.sum(dim=-1), self.reduction)
nll = F.nll_loss(log_preds, target, reduction=self.reduction)
return linear_combination(loss/n, nll, self.epsilon)
الارتطام إلى hi-pri بناءً على النشاط
التعليق الأكثر فائدة
هنا هو تطبيق بلدي