الگوریتم پسرو-پیشرو
الگوریتم پسرو-پیشرو یک الگوریتم استنباطی آماری برای مدل پنهان مارکف است که احتمال پسین توزیع حاشیهای تمام متغیرهای حالت پنهان با توالی مشاهدهشدهٔ
در اصل اصطلاح «پسرو-پیشرو» به تمام الگوریتمهایی که به کلاس عمومی الگوریتمهایی که به صورت پسرونده-پیشرونده بر روی توالیها عملیات انجام میدهند اطلاق میشود. در این مفهوم، توصیفات ارائه شده در باقیماندهٔ این مقاله تنها به یک نمونهٔ خاص از این کلاس اشاره میکند.
بررسی اجمالی
در پاس اول، این الگوریتم مجموعهٔ احتمالاتی را محاسبه میکند که برای تمام
در قدم آخر با استفاده از قضیهٔ بیز و استقلال مشروط
همانطور که در بالا ذکر شده این الگوریتم شامل سه مرحله است:
- محاسبه کردن احتمالات رو به جلو (پسین)
- محاسبه کردن احتمالات رو به عقب (پیشین)
- محاسبه کردن مقادیر «صاف شده».
الگوریتم پسرو-پیشرو میتواند محتملترین حالت را در هر نقطهٔ زمانی پیدا کند اما نمیتواند برای پیدا کردن محتملترین توالی حالتها استفاده شود (به الگوریتم ویتربی رجوع کنید)
احتمالات رو به جلو (پسین)
در توضیحات پیش رو به جای توزیع احتمالاتی، از ماتریس احتمالاتی استفاده میشود. در حالت عمومی از الگوریتم پسرو-پیشرو میتوان هم در مدلهای پیوسته و هم در مدلهای گسستهٔ احتمالاتی استفاده کرد.
ما توزیعات احتمالاتی مربوط به مدل پنهان مارکف را به ماتریس احتمالاتی تبدیل میکنیم. احتمالات \
در مدل مارکف معمولی ما حالت فعلی را در این ماتریس ضرب میکردیم تا احتمالات حالت بعدی را به دست آوریم. اما در مدل پنهان مارکف حالت فعلی پنهان است و در عوض ما وقایع مرتبط با حالت فعلی را مشاهده میکنیم. یک ماتریس وقایع به صورت زیر است که احتمال مشاهده شدن هر واقعه را در هر حالت خاص بیان میکند:
در این مثال احتمال مشاهده شدن واقعهٔ یک زمانی که در حالت اول هستیم ۹۰٪ است در حالی که احتمال مشاهده شدن واقعهٔ دو زمانی که در حالت اول هستیم ۱۰٪ میباشد. به همین ترتیب واقعهٔ یک تنها ۲۰٪ اوقات مشاهده میشود اگر در حالت دوم باشیم و واقعهٔ دو با احتمال ۸۰٪ در حالت دوم قابل مشاهده است. هر بردار افقی دلخواه نشان دهندهٔ یک حالت از سیستم است(
ما میتوانیم با جبر ماتریسی این عمل را به این صورت نشان بدهیم که بردار افقی
این به ما اجازه میدهد تا با استفاده از قضیهٔ بیز بردار احتمالاتی غیرنرمال شدهٔ
اکنون ما میتوانیم این روش کلی را به مجموعه ای از مشاهدات خود اختصاص دهیم. فرض میکنیم بردار حالت اولیه ما
این فرایند میتواند رو به جلو (پس) تکرار شود و از مشاهدات اضافی و جدید نیز استفاده شود:
نتیجه یک بردار پسین غیرنرمال احتمالاتی است. i اُمین ورودی این بردار نتیجه میدهد:
بهطور معمول ما در هر مرحله این بردار را نرمال میکنیم (جمع ورودیها را یک میکنیم) یک عامل مقیاس گذاری را در هر مرحله به صورت زیر معرفی میکنیم:
که در آن
ای به ما اجازه میدهد که بردار احتمالاتی مقیاسپذیر را اینگونه تفسیر کنیم:
پس تا به حال نتیجه گرفتین که ضرب عوامل مقیاس، احتمال حقیقی مشاهدهٔ توالی مورد نظر تا زمان t را مهیا میکند و این که بردار احتمالاتی اسکیل شده به ما احتمال بودن در هر حالت را در زمان میدهد.
احتمالات رو به عقب (پیشین)
با یک روش مشابه میتوان احتمالات پیشین را محاسبه کرد. به صورت زیر:
حالا ما فرض میکنیم که در حالت خاص
توجه کنید که ما در حال حاضر از یک بردار عمودی استفاده میکنیم و بردارهای احتمالاتی پسین ما افقی بودند. پس میتوانیم عملیات زیر را انجام دهیم:
میتوانیم این بردار را هم (مانند بخش قبل) نرمال کنیم اما معمولاً این کار را انجام نمیدهند. هر ورودی احتمال واقعهای در آینده را نشان میدهد و نرمال کردن این بردار معادل استفاده از قضیهٔ بیز برای پیدا کردن احتمال هر حالت برای ایجاد کردن واقعههای آینده است. در اینجا هم مانند قسمت پسین از همان
که در آن
این معادله برای این مفید است که اجازه میدهد تا احتمال کامل بودن در یک حالت در زمان داده شده t را داشته با ضرب کردن این مقادیر داشته باشیم:
برای درک این موضوع توجه داشته باشید که
بنابراین مقادیر
برای به دست آوردن محتملترین دنباله از حالتها که دنبالهٔ مشاهدات را تولید میکنند، میتوانید از الگوریتم ویتربی استفاده کنید
مثال
این مثال منشاءاش را از جهان چتری(umbrella world) در راسل و نوریگ ۲۰۱۰ فصل ۱۵, صفحات ۵۶۶ میآورد که در آن ما میخواهم با مشاهداتمان از چتر داشتن یا نداشتن یک مرد وضعیت آب و هوا را نتیجهگیری کنیم. ما دو حالت مختلف را برای آب و هوا فرض میکنیم: حالت اول = باران ببارد؛ حالت دوم = باران نبارد. ما فرض میکنیم که آب و هوا است ۷۰٪ شانس ماندن در همان وضعیت خودش را دارد و ۳۰٪ شانس برای تغییر حالت دادن. پس ماتریس تغییرات ما به شکل زیر خواهد شد:
ما همچنین فرض کنیم که هر حالت دو واقعه را دربردارد: واقعه اول = مرد چتر بیاورد؛ واقعه دوم = مرد چتر نیاورد. پس احتمالات چتر آوردن و چتر نیاوردن را برای هر حالت (بارانی و غیر بارانی) در ماتریس احتمالات مینویسیم. فرض کنید احتمال این که بارانی باشد و چتر بیاورد ۹۰٪؛ بارانی باشد و چتر بیاورد ۱۰٪؛ بارانی نباشد و چتر بیاورد ۲۰٪؛ بارانی نباشد و چتر نیاورد ۸۰٪ است:
با داشتن این اطلاعات بعد از آن که توالی وقایع را بهترتیب {چتر، چتر، بدون چتر، چتر، چتر} مشاهده کردیم میتوانیم محاسبات خود را شروع کنیم:
توجه داشته باشید که
شروع میکنیم به محاسبهٔ احتمالات پیشرو، بنابراین یک بردار اولیه میگیریم:
به این دلیل بردار اولیه را انتخاب میکنیم، چون نمیدانیم قبل از مشاهدات ما آب و هوا در چه حالتی بود (بارانی بود یا نبود). بردار اولیه ما باید یک بردار افقی باشد. برای راحتتر شدن محاسباتمان این بردار را ترانهاده میکنیم. معادلهٔ ما به صورت زیر میشود:
به جای:
توجه کنید که ماتریس انتقال نیز ترانهاده شده اما در مثال ما ترانهاده این ماتریس با خودش برابر است (چون ماتریس متقارن است). انجام این محاسبات و نرمال کردن این نتایج را فراهم میکند:
شروع میکنیم به محاسبهٔ احتمالات پسرو، بنابراین یک بردار اولیه میگیریم:
و بعد از آن شروع میکنیم به انجام محاسبات (مثل قبل):
در نهایت، ما احتمالات صافشده را محاسبه میکنیم. این نتایج باید نرمال هم بشوند (جمع ورودیها یک شود) چون ما در احتمالات پیشین، احتمالات را با <
دقت داشته باشید که ارزش
اگرچه،
محاسبات فوق نشان میدهند که محتملترین حالت آب و هوا برای هر روز به غیر از روز سوم، آب و هوای «بارانی» است. البته این محاسبات به ما بیشتر از این میگویند، چون آنها میتوانند احتمالات هر حالت را در زمانهای مختلف به ما ارائه کنند. شاید مهمتر از همه بدست آوردن اطلاع دربارهٔ
عملکرد
با استفاده از الگوریتم جستجوی جامع برای حل این مسئله ما باید تمامی
یک الگوریتم حافظه محور بهینهتر از الگوریتم پسرو-پیشرو وجود دارد به نام الگوریتم جزیره که استفادهٔ از حافظهٔ کمتر را با کشیدن زمان بیشتر تعویض کرده. این الگوریتم دارای پیچیدگی زمان
علاوه بر این، این الگوریتمها طوری تکوین یافتهاند تا با استفاده از الگوریتمهای صاف کردن برخط(online smoothing) مانند الگوریتم fixed-lag smoothing (FLS) مقادیر
شبه کد
Backward(guessState, sequenceIndex): if sequenceIndex is past the end of the sequence, return 1 if (guessState, sequenceIndex) has been seen before, return saved result result = ۰ for each neighboring state n: result = result + (transition probability from guessState to n given observation element at sequenceIndex) * Backward(n, sequenceIndex+1) save result for (guessState, sequenceIndex) return result
مثال با زبان پایتون
با توجه HMM(مدل پنهان مارکف) (دقیقاً مانند الگوریتم ویتربی) در زبان برنامهنویسی پایتون نشان میدهیم:
states = ('Healthy', 'Fever')
end_state = 'E'
observations = ('normal', 'cold', 'dizzy')
start_probability = {'Healthy': 0.6, 'Fever': 0.4}
transition_probability = {
'Healthy' : {'Healthy': 0.69, 'Fever': 0.3, 'E': 0.01},
'Fever' : {'Healthy': 0.4, 'Fever': 0.59, 'E': 0.01},
}
emission_probability = {
'Healthy' : {'normal': 0.5, 'cold': 0.4, 'dizzy': 0.1},
'Fever' : {'normal': 0.1, 'cold': 0.3, 'dizzy': 0.6},
}
ما میتوانیم پیادهسازی را بدین شکل بنویسیم:
def fwd_bkw(observations, states, start_prob, trans_prob, emm_prob, end_st):
# forward part of the algorithm
fwd = []
f_prev = {}
for i, observation_i in enumerate(observations):
f_curr = {}
for st in states:
if i == 0:
# base case for the forward part
prev_f_sum = start_prob[st]
else:
prev_f_sum = sum(f_prev[k]*trans_prob[k][st] for k in states)
f_curr[st] = emm_prob[st][observation_i] * prev_f_sum
fwd.append(f_curr)
f_prev = f_curr
p_fwd = sum(f_curr[k] * trans_prob[k][end_st] for k in states)
# backward part of the algorithm
bkw = []
b_prev = {}
for i, observation_i_plus in enumerate(reversed(observations[1:]+(None,))):
b_curr = {}
for st in states:
if i == 0:
# base case for backward part
b_curr[st] = trans_prob[st][end_st]
else:
b_curr[st] = sum(trans_prob[st][l] * emm_prob[l][observation_i_plus] * b_prev[l] for l in states)
bkw.insert(0,b_curr)
b_prev = b_curr
p_bkw = sum(start_prob[l] * emm_prob[l][observations[0]] * b_curr[l] for l in states)
# merging the two parts
posterior = []
for i in range(len(observations)):
posterior.append({st: fwd[i][st] * bkw[i][st] / p_fwd for st in states})
assert p_fwd == p_bkw
return fwd, bkw, posterior
تابع fwd_bkw
این ورودیها را میگیرد:
observations
دنبالهٔ مشاهدات ما است مثلاً ['normal', 'cold', 'dizzy']
;
states
همان مجموعه ما از حالات پنهان است؛
start_prob
احتمالات آغازین ما است؛ trans_prob
احتمالات گذار ما است احتمالات و emm_prob
احتمالات انتشار ما.
برای سادگی کد، ما فرض میکنیم که توالی مشاهدات ما observations
خالی نیست و trans_prob[i][j]
و [i][j]emm_prob
تعریف شدهاست برای تمام حالات i,j.
در مثال اجرا شده، الگوریتم پسرو-پیشرو به صورت زیر استفاده شدهاست:
def example():
return fwd_bkw(observations,
states,
start_probability,
transition_probability,
emission_probability,
end_state)
>>> for line in example():
... print(*line)
...
{'Healthy': 0.3, 'Fever': 0.04000000000000001} {'Healthy': 0.0892, 'Fever': 0.03408} {'Healthy': 0.007518, 'Fever': 0.028120319999999997}
{'Healthy': 0.0010418399999999998, 'Fever': 0.00109578} {'Healthy': 0.00249, 'Fever': 0.00394} {'Healthy': 0.01, 'Fever': 0.01}
{'Healthy': 0.8770110375573259, 'Fever': 0.1229889624426741} {'Healthy': 0.623228030950954, 'Fever': 0.3767719690490461} {'Healthy': 0.2109527048413057, 'Fever': 0.7890472951586943}
جستارهای وابسته
منابع
- Lawrence R. Rabinerآموزش در مخفی مارکوف و مدلهای انتخاب شده در برنامههای کاربردی در گفتار. مجموعه مقالات IEEE, 77 (2), p. 257-286 فوریه 1989. ۱۰٫۱۱۰۹/۵٫۱۸۶۲۶
- Lawrence R. Rabiner, B. H. Juang (January 1986). "An introduction to hidden Markov models". IEEE ASSP Magazine: 4–15.
- Eugene Charniak (1993). Statistical Language Learning. Cambridge, Massachusetts: MIT Press. ISBN 978-0-262-53141-2.
پیوند به بیرون
- تعاملی گسترده برای آموزش به جلو–رو به عقب الگوریتم (صفحه گسترده و مقاله با گام به گام از طریق راه رفتن)
- آموزش پنهان مارکوف مدل از جمله رو به جلو–رو به عقب الگوریتم
- مجموعه ای از الگوریتمهای هوش مصنوعی اجرا در جاوا (از جمله HMM و رو به جلو–رو به عقب الگوریتم)