Nltk: خطأ في حساب تنعيم NgramModel التراجع؟

تم إنشاؤها على ٧ مارس ٢٠١٣  ·  18تعليقات  ·  مصدر: nltk/nltk

أعتقد أن هناك خطأ في كيفية حساب تجانس التراجع في NgramModel.

  • ضع في اعتبارك تسلسل "الكلمات": aaaababaaccbacb بالكلمات ['a'، 'b'، 'c']
  • بناء نموذج بيغرام (ن = 2). للتبسيط ، استخدم تجانس LidstoneProbDist
  • والجدير بالذكر أن هذا التسلسل لا يحتوي على جميع الحروف الكبيرة مسبوقة بـ "b" أو "c". وبالتالي ، فإن التراجع مطلوب للحصول على احتمال bigram "bb" و "bc" و "ca"
  • بالنسبة إلى السياق = ['a'] ، يبدو model.prob (w ، سياق) جيدًا لجميع الكلمات والمجموعات لـ 1
  • بالنسبة إلى السياق = ['b'] ، فإن model.prob (w ، سياق) لا يبدو صحيحًا ، مجاميع إلى> 1

اعتقدت أن حساب التراجع يجب أن يقوم بما يلي ، لنقل السياق "ب":

  • احسب إجمالي الاحتمال "المفقود" للقيم غير المرئية في سياق 'b' (أي bb و bc) ، على مستوى bigram ، استدع هذا Beta2
  • احسب إجمالي احتمالية unigram لهذه القيم غير المرئية (مثل 'b' و 'c') ، واستدع هذا Beta1
  • إرجاع (Beta2 / Beta1) * backoff.prob ()

يقوم هذا بشكل أساسي بتبديل احتمالات unigram لتلك الكلمات التي لم يتم ملاحظتها في سياق bigram ، وتم قياسها بشكل مناسب لملء كتلة الاحتمال المفقودة.

هل فاتني شيء؟ الكود في NgramModel يفعل شيئًا مختلفًا إلى حد ما على ما يبدو ، ولم أستطع فهمه.

language-model

التعليق الأكثر فائدة

دخول عام 2016 ولم تشهد مشكلة "نموذج ngram" أي تقدم.

ال 18 كومينتر

أعتقد أنك محق في أن هذا بالفعل خطأ.

إذا افترضنا هذا الإعداد:

from nltk.model import NgramModel
from nltk.probability import LidstoneProbDist

word_seq = list('aaaababaaccbacb')
words = ['a', 'b', 'c', '']

est = lambda freqdist, bins: LidstoneProbDist(freqdist, 0.2, bins=bins)
model = NgramModel(2, word_seq, True, True, est, 4)

يمكننا أن نرى التناقضات بسرعة كبيرة:

sum(model.prob(w, ['b']) for w in words)
Out[150]: 2.4583333333333335
sum(model.prob(w, ['a']) for w in words)
Out[151]: 1.0

[(w, model.prob(w, ['b'])) for w in words]
Out[152]: 
[('a', 0.6666666666666667),
 ('b', 0.875),
 ('c', 0.6666666666666667),
 ('', 0.25)]

[(w, model.prob(w, ['a'])) for w in words]
Out[153]: 
[('a', 0.47727272727272724),
 ('b', 0.25),
 ('c', 0.25),
 ('', 0.022727272727272728)]

عندما كنت أعمل على NgramModel منذ فترة ، أتذكر أيضًا أنني وجدت الطريقة التي تم بها تنفيذ التراجع مربكة بعض الشيء. الآن بعد أن لم أنظر إليها منذ وقت طويل ، فقدت فهمي الحدسي لكيفية عملها. يبدو لي أننا ندعي أننا نطبق Katz Back-off ، لكن الحسابات مختلفة قليلاً عن تلك الموجودة على ويكيبيديا .

أعتقد أن السبب في ذلك هو أن الوظيفة LidstoneProbDist.discount استدعاؤها من NgramModel._beta تأخذ بالفعل التلخيص في الاعتبار ، لكن عليّ النظر في الأمر أكثر.

def _alpha(self, tokens):
    return self._beta(tokens) / self._backoff._beta(tokens[1:])

def _beta(self, tokens):
    return (self[tokens].discount() if tokens in self else 1)

يبدو لي أن حسابات بيتا هي حيث تسير الأمور بشكل خاطئ ، لأن بيتا على مستوى بيغرام أكبر بكثير من بيتا على مستوى يونيغرام ، مما يجعل النسبة ، ألفا ، إيجابية.

model._beta(('b',))
Out[154]: 0.16666666666666669
model._backoff._beta(())
Out[155]: 0.05063291139240506
model._alpha(('b',))
Out[155]: 3.291666666666667

لقد استبعدت أيضًا أن يكون LidstoneProbDist نفسه هو الذي يعاني من مشكلة:

[(w, model._model[('b',)].prob(w)) for w in words]
Out[159]: 
[('a', 0.6666666666666667),
 ('b', 0.04166666666666667),
 ('c', 0.04166666666666667),
 ('', 0.25)]

sum([model._model[('b',)].prob(w) for w in words])
Out[161]: 1.0

سأحاول اكتشاف كيفية ترابط كل هذه الأجزاء مرة أخرى ومعرفة ما إذا كان بإمكاني إصلاح ذلك. على الرغم من أنه إذا كان أي شخص آخر يريد القفز (مثلdesilinguist) ، فأنا أقدر مجموعة أخرى من العيون على هذا.

مرحبا ، وشكرا للتحقق من هذا. فقط بضع أفكار أخرى:

أولاً ، الشيء الوحيد المربك هو المفاهيم المختلفة لـ "الحسم". هناك الخصم الذي تحققه طرق التنعيم المختلفة. على سبيل المثال ، تنعيم Laplacian البسيط (أضف واحدًا) يقلل من احتمالية الكلمات المرصودة وينقل هذه الكتلة إلى الكلمات غير المرصودة. وظيفة الخصم () التي يتم استدعاؤها في وظيفة _beta هي للتسوية التي يقوم بها ProbDist ، وليست (لا أعتقد) ذات صلة بتنعيم التراجع. أعتقد أن فكرة التراجع للخصم تتعلق باحتمالية المجموعة الفرعية من الكلمات "المفقودة" (غير المرصودة) لسياقات مختلفة في نموذج الترتيب الأعلى.

لذلك ، لقد قمت بتعديل الشفرة لأغراضي الخاصة للقيام بما أعتقد أنه الشيء الصحيح ، وقد قمت بمشاركة بعض المقتطفات أدناه. بشكل أساسي ، أحدد المجموعة الفرعية من الكلمات المفقودة في النموذج لسياق معين ، ولهذه المجموعة الفرعية احسب الاحتمالية الإجمالية لهذه الكلمات "المفقودة" والكمية المقابلة في نموذج التراجع. النسبة هي "alpha" ، ولاحظ أن هذه دالة للسياق. أعتقد أن هذا التنفيذ يتوافق مع ما هو موجود في رابط ويكيبيديا الذي تقدمه. أيضًا ، لم تعد وظيفة _beta مستخدمة في حالتي.

آمل أن يكون هذا مفيدًا للمناقشة. شكرا لك مرة أخرى.

    # (Code fragment for calculating backoff)

    # Now, for Katz backoff smoothing we need to calculate the alphas
    if self._backoff is not None:
        self._backoff_alphas = dict()

        # For each condition (or context)
        for ctxt in self._cfd.conditions():
            pd = self._model[ctxt] # prob dist for this context

            backoff_ctxt = ctxt[1:]
            backoff_total_pr = 0
            total_observed_pr = 0
            for word in self._cfd[ctxt].keys(): # this is the subset of words that we OBSERVED
                backoff_total_pr += self._backoff.prob(word,backoff_ctxt) 
                total_observed_pr += pd.prob(word)

            assert total_observed_pr <= 1 and total_observed_pr > 0
            assert backoff_total_pr <= 1 and backoff_total_pr > 0

            alpha_ctxt = (1.0-total_observed_pr) / (1.0-backoff_total_pr)

            self._backoff_alphas[ctxt] = alpha_ctxt

# Updated _alpha function, discarded the _beta function
def _alpha(self, tokens):
    """Get the backoff alpha value for the given context
    """
    if tokens in self._backoff_alphas:
        return self._backoff_alphas[tokens]
    else:
        return 1

مرحبًا بالجميع ، أردت فقط المشاركة في هذه المناقشة ، والإشارة إلى أن المشكلة أسوأ بكثير من مجرد وجود الاحتمالات التي تفشل في الجمع إلى 1.0

ضع في اعتبارك مثال مثلث الشكل التالي:

#!/usr/bin/python
from nltk.model import NgramModel
from nltk.probability import LidstoneProbDist

word_seq = ['foo', 'foo', 'foo', 'foo', 'bar', 'baz']

# Set up a trigram model, nothing special  
est = lambda freqdist, bins: LidstoneProbDist(freqdist, 0.2, bins)
model = NgramModel(3, word_seq, True, True, est, 3)

# Consider the ngram ['bar', 'baz', 'foo']
# We've never seen this before, so the trigram model will fall back
context = ('bar', 'baz',)
word = 'foo'
print "P(foo | bar, baz) = " + str(model.prob(word,context))

# Result:
# P(foo | bar, baz) = 2.625

نعم - هذا الاحتمال الشرطي> 1.0

الجزء السيئ هو أنه كلما تراجعت النماذج ، كلما تضخمت الاحتمالات.

تزداد المشكلة أيضًا سوءًا عندما نضيف المزيد من الأمثلة التدريبية!

word_seq = ['foo' for i in range(0,10000)]
word_seq.append('bar')
word_seq.append('baz')

est = lambda freqdist, bins: LidstoneProbDist(freqdist, 0.2, bins)
model = NgramModel(3, word_seq, True, True, est, 3)

# Consider the ngram ['bar', 'baz', 'foo']
# We've never seen this before, so the trigram model will fall back
context = ('bar', 'baz',)
word = 'foo'
print "P(foo | bar, baz) = " + str(model.prob(word,context))

# Result:
P(foo | bar, baz) = 6250.125

كما هو الحال ، لا يمكن الاعتماد على NgramModel - على الأقل ليس مع تجانس Lidstone الإضافي.

afourney : أعتقد أن هذا مقصود (يحتوي LidstoneProbDist على سمة SUM_TO_ONE = False )

afourney أوافق على أنه لا يمكن استخدام NgramModel حقًا حتى يتم إصلاح ذلك. لسوء الحظ ، لم يتح لي الوقت لأخذ طعنة في هذا مؤخرًا.

kmike SUM_TO_ONE خطأ لـ LidstoneProbDist لأنه إذا واجهت حدثًا لم يكن في التوزيع الأولي ولم تقم بتعيين قيمة الحاويات لتكون عدد الأحداث المحتملة ، فلن يتم جمعها إلى واحد. ولكن إذا تم استخدامها بشكل صحيح ، فسيكون مجموعها واحدًا. المشكلة هنا هي حساب NgramModel التجريبي ، وليس LidstoneProbDist نفسه.

kmike : نعم ، لقد لاحظت أن SUM_TO_ONE كان خطأ. كان قلقي هو أن النموذج كان يعيد الاحتمالات الشرطية الفردية (للأحداث الفردية) التي كانت بالفعل أكبر من 1 - قبل دمجها في التجميع.

bcroy أعتقد أن الحل الخاص بك هو النهج الصحيح. وببساطة ، يؤدي _alpha مهمتين هامتين:

  1. يقوم بإعادة تهيئة نموذج التراجع للسياق المحدد وذلك لاستبعاد الكلمات التي تم حسابها بالفعل بواسطة نموذج الترتيب الأعلى الحالي.
  2. يقوم بقياس نموذج التراجع المعاد تسويته "لملائمة" الاحتمال "المفقود" / المخصوم للنموذج الحالي.

ومع ذلك ، سيكون من الجيد أن يقدم NgramModel أيضًا استراتيجية الاستيفاء كبديل لاستراتيجية التراجع. سيمكن هذا من دعم تجانس Jelinek-Mercer أو Witten-Bell - الأخير الذي وجدته بسيطًا ويعمل بشكل جيد. انظر: http://nlp.stanford.edu/~wcmac/papers/20050421-smoothing-tutorial.pdf

هل يمكن لأحد أن يؤكد أن هذا لا يزال خطأ مفتوحًا؟

نعم ، ما زلت أحصل على P (foo | bar، baz) = 2.625

أهلا بالجميع،

هل هناك أي تقدم في هذه القضية؟ هل ما زالت حشرة مفتوحة؟ سأحصل على P (foo | bar، baz) = 2.625 لذا تستمر المشكلة.

أعتقد أن هذه مشكلة مهمة ويجب إصلاحها لأن نماذج اللغة تُستخدم لجميع التطبيقات تقريبًا في البرمجة اللغوية العصبية.

لسوء الحظ ، لم يكن لدي أي وقت للنظر في المشكلات العديدة المتعلقة بـ NgramModel ، ولا أتوقع أن أتمكن من القيام بذلك في أي وقت قريب. حتى يتعامل شخص ما مع هذه الأخطاء ، تمت إزالة NgramModel من nltk.

دان ، شكرا على الإجابة.

مجرد التحقق من التحديث. يمكنني رؤية بعض المشكلات تم إغلاقها ولكن أريد فقط التأكد من أنها لا تزال بعيدة عن كونها قابلة للاستخدام؟

ZeerakW لسوء الحظ ، كان هناك تقدم ضئيل في نماذج ngram ، ولم يلتزم أحد بمعالجة هذا حتى الآن.

دخول عام 2016 ولم تشهد مشكلة "نموذج ngram" أي تقدم.

يمكننا إغلاق هذا أخيرًا يا رفاق :)

تحديث 2018. تخرج بالفعل وبدأ العمل وما زالت مشكلة Ngram موجودة

صيف!

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات

القضايا ذات الصلة

Chris00 picture Chris00  ·  3تعليقات

stevenbird picture stevenbird  ·  4تعليقات

stevenbird picture stevenbird  ·  3تعليقات

peterbe picture peterbe  ·  5تعليقات

chaseireland picture chaseireland  ·  3تعليقات