نقوم بتفكيك خوارزمية EM إلى طوب صغير



في هذه المقالة ، كما توقعت بالفعل ، سنتحدث عن خوارزمية EM للجهاز. بادئ ذي بدء ، قد تكون المقالة ذات أهمية لأولئك الذين ينضمون ببطء إلى مجتمع datasainists. ستكون المادة المقدمة في المقالة أكثر فائدة لأولئك الذين بدأوا مؤخرًا في أخذ الدورة الثالثة "البحث عن هياكل البيانات" ضمن التخصص "التعلم الآلي وتحليل البيانات" من MIPT و Yandex.

تعتبر المادة المقدمة في المقالة ، إلى حد ما ، إضافة إلى الأسبوع الأول من التدريب في الدورة المذكورة أعلاه ، وهي تسمح لك بالإجابة على بعض الأسئلة المهمة المتعلقة بمبدأ تشغيل خوارزمية EM. من أجل فهم أفضل للمادة ، من المستحسن أن يكون القارئ المحترم لدينا قادراً على تنفيذ العمليات باستخدام المصفوفات (ضرب المصفوفة ، وإيجاد محدد المصفوفة والمصفوفة العكسية) ، وفهم أساسيات نظرية الاحتمالات و matstat ، وبالطبع ، لديهم على الأقل فهم أساسي لخوارزميات التجميع الأساسية وفهم ما يتم التجميع في التعلم الآلي. على الرغم من أنه بالطبع بدون هذه المعرفة ، يمكنك قراءة المقالة ، شيء ونعم سيكون بالتأكيد واضحًا :)

أيضًا ، وفقًا للتقاليد القديمة ، لن تحتوي المقالة على بحث نظري عميق ، ولكن سيتم ملؤها بأمثلة بسيطة ومفهومة. سيشرح كل مثال لاحق تشغيل خوارزمية EM بشكل أعمق قليلاً من الخوارزمية السابقة ، الأمر الذي يقودنا في نهاية المطاف بشكل مباشر إلى تحليل الخوارزمية نفسها. لكل مثال ، سيتم كتابة الرمز. تم كتابة جميع التعليمات البرمجية في python 2.7 ، ولهذا أعتذر مقدمًا. اتضح أنني الآن أستخدم هذا الإصدار المعين ، ولكن بعد التبديل إلى python 3 ، سأحاول تغيير الرمز في المقالة.



دعونا نتعرف على الخطوط العريضة للمقالة: 1) دعونا نفكر بشكل عام في كيفية عمل خوارزمية EM.

2) نكرر النقاط الرئيسية من نظرية بايز (الصيغة):

Pxi(Bj)=P(Bj)PBj(xi)P(xi)



3) ضع في اعتبارك المثال الأول عن نظرية بايزي ، حيث جميع عناصر الصيغة (أو بالأحرى الاحتمالية P(Bj),PBj(xi)) لعلامة المساواة على اليمين معروفة. في هذه الحالة ، نحتاج فقط إلى فهم الأرقام التي يجب استبدالها ثم إجراء العمليات الأساسية بشكل صحيح.

4) تأمل المثال الثاني في نظرية بايز. لحل المشكلة ، سنحتاج أيضًا إلى حساب كثافة الاحتمال لحدث معين (xi) تخضع للفرضية (Bj) - ρBj(xi). بالنسبة للحسابات ، سيتم إعطاؤنا معلمات لمتغير عشوائي ، أي التوقع الرياضي -μ والانحراف المعياري - σ. سيتم إجراء حسابات كثافة الاحتمال وفقًا للصيغة التالية:

ρBj(xi)=1σj2πexp((xiμj)22σj2)


يفترض استخدام الصيغة المذكورة أعلاه أن المتغير العشوائي له بُعد واحد البعد ويتم توزيعه بشكل طبيعي (وبعبارة أخرى ، فإن توزيع Gaussian أو Gaussian-Laplace هو توزيع احتمالي).

5) ضع في اعتبارك المثال الثالث ، الذي يختلف عن المثال السابق فقط من حيث أنه ينظر في حالة التوزيع الطبيعي متعدد الأبعاد (في نسختنا ثنائية الأبعاد) لمتغير عشوائي. في هذه الحالة ، يتم حساب الكثافة وفقًا للصيغة التالية:

ρBj(xi)=1(2π)k/2Σj1/2exp(12(xiμj)TΣj1(xiμj))



6) وأخيرًا ، نقوم بتعديل المثال الثالث بطريقة توضح بوضوح عمل خوارزمية EM.

7) في الختام ، نقارن جودة الخوارزمية التي استنتجناها مع جودة خوارزمية EM ، والتي تم إنشاؤها في مكتبة sklearn (class sklearn.mixture.GaussianMixture)

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

خوارزمية EM بشكل عام


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

يتم استخدام خوارزمية EM في مشاكل التكتل كخوارزمية تكرارية ، والتي تنفذ خطوتين في كل تكرار:

E-step. في الخطوة الإلكترونية الأولى ، بطريقة ما ، على سبيل المثال ، بشكل عشوائي ، نختار المتغيرات المخفية ، في حالتنا سيكون ذلك توقعًا رياضيًا -μ والانحراف المعياري - σ. باستخدام المتغيرات المحددة ، نحسب احتمالية تعيين كل كائن لمجموعة معينة. تستخدم الخطوات الإلكترونية اللاحقة المتغيرات المخفية المحددة في الخطوات M.

M-خطوة . في الخطوة M ، نقوم ، وفقًا لاحتمالات تعيين كل كائن لمجموعة معينة تم الحصول عليها في الخطوة E ، بإعادة حساب المتغيرات المخفيةμ و σ

تتكرر التكرارات حتى يحدث التقارب. يمكننا أن نفترض أن التقارب حدث عندما لا تتغير قيم المتغيرات المخفية بشكل كبير ، على سبيل المثال ، ضمن ثابت معين. في المثال الأخير ، الذي تم تناوله في المقالة ، لن نقوم بتعيين الثوابت ، وبالتالي ، لن نحدد التغييرات في قيم المتغيرات المخفية في كل تكرار. دعونا نفعل ذلك بشكل أبسط - سنقتصر الخوارزمية على عدد ثابت من الخطوات.

إن الخطوة M بسيطة بما يكفي لفهمها ، وسنرى ذلك في المثال الأخير. سنركز على الخطوة الإلكترونية في المقالة.

تعتمد الخطوة الإلكترونية على نظرية بايزي ، التي نحدد على أساسها احتمالية تعيين كل كائن لمجموعة أو أخرى. لنتذكر ماهية هذه النظرية.

أذكر صيغة بايز


Pxi(Bj)=P(Bj)PBj(xi)P(xi)



أين Pxi(Bj)- احتمال ذلك مع الحدث xiكان هناك فرضية Bj

P(Bj)- احتمالية الفرضية Bj

PBj(xi)- احتمالية وقوع الحدث xiتخضع للفرضية Bj

P(xi)- احتمالية وقوع الحدث xiرهناً بتحقيق كل فرضية (محسوبة بواسطة صيغة الاحتمال الكلي للحدث)

شريطة أن يكون الحدثxi حدث بالفعل ، احتمال تحقيق الفرضية Bjأعيد تقييمها باستخدام الصيغة أعلاه. يمكننا القول بأنهP(Bj) هذا هو الاحتمال المسبق للفرضية (قبل الاختبار) ، و Pxi(Bj)يتم تقييم الاحتمال الخلفي لنفس الفرضية بعد الحدث xiأي ، بالنظر إلى حقيقة أن الحدث xiحدث موثوق.

مثال واحد من نظرية بايز


تخيل أننا تلقينا أجزاء تم إنتاجها على جهازين مختلفين. الخصائص التالية للمنتجات المستلمة في المستودع معروفة:

في المجموع ، الأجزاء - 10000 قطعة (N=10000) ، الأجزاء التي تم إنتاجها على الجهاز الأول - 6000 قطعة. (N1=6000) ، في الثانية - 4000 قطعة. (N2=4000)

نسبة المنتجات القياسية (أي غير المعيبة) المصنعة على الجهاز الأول هي 0.9 ، ونسبة المنتجات القياسية المصنعة على الجهاز الثاني هي 0.8.

استخرجنا جزءًا عشوائيًا من الأجزاء المستلمة ، وتبين أنه قياسي.

نحتاج إلى تحديد احتمال:

1) إنتاج الجزء على الآلة الأولى ؛

2) تم إنتاج العنصر على الجهاز الثاني.

القرار

1) الحدثxفي مثالنا ، استخراج منتج قياسي.

2) الآن ، دعنا نحدد الفرضياتBj. لدينا جزءان من الأجزاء ، مما يعني فرضيتين:

الفرضيةB1: تم إنتاج منتج تمت إزالته عن طريق الخطأ على الجهاز رقم 1.

فرضيةB2: تم إنتاج منتج تمت إزالته عن طريق الخطأ على الجهاز رقم 2.

وبناءً على ذلك ، فإن احتمال استخراج منتج تم تصنيعه على الجهاز الأول هوP(B1) يشكل N1/N=6000/10000=0.6.

احتمالية استخراج منتج تم تصنيعه على آلة ثانية هوP(B2) يشكل N2/N=0.4. علاوة على ذلك ، نحن لا نهتم بالمنتج القياسي أو المعيب ، فمن المهم أن تكون الدفعة منه.

3) احتمال استخراج منتج قياسي من المنتجات المصنعة على الماكينة رقم 1 (أي تحت الفرضية الأولى) يتوافق مع حصة المنتجات القياسية المصنعة على الماكينة رقم 1 وهو 0.9 ،PB1(xi)=0.9.

احتمال استخراج المنتج هو منتج قياسي يخضع للفرضية رقم 2 -PB2(xi)=0.8

4) تحديد احتمال استخراج منتج قياسي من مجموعة المنتجات بأكملها -P(xi). وفقًا لصيغة الاحتمال الكلي لحدث ماP(xi)=P(B1)PB1(xi)+P(B2)PB2(xi)=0.60.9+0.40.8=0.54+0.32=0.86. هنا نفهم ذلك الحين0.14 - هذا هو احتمال استخراج الجزء المعيب من جميع الأجزاء التي وصلت إلى المستودع ويتبين في المجموع 1 (0.86+0.14=1).

5) الآن لدينا جميع البيانات من أجل حل المشكلة.

5.1) تحديد احتمالية إنتاج جزء قياسي مستخرج عشوائيًا على جهاز1:

Pxi(B1)=P(B1)PB1(xi)P(xi)=0.60.90.860.63



5.2) نحدد احتمال إنتاج جزء قياسي مستخرج عشوائيًا على جهاز2:

Pxi(B2)=P(B2)PB2(xi)P(xi)=0.40.80.860.37



وهكذا ، قمنا بإعادة تقييم الفرضيات B1و B2. بعد إعادة التقييم ، تشكل الفرضيات أيضًا مجموعة كاملة من الأحداث:0.63+0.37=1.

حسنًا ، حان الوقت الآن للانتقال إلى المثال الثاني.

المثال الثاني لنظرية بايز باستخدام معلمات التوزيع الطبيعي لمتغير عشوائي: التوقع الرياضي μوالانحراف المعياري σ



دعنا نعدل شروط المثال السابق بشكل طفيف. نفترض أننا لا نعرف نسبة المنتجات القياسية المصنعة على الماكينات رقم 1 ورقم 2 ، ولكن نفترض ، بدلاً من ذلك ، أننا نعرف متوسط ​​أبعاد أقطار المنتجات والانحراف المعياري لقطر المنتجات على كل آلة.

تنتج الماكينة رقم 1 أجزاء بقطر 64 مم وانحراف معياري يبلغ 4 مم.

تنتج الماكينة رقم 2 أجزاء بقطر 52 مم وانحراف معياري يبلغ 2 مم.

شرط مهم هو أن يتم وصف مجموعة المنتجات بالكامل من خلال التوزيع العادي أو التوزيع الغوسي.

خلاف ذلك ، فإن الشروط هي نفسها ، نكتب لهم:

N1=6000,μ1=64,σ1=4

N2=4000,μ2=52,σ2=2

نفترض أنه في عملية قبول المنتج كانت هناك حادثة صغيرة ، ونتيجة لذلك تم خلط جميع المنتجات.

مهمتنا هي فرز التفاصيل ولكل منها تحديد احتمال إنتاجه على الجهاز رقم 1 أو الجهاز رقم 2. سنفترض أيضًا أن الجزء تم إنتاجه على الجهاز ، والذي يكون احتماله أعلى.

الحل

أولاً وقبل كل شيء ، سنقوم بتحليل خوارزمية الحل. يمكننا بسهولة حساب احتمال كل فرضية ، ومع ذلك ، فإننا نعرف بالفعل قيمها من مثال سابق:P(B1)=0.6، P(B2)=0.4. ولكن كيف نحسب احتمالية الاستيلاء على منتج قياسي بشكل فردي لكل من الفرضيات المتاحة؟ كل شيء بسيط! لن نفكر في الاحتمالية ، بدلاً من ذلك ، سنحدد كثافة الاحتمال للعنصر المراد إزالته مع قيمة قطره لكل فرضية على حدة.

للقيام بذلك ، نستخدم الصيغة المعروفة:

ρBj(xi)=1σj2πexp((xiμj)22σj2)



أين xi- قيمة عشوائية (في حالتنا ، الحجم الفعلي لقطر المنتج) ،

μj- التوقع الرياضي للمتغيرات العشوائية jالفرضية (في حالتنا ، متوسط ​​حجم قطر المنتج المنتج jأداة آلة)

σj- الانحراف المعياري للمتغيرات العشوائية jالفرضية (في حالتنا ، الانحراف عن متوسط ​​حجم قطر المنتج المنتج jأداة آلة).

وبالتالي ، نقوم باستبدال ذكي لاحتمال كثافة الاحتمال في بسط صيغة بايز ، وسوف نقوم باستبدال مماثل في المقام.

نتكيف الصيغ خصيصا لحالتنا.

احتمالية أن يكون الجزء بأبعاد القطرxi يتم إنتاجه على الجهاز رقم 1 بواسطة الصيغة:

Pxi(B1)=w1ρB1(xi)w1ρB1(xi)+w2ρB1(xi)



احتمالية أن يكون الجزء بأبعاد القطر xiالمنتجة على الجهاز رقم 2:

Pxi(B2)=w2ρB2(xi)w1ρB1(xi)+w2ρB1(xi)



لاحظ أننا استبدلنا الترميز لاحتمال فرضية بـ P(Bj)على ال wj. ويرجع ذلك إلى التعيين المقابل في الدورة المعينة سابقًا. علاوة على ذلك ، سنستخدم مثل هذا التدوين.

الآن نحن 100٪ كاملة ومستعدة لحل المشكلة.

نحن ننظر إلى الرمز

استيراد مكتبات
#  , 
import numpy as np
import random
import math
import matplotlib.pyplot as plt
%matplotlib inline
from sklearn.metrics import accuracy_score


الوظائف المستخدمة في المثال الثاني
#      ,    
#      : .,  . 
def gaus_func_01(mu,sigma,x):
    return math.e**(-(x-mu)**2/(2*sigma**2)) / (sigma*(2*math.pi)**0.5)

#        
def proba_x(X, w1, w2, mu_1, mu_2, sigma_1, sigma_2):
    for i in X:
        P1_x = gaus_func_01(mu_1,sigma_1,i)
        P2_x = gaus_func_01(mu_2,sigma_2,i)
        P_x = w1*P1_x + w2*P2_x
        P_x_1 = (w1*P1_x)/P_x
        P_x_2 = (w2*P2_x)/P_x
        proba_temp = []
        proba_temp.append(P_x_1)
        proba_temp.append(P_x_2)
        proba_X.append(proba_temp)
    return proba_X

#        
def pred_x(proba_X, limit_proba):
    pred_X = []
    for x in proba_X:
        if x[0] >= limit_proba:
            pred_X.append(1)
        else:
            pred_X.append(2)
    return np.array(pred_X)

#    
def graph_01(X, pred_X, mu_1, sigma_1, mu_2, sigma_2):
    true_pred = []
    false_pred_1 = []
    false_pred_2 = []
    for i in range(X.shape[0]):
        if pred_X[i] == y[i]:
            true_pred.append([X[i], -0.025])
        else:
            if y[i] == 1:
                false_pred_1.append([X[i], -0.0075])
            else:
                false_pred_2.append([X[i], -0.015])

    false_pred_1 = np.array(false_pred_1)            
    false_pred_2 = np.array(false_pred_2)
    true_pred = np.array(true_pred)

    x_theory = np.linspace(42, 85, 20000)
    y_theory_1 = []
    for x in x_theory:
        y_theory_1.append(gaus_func_01(mu_1,sigma_1,x))
    y_theory_2 = []
    for x in x_theory:
        y_theory_2.append(gaus_func_01(mu_2,sigma_2,x))

    plt.figure(figsize=(18, 8))    
    plt.plot(
        x_theory, y_theory_1, color = 'green', lw = 2, label = 'Theoretical probability density for machine 1')
    plt.plot(
        x_theory, y_theory_2, color = 'firebrick', lw = 2, label = 'Theoretical probability density for machine 2')
    plt.hist(
        X[:N1], bins = 'auto', color='#539caf', normed = True, alpha = 0.35, label = 'machine tool products 1')
    plt.hist(
        X[N1:N], bins = 'auto', color='sandybrown', normed = True, alpha = 0.75, label = 'machine tool products 2')
    plt.plot(mu_1, 0, 'o', markersize = 11, color = 'blue', label = 'Mu 1')
    plt.plot(mu_2, 0, 'o', markersize = 11, color = 'red', label = 'Mu 2')

    plt.plot([mu_1 - sigma_1, mu_1 - sigma_1], [0,0.85*np.max(y_theory_1)],
             ':', lw = 3, color = 'blue', alpha = 0.55, label = 'Mu1 - sigma1')
    plt.plot([mu_1 + sigma_1, mu_1 + sigma_1], [0,0.85*np.max(y_theory_1)],
             ':', lw = 3, color = 'blue', alpha = 0.55, label = 'Mu1 + sigma1')
    plt.plot([mu_2 - sigma_2, mu_2 - sigma_2], [0,0.85*np.max(y_theory_2)],
             ':', lw = 3, color = 'red', alpha = 0.55, label = 'Mu2 - sigma2')
    plt.plot([mu_2 + sigma_2, mu_2 + sigma_2], [0,0.85*np.max(y_theory_2)],
             ':', lw = 3, color = 'red', alpha = 0.55, label = 'Mu2 + sigma2')

    plt.plot([mu_1 - 2 * sigma_1, mu_1 - 2 * sigma_1], [0, 0.9*0.5 * np.max(y_theory_1)],
             ':', lw = 2.5, color = 'blue', alpha = 0.35, label = 'Mu1 - 2*sigma1')
    plt.plot([mu_1 + 2 * sigma_1, mu_1 + 2 * sigma_1], [0, 0.9*0.5 * np.max(y_theory_1)],
             ':', lw = 2.5, color = 'blue', alpha = 0.35, label = 'Mu1 + 2*sigma1')
    plt.plot([mu_2 - 2 * sigma_2, mu_2 - 2 * sigma_2], [0, 0.9*0.5 * np.max(y_theory_2)],
             ':', lw = 2.5, color = 'red', alpha = 0.35, label = 'Mu2 - 2*sigma2')
    plt.plot([mu_2 + 2 * sigma_2, mu_2 + 2 * sigma_2], [0, 0.9*0.5 * np.max(y_theory_2)],
             ':', lw = 2.5, color = 'red', alpha = 0.35, label = 'Mu2 + 2*sigma2')

    plt.plot(false_pred_1[:,0], false_pred_1[:,1], 'o', markersize = 2.5, color = 'blue', alpha = 0.2, label = 'errors1')
    plt.plot(false_pred_2[:,0], false_pred_2[:,1], 'o', markersize = 2.5, color = 'red', alpha = 0.3, label = 'errors2')
    plt.plot(true_pred[:,0], true_pred[:,1], 'o', markersize = 3, color = 'green', alpha = 0.2, label = 'right answers')

    plt.xlabel('Caliber')
    plt.ylabel('Probability density')
    plt.legend()
    plt.show()


حدد المعلمات
#    
#      №1
N1 = 6000
#      №2
N2 = 4000
#      
N = N1+N2

#    №1
mu_1 = 64.
#        №1
sigma_1 = 3.5

#    №2
mu_2 = 52
#        №2
sigma_2 = 2.


سنحسب
X = np.zeros((N))
np.random.seed(seed=42)
#    ,   №1
X[:N1] = np.random.normal(loc=mu_1, scale=sigma_1, size=N1)
#  ,   №2
X[N1:N] = np.random.normal(loc=mu_2, scale=sigma_2, size=N2)

#   
y = np.zeros((N))
y[:N1] = np.array((1))
y[N1:N] = np.array((2))

#     ,    №1
w1 = float(N1)/N
#     ,    №2
w2 = float(N2)/N

#           
proba_X = []
proba_X = proba_x(X, w1, w2, mu_1, mu_2, sigma_1, sigma_2)

#   ,   ,        
limit_proba = 0.5

#     
pred_X = []
pred_X = pred_x(proba_X, limit_proba)

#    
print '   :', round(accuracy_score(y, pred_X),3)
print

print ' №1'
graph_01(X, pred_X, mu_1, sigma_1, mu_2, sigma_2)


الرسم البياني رقم 1



ماذا فعلنا للتو؟ لقد أنشأنا بطريقة عشوائية زائفة 10000 قيمة موصوفة بالتوزيع العادي ، منها 6000 قيمة بمتوسط ​​64 مم وانحراف معياري 4 مم ، و 4000 قيمة بمتوسط ​​52 مم وانحراف معياري 2 مم. علاوة على ذلك ، وفقًا للخوارزمية المذكورة أعلاه ، لكل جزء ، تم تحديد احتمال إنتاجه على الجهاز رقم 1 أو رقم 2. بعد ذلك ، اخترنا الفرضية حول إنتاج المنتج على جهاز أو آخر ، اعتمادًا على الفرضية الأكثر احتمالا. أخيرًا ، قارنا نتائج الخوارزمية بالإجابات الصحيحة.

عند الإخراج ، حصلنا على حصة من الإجابات الصحيحة - 0.986. بشكل عام ، هذا جيد جدًا ، نظرًا لأننا أجرينا التدريب دون استخدام إجابات صحيحة.

دعونا نلقي نظرة على الرسم البياني. ما هو الموصى به الانتباه؟ انظر أين توجد المنتجات التي لم يتم تحديدها بشكل صحيح بواسطة الخوارزمية.

أولاً ، نرى أخطاء الخوارزمية فقط في المنطقة حيث يكون للمنتجات المصنعة على أجهزة مختلفة نفس القطر. يبدو منطقيا تماما.

ثانيًا ، نرى أن الخوارزمية مخطئة فقط في تلك الأشياء البعيدة جدًا عن متوسط ​​القيمة الحقيقية للأشياء وفي نفس الوقت قريبة جدًا من المركز الخاطئ.

لكن الشيء الأكثر إثارة للاهتمام هو أن المشاكل تبدأ بشكل أساسي بعد تجاوز قيم متساوية تقريبًاμ+2σ، تحديدًا في حالتنا عند التقاطع μ12σ1و μ2+2σ2

يمكن لأولئك الذين يرغبون في "تحريف" المعلمات ومعرفة كيف تتغير جودة الخوارزمية. سيكون هذا مفيدًا لتحسين استيعاب المواد.

حسنًا ، ننتقل إلى المثال التالي

المثال الثالث. حالة ثنائية الأبعاد


هذه المرة سننظر في الحالة عندما يكون لدينا بيانات ليس فقط حول قطر المنتجات ، ولكن أيضًا ، على سبيل المثال ، حول وزن كل منتج. دع الآلة رقم 1 تنتج أجزاء تزن 12 جرامًا وانحرافًا قياسيًا يبلغ 1 جرامًا ، وتنتج الآلة رقم 2 منتجات تزن 10 جرامًا وانحرافًا قياسيًا يبلغ 0.8 مم.

وبالنسبة للباقي ، سنستخدم البيانات من المثال السابق ، وسنقوم بتدوينها.

N1=6000,μ11=64,σ11=4,μ12=14,σ12=1

N2=4000,μ21=52,σ21=2,μ22=10,σ22=0.9

الوضع هو نفسه - تم خلط جميع التفاصيل في كومة واحدة كبيرة ونحن بحاجة إلى فرزها وتحديد كل جزء من احتمال إنتاجه على الجهاز رقم 1 والآلة رقم 2.

الحل

بشكل عام ، لا يتغير نهج الحل للمثال السابق ، باستثناء الصيغة لتحديد كثافة الاحتمال لمتغير عشوائي. بالنسبة للحالة متعددة الأبعاد ، يتم استخدام الصيغة التالية:

pBj(xi)=1(2π)k/2Σj1/2exp(12(xiμj)TΣj1(xiμj))



أين Σjمصفوفة التغايرات للمتغيرات العشوائية jالفرضية (في حالتنا ، مصفوفة التغاير لبارامترات المنتجات المنتجة jأداة آلة)

Σjهو محدد مصفوفة التغاير للمتغيرات العشوائية jفرضية

μj- التوقع الرياضي للمتغيرات العشوائية jالفرضية (في حالتنا ، متوسط ​​قيمة المنتجات المصنعة على jأداة آلة)

xi- متغير عشوائي (في حالتنا ، المعلمات i-المنتج)

هذه المرة ، لفهم الشفرة ، سيحتاج القارئ المحترم إلى المعرفة حول العمليات باستخدام المصفوفات

الوظائف المستخدمة في المثال الثالث
#      ,    
#      : .,  . 
def gaus_func_02(k, m, x, mu, sigma):
    pj_xi = []
    for j in range(k):
        det_sigma_j = np.linalg.det(sigma[j])
        factor_1 = 1 / (((2 * math.pi)**(k/2)) * ((det_sigma_j)**0.5))
        factor_2 = []
        for i in x:
#    ,            
#          
#   .    ,      
#     
            factor_2.append(math.e**float(
            -0.5 * np.matrix(i - mu[j]) * np.matrix(np.linalg.inv(sigma[j])) * np.matrix(i - mu[j]).T))
        pj_xi.append(factor_1 * np.array(factor_2))
    return np.array(pj_xi)

#     ,       №1  №2
def proba_func_02(pjxi, w, k):
    #          
    P_X = []
    for j in range(k):
        P_X.append(w[j] * pjxi[j])
    P_X = np.sum(np.array(P_X), axis = 0)
    #    ,       №1  №2
    P_J_X = []
    for j in range(k):
        P_J_X.append(w[j] * pjxi[j] / P_X)
    return np.array(P_J_X)

#        
def pred_x_02(proba_X, limit_proba):
    pred_X = []
    for x in proba_X[0]:
        if x >= limit_proba:
            pred_X.append(1)
        else:
            pred_X.append(2)
    return np.array(pred_X)

#             
def graph_02_algorithm(pred_X, mu):
    #   
    pred_X = np.array(pred_X)

    #   ,         
    answers_1 = []
    answers_2 = []

    for i in range(pred_X.shape[0]):
        if pred_X[i] == 1:
            answers_1.append(X[i])
        else:
            answers_2.append(X[i])
    
    print ' "     "'
    plt.figure(figsize=(16, 6))  
    plt.plot(
        np.array(answers_1)[:,0], np.array(answers_1)[:,1], 'o', alpha = 0.7, color='sandybrown', label = 'Produced on machine #1')
    plt.plot(
        np.array(answers_2)[:,0], np.array(answers_2)[:,1], 'o', alpha = 0.45, color = 'darkblue', label = 'Produced on machine #2')
    plt.plot(mu[0][0], mu[0][1], 'o', markersize = 16, color = 'red', label = 'Mu 1')
    plt.plot(mu[1][0], mu[1][1], 'o',  markersize = 16, color = 'slateblue', label = 'Mu 2')
    plt.xlabel('Diameter')
    plt.ylabel('Weight')
    plt.legend()
    plt.show()
    
#          
def graph_02_true(X, mu):
    print ' "  "'
    plt.figure(figsize=(16, 6))  
    plt.plot(
        X[0:N1,0], X[0:N1,1], 'o', alpha = 0.7, color='sandybrown', label = 'Produced on machine #1')
    plt.plot(
        X[N1:N,0], X[N1:N,1], 'o', alpha = 0.45, color = 'darkblue', label = 'Produced on machine #2')
    plt.plot(mu[0][0], mu[0][1], 'o', markersize = 16, color = 'red', label = 'Mu 1')
    plt.plot(mu[1][0], mu[1][1], 'o',  markersize = 16, color = 'slateblue', label = 'Mu 2')
    plt.xlabel('Diameter')
    plt.ylabel('Weight')
    plt.legend()
    plt.show()


حدد المعلمات
#  
k = 2

#      №1
N1 = 6000
#      №2
N2 = 4000
N = N1+N2

#   (  )
m = 2

#    №1
mu_1_1 = 64.
#    №1
mu_1_2 = 14.
#  
sigma_1_1 = 3.5
sigma_1_2 = 1.

#    №2
mu_2_1 = 52.
#    №2
mu_2_2 = 9.5
#  
sigma_2_1 = 2.
sigma_2_2 = 0.7


سنحسب
X = np.zeros((N, m))
np.random.seed(seed=42)
#    ,   №1
X[:N1, 0] = np.random.normal(loc=mu_1_1, scale=sigma_1_1, size=N1)
X[:N1, 1] = np.random.normal(loc=mu_1_2, scale=sigma_1_2, size=N1)
#  ,   №2
X[N1:N, 0] = np.random.normal(loc=mu_2_1, scale=sigma_2_1, size=N2)
X[N1:N, 1] = np.random.normal(loc=mu_2_2, scale=sigma_2_2, size=N2)

#    (   ,    )
y = np.zeros((N))
y[:N1] = np.array((1))
y[N1:N] = np.array((2))

#           (  )
mu  = np.array(([mu_1_1, mu_1_2], [mu_2_1, mu_2_2]))

#        (  )
sigma = np.array(([sigma_1_1, 0.],[0., sigma_1_2], [sigma_2_1, 0.],[0., sigma_2_2]))
sigma = sigma.reshape(k, m, m)

#     ,    №1  №2
w = np.array([float(1./k), float(1./k)])

#   
pj_xi = gaus_func_02(k, m, X, mu, sigma)
proba_X = proba_func_02(pj_xi, w, m)

#   ,   ,        
limit_proba = 0.5

pred_X = pred_x_02(proba_X, limit_proba)
        
#    
print '   :', round(accuracy_score(y, pred_X),3)
print

graph_02_algorithm(pred_X, mu)

graph_02_true(X, mu)


الرسم البياني رقم 2.1 "توزيع المنتجات وفقًا للخوارزمية"


الرسم البياني رقم 2.2 "التوزيع الحقيقي للمنتجات" من


خلال القياس مع المثال السابق ، قمنا بتوليد 10000 قيم وفقًا للمعايير المذكورة أعلاهμ و σ، كتب عدة وظائف لتشغيل الخوارزمية وأطلقناها. الفرق الأساسي بين هذا الرمز والشفرة من المثال السابق هو أننا هذه المرة استخدمنا تعبيرات المصفوفة للحسابات.

نتيجة لذلك ، تظهر الخوارزمية نسبة الإجابات الصحيحة التي تساوي 0.998 ، وهي في الواقع جيدة جدًا.

المشاكل ، كما نرى ، هي نفسها - أخطاء في التفاصيل التي تم إنتاجها على أجهزة مختلفة وفي نفس الوقت لها أبعاد وأوزان متشابهة.

تتم كتابة الرمز بحيث يمكن للقارئ استبدال أي قيم معلماتμ و σوانظر كيف ستعمل الخوارزمية: في أي حالة ستتدهور الجودة ، وفيها ستتحسن. الشيء الرئيسي هو عدم نسيان دراسة الجدول الزمني. حسنًا ، نحن ننتقل إلى نقطتنا النهائية في تحليل خوارزمية EM ، في الواقع خوارزمية EM نفسها.

تعرف على خوارزمية EM


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

للوهلة الأولى ، يبدو الأمر غير واقعي تقريبًا ، ولكن في الحقيقة لدينا بين أيدينا مجموعة أدوات قوية: صيغة Bayes وصيغة كثافة الاحتمال لمتغير عشوائي. دعونا نأخذ كل هذا الخير.

الحل

ماذا سنفعل؟ كما يجب أن يكون في خوارزمية EM ، نقوم أولاً بتهيئة المعلمات:

احتمال الفرضية هو استخراج الجزء المنتج على الجهاز رقم 1 -w1 نحدد احتمال فرضية لاستخراج الجزء المنتج على الجهاز رقم 2 - w2. هناك فرضيتان فقط ، مما يعني أن كل منهما في الخطوة الأولى سيكون مساوياً لـ 0.5.

التوقع الرياضي للمتغيرات العشوائيةμتعرف على النحو التالي. نمزج جميع المنتجات باستخدام الوظيفة العشوائية ، ونقسم المجموعة بالتساوي إلى قسمين ، لكل جزء لكل معلمة (القطر ، الوزن) نحدد متوسط ​​القيمة.

الانحراف المعياريσخذ ما يسمى من السقف - اجعله يساوي الوحدة في جميع النواحي. نكتب في شكل مصفوفة التغاير.

نحن على استعداد للقيام بالخطوة الأولى من الخوارزمية. باستخدام المعلمات الأولية للمتغيرات العشوائية ، نحدد احتمالية تخصيص كل جزء للجهاز رقم 1 أو للجهاز رقم 2.

في الواقع ، بهذه الطريقة ، اتخذنا الخطوة الأولى.

الآن الأمر متروك لخطوة M. كل شيء بسيط هنا. بعد أن حددنا احتمالية إنتاج كل جزء على آلة معينة ، يمكننا إعادة حساب احتمالية كل فرضية -w1، w2و μو σ.

سنقوم بـ 15 عملية تكرار من هذا القبيل ، في خطوتين لكل منهما

.
الوظائف المستخدمة في خوارزمية EM
#   E-
def e_step(x, k, m, n, w, mu, sigma):
    #      i-     j-  
    pj_xi = []
    for j in range(k):
        det_sigma_j = np.linalg.det(sigma[j])
        factor_1 = 1 / (((2 * math.pi)**(k/2)) * ((det_sigma_j)**0.5))
        factor_2 = []
        for i in x:
            factor_2.append(math.e**float(
                -0.5 * np.matrix(i - mu[j]) * np.matrix(np.linalg.inv(sigma[j])) * np.matrix(i - mu[j]).T))
        pj_xi.append(factor_1 * np.array(factor_2))
    pj_xi = np.array(pj_xi)
    
    #     ,  i-    j- 
    pj_xi_w = []
    for j in range(k):
        pj_xi_w.append(pj_xi[j] * w[j])
    pj_xi_w = np.array(pj_xi_w)
    
    #     i-      
    sum_pj_xi_w = np.sum(pj_xi_w, axis = 0)
    
    #         
    proba_xi = []
    for j in range(k):
        proba_xi.append(pj_xi_w[j] / sum_pj_xi_w)
    
    return np.array(proba_xi)

#  ,    ,            ,
#       
def x_new(proba_xi):
    X1_new_ind = []
    X2_new_ind = []
    X_answers = []

    count = 0
    for x in proba_xi[0]:
        if x >= 0.5:
            X1_new_ind.append(count)
            X_answers.append(1)
        else:
            X2_new_ind.append(count)
            X_answers.append(2)
        count += 1
    #      ,    №1, №2   
    return X1_new_ind, X2_new_ind, X_answers


#   M-
def m_step(x, proba_xi,N):
    w_new = np.sum(proba_xi, axis = 1) / N
    
    #   
    mu_new = (np.array((np.matrix(proba_xi) * np.matrix(X))).T / np.sum(proba_xi, axis = 1)).T
    
    #  
    cov_new = []
    for mu in range(mu_new.shape[0]):
        X_cd = []
        X_cd_proba = []
        count = 0
        for x_i in x:
            cd = np.array(x_i - mu_new[mu])
            X_cd.append(cd)
            X_cd_proba.append(cd * proba_xi[mu][count])
            count += 1
        X_cd = np.array(X_cd)
        X_cd = X_cd.reshape(N, m)
        X_cd_proba = np.array(X_cd_proba)
        X_cd_proba = X_cd_proba.reshape(N, m)

        cov_new.append(np.matrix(X_cd.T) * np.matrix(X_cd_proba))
    cov_new = np.array((np.array(cov_new) / (np.sum(proba_xi, axis = 1)-1)))
    #             ,    
    #       ,        
    if cov_new[0][0][1] < 0:
        cov_new[0][0][1] = 0
    if cov_new[0][1][0] < 0:
        cov_new[0][1][0] = 0
    
    if cov_new[1][0][1] < 0:
        cov_new[1][0][1] = 0
    if cov_new[1][1][0] < 0:
        cov_new[1][1][0] = 0
    
    #   
    sigma_new = cov_new**0.5
    return w_new, mu_new, sigma_new


حدد المعلمات
#   
#      №1 ( 1)
N1 = 6000
#      №2 ( 2)
N2 = 4000
#       
N = N1 + N2

#  
k = 2

#    №1
mu_samples_1_1 = 64.
#    №1
mu_samples_1_2 = 14.

#    №2
mu_samples_2_1 = 52.
#    №2
mu_samples_2_2 = 9.5

#      №1
sigma_samples_1_1 = 3.5
#      №1
sigma_samples_1_2 = 1.

#      №2
sigma_samples_2_1 = 2.
#      №2
sigma_samples_2_2 = 0.7


سنحسب
X = np.zeros((N, 2))

np.random.seed(seed=42)
#    ,    №1
X[:N1, 0] = np.random.normal(loc=mu_samples_1_1, scale=sigma_samples_1_1, size=N1)
X[:N1, 1] = np.random.normal(loc=mu_samples_1_2, scale=sigma_samples_1_2, size=N1)
#    ,    №2
X[N1:N, 0] = np.random.normal(loc=mu_samples_2_1, scale=sigma_samples_2_1, size=N2)
X[N1:N, 1] = np.random.normal(loc=mu_samples_2_2, scale=sigma_samples_2_2, size=N2)

#   
m = X.shape[1]

#   
n = X.shape[0]

#        (   )
y = np.zeros((N))
y[:N1] = np.array((1))
y[N1:N] = np.array((2))

#     ,    №1  №2
w = np.array([float(1./k), float(1./k)])

np.random.seed(seed = None)
#        (   )
mu  = np.array(
    (np.mean(X[np.random.choice(n, n/k)], axis = 0), np.mean(X[np.random.choice(n, n/k)], axis = 0)))
# mu = np.array(([mu_samples_1_1, mu_samples_1_2],[mu_samples_2_1, mu_samples_2_2]))

#         (    )
sigma = np.array(([1., 0.],[0., 1.], [1., 0.],[0., 1.]))
# sigma = np.array(([sigma_samples_1_1, 0.],[0., sigma_samples_1_2], [sigma_samples_2_1, 0.],[0., sigma_samples_2_2]))
sigma = sigma.reshape(k, m, m)

#    EM-
steps = 15
#   EM-
for i in range(steps):
    proba_xi = e_step(X, k, m, n, w, mu, sigma)
    w, mu, sigma = m_step(X, proba_xi,N)
    X1_new_ind, X2_new_ind, X_answers = x_new(proba_xi)
    print ' №', i+1
    print
    print '   '
    print mu
    print
    print '   '
    print sigma
    print
    print '   '
    print round(accuracy_score(y, X_answers),3)
    
    plt.figure(figsize=(16, 6))  
    plt.plot(
        X[X1_new_ind,0], X[X1_new_ind,1], 'o', alpha = 0.7, color='sandybrown', label = 'Produced on machine #1')
    plt.plot(
        X[X2_new_ind,0], X[X2_new_ind,1], 'o', alpha = 0.45, color = 'darkblue', label = 'Produced on machine #2')
    plt.plot(mu[0][0], mu[0][1], 'o', markersize = 16, color = 'red', label = 'Mu 1')
    plt.plot(mu[1][0], mu[1][1], 'o',  markersize = 16, color = 'purple', label = 'Mu 2')
    plt.xlabel('Diameter')
    plt.ylabel('Weight')
    plt.legend()
    plt.show()


الرسم البياني 3.1 "توزيع الأجزاء عند كل تكرار للخوارزمية EM"

جميع التكرارات
















ماذا حدث في النهاية؟ وتبين ما يلي ، دون وجود معلومات أولية حول احتمالية الفرضيات لاستخراج الأجزاء المنتجة على الجهاز رقم 1 -w1 أو الجهاز رقم 2 w2والتوقع الرياضي والانحراف المعياري للمتغيرات العشوائية - μو σ، حققنا جودة مماثلة للمثال السابق ، حيث كانت جميع المعلمات المذكورة أعلاه معروفة.

قارن المعلمات التي قمنا بتعيينها عند إنشاء مجموعة المنتجات ، والمعلمات المسماة بالمعلمات الحقيقية والمعلمات التي حددتها لنا خوارزمية EM:

المعلمات الحقيقية

μ11=64,μ12=14,σ11=3.5,σ12=1.

μ21=52,μ12=9.5,σ21=2.0,σ22=0.7

معلمات محددة

μ1164.03,μ1213.99,σ113.44,σ121.23

μ2152.06,μ129.54,σ211.65,σ220.77

في هذه المقالة ينتهي. في الختام ، سأضيف أنه لغرض تحليل البيانات ، ليس من المنطقي إعادة اختراع العجلة وكتابة خوارزمية EM بنفسك ، يمكنك ببساطة استخدام وظيفة مكتبة sklearn المتوفرة.

دعونا نرى كيف تعمل مكتبة sklearn GaussianMixture على مثالنا.

وحدة استيراد
from sklearn.mixture import GaussianMixture as GMM


حدد المعلمات
#   
#      №1 ( 1)
N1 = 6000
#      №2 ( 2)
N2 = 4000
#       
N = N1 + N2

#    №1
mu_samples_1_1 = 64.
#    №1
mu_samples_1_2 = 14.

#    №2
mu_samples_2_1 = 52.
#    №2
mu_samples_2_2 = 9.5

#      №1
sigma_samples_1_1 = 3.5
#      №1
sigma_samples_1_2 = 1.

#      №2
sigma_samples_2_1 = 2.
#      №2
sigma_samples_2_2 = 0.7


#  
k = 2

X = np.zeros((N, 2))

np.random.seed(seed=42)
#    ,    №1
X[:N1, 0] = np.random.normal(loc=mu_samples_1_1, scale=sigma_samples_1_1, size=N1)
X[:N1, 1] = np.random.normal(loc=mu_samples_1_2, scale=sigma_samples_1_2, size=N1)
#    ,    №2
X[N1:N, 0] = np.random.normal(loc=mu_samples_2_1, scale=sigma_samples_2_1, size=N2)
X[N1:N, 1] = np.random.normal(loc=mu_samples_2_2, scale=sigma_samples_2_2, size=N2)

#        (   )
y = np.zeros((N))
y[:N1] = np.array((1))
y[N1:N] = np.array((2))


قم بتشغيل خوارزمية EM
np.random.seed(1)
model = GMM(n_components=k, covariance_type='full')
model.fit(X)


temp_predict_X = model.predict(X)
X_answers = []
for i in range(X.shape[0]):
    if temp_predict_X[i] == 0:
        X_answers.append(1)
    else:
        X_answers.append(2)
        

print '   '
print round(accuracy_score(y, X_answers),3)


عملت مع ضجة! لا أخطاء! كما تتوقع ، فإن مكتبة GaussianMixture في Skussian أسرع وأفضل من الخوارزمية. ومع ذلك ، كان الغرض من المقالة ، كما نتذكر ، هو فهم كيفية عمل خوارزميات EM. أتمنى أن يتحقق الهدف :)

مصادر المعلومات


الأدب

1) الإحصاء التطبيقي: التصنيفات وخفض الأبعاد ، S.A. Ayvazyan ، V.M. Buchstaber ، I.S. Enyukov، L.D. Meshalkin، Moscow، Finance and Statistics، 1989

موارد الإنترنت

1) مقالة "برنامج تعليمي لطيف عن خوارزمية EM وتطبيقها على تقدير المعلمات لخليط غوسي ونماذج ماركوف المخفية" ، المعهد الدولي لعلوم الكمبيوتر ، Jeff A. Bilmes ، 1998

2) عرض تقديمي "نماذج المزيج وخوارزمية EM" ، جامعة نيويورك ، David Sontag

3) دورة "البحث عن هياكل البيانات"

4) صيغة الاحتمال الكامل وصيغ Bayes

5) الوظيفة "sklearn.mixture.GaussianMixture"

6) التوزيع العادي ، ويكيبيديا

7) متعدد الأبعاد التوزيع الطبيعي ، ويكيبيديا

8)github.com/diefimov/MTH594_MachineLearning/blob/master/ipython/Lecture10.ipynb

9) مقال عن خوارزمية EM

10) مقال آخر عن خوارزمية EM

11) Github github.com/AlexanderPetrenko83/Articles

All Articles