Sandwood هي لغة ومترجم ووقت تشغيل للنماذج الاحتمالية القائمة على JVM. إنه مصمم للسماح بكتابة النماذج بلغة مألوفة لمطوري Java. تأخذ النماذج الناتجة شكل كائنات Java مما يسمح لها بأن تكون مكونات مجردة جيدًا لنظام شامل.
مع نموذج بايزي التقليدي، يتعين على المستخدم تصميم النموذج، ثم تنفيذ كود الاستدلال لأي عملية يرغب في تنفيذها على النموذج. وهذا يخلق عددا من القضايا:
يعد إنشاء رمز الاستدلال أمرًا صعبًا من الناحية الفنية ويستغرق وقتًا طويلاً. تمثل هذه الخطوة فرصة لإدخال الأخطاء الدقيقة.
إذا تم تعديل النموذج، فيجب تحديث رمز الاستدلال. وهذا أيضًا يستغرق وقتًا طويلاً ويمثل تحديًا تقنيًا، مما يؤدي إلى المشكلات التالية:
إنه بمثابة رادع لتعديل النماذج.
من الممكن أن تخرج عمليات الاستدلال المختلفة عن الخطوة، بحيث يعمل بعضها على النموذج القديم والبعض الآخر على النموذج الجديد.
إنه يقدم فرصة أخرى للأخطاء للدخول إلى خوارزمية الاستدلال حيث يحاول المستخدمون إجراء تعديلات طفيفة على التعليمات البرمجية الموجودة.
تتغلب البرمجة الاحتمالية على هذه المشكلات من خلال السماح بوصف النماذج باستخدام إما واجهة برمجة التطبيقات (API) أو لغة مجال محدد (DSL) كما هو الحال مع Sandwood. يتم تجميع Sandwood DSL لإنتاج فئات Java التي تمثل النموذج وتنفذ جميع عمليات الاستدلال المطلوبة. وهذا له عدد من المزايا:
يتكون Sandwood من 3 مكونات لكل منها في الدليل المقابل لها:
كل قطعة تعتمد على القطع السابقة. يحتوي كل دليل مكون على ملف Maven POM لإنشاء المكون. بالنسبة للمترجم والمكون الإضافي، يجب استدعاءهما مع install
لإتاحتهما للمراحل اللاحقة، مثل mvn clean install
. يجب إنشاء الأمثلة فقط mvn clean package
.
بعد تثبيت Sandwood، توجد حاليًا ثلاث طرق لتجميع النموذج:
لاستخدام Sandwood من سطر الأوامر بمجرد إنشاء المترجم ووقت التشغيل، يمكن العثور على نصوص برمجية لسطر الأوامر لها وظائف مشابهة لـ javac
في commandline/SandwoodC/bin
. لاستخدام هذا، يقوم المستخدم عادةً بإضافة دليل bin إلى المسار، ثم استدعاء sandwoodc.sh HMM.sandwood لتجميع نموذج HMM. سوف يؤدي sandwoodc.sh -h
أو sandwoodc.bat -h
إلى طباعة وصف للاستخدام والخيارات المتاحة.
يمكن الوصول إلى جميع وظائف SandwoodC عن طريق استدعاء الأسلوب compile
في org.sandwood.compilation.SandwoodC
وتمرير مصفوفة تحتوي على الوسائط التي كان من الممكن تمريرها إلى سطر الأوامر.
يمكن استخدام البرنامج المساعد Maven لتشغيل تجميع ملفات Sandwood تلقائيًا عند إنشاء المشروع التابع. لاستخدام البرنامج المساعد، تحتاج إلى إضافة وقت تشغيل Sandwood باعتباره تبعية، وإضافة البرنامج المساعد إلى الإصدار. يتم تحقيق ذلك من خلال الإضافات التالية إلى ملف POM:
<dependencies>
<dependency>
<groupId>org.sandwood</groupId>
<artifactId>sandwood-runtime</artifactId>
<version>0.3.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.sandwood</groupId>
<artifactId>sandwoodc-maven-plugin</artifactId>
<version>0.3-SNAPSHOT</version>
<executions>
<execution>
<configuration>
<partialInferenceWarning>true</partialInferenceWarning>
<sourceDirectory>${basedir}/src/main/java</sourceDirectory>
</configuration>
<goals>
<goal>sandwoodc</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>`
يؤدي تضمين العنصر <sourceDirectory>${basedir}/src/main/java</sourceDirectory>
إلى توجيه المكون الإضافي إلى الدليل الذي يجب البحث فيه عن النماذج. تشمل العلامات المفيدة الأخرى ما يلي:
debug
يستخدم هذا الخيار للحصول على معلومات التصحيح من SandwoodC. يؤدي تعيين هذا الخيار إلى true
إلى قيام Sandwood بإنشاء أثر لإجراءاته. القيمة الافتراضية false
. لاحظ أن هذه العلامة مخصصة لتصحيح الأخطاء في تكوين/مترجم المحول البرمجي، وليس مع النموذج الذي يتم تجميعه. سيتم دائمًا إرجاع الأخطاء والتحذيرات في ملفات نموذج Sandwood بواسطة المترجم.
partialInferenceWarning
يتم استخدام هذا الخيار لمنع SandwoodC من الفشل عندما لا يمكن إنشاء بعض خطوات الاستدلال. يؤدي تعيين هذا الخيار إلى true
إلى قيام Sandwood بإنشاء تحذيرات بشأن الخطوات المفقودة. القيمة الافتراضية false
.
sourceDirectory
تحدد هذه المعلمة الدليل الذي سيتم البحث فيه عن ملفات النموذج. ضمن هذا الدليل، يمكن وضع النماذج في حزم مختلفة.
outputDirectory
تحدد هذه المعلمة الدليل الذي يجب وضع كود مصدر Java للنماذج فيه. القيمة الافتراضية هي ${project.build.directory}/generated-sources/sandwood
.
calculateIndividualProbabilities
تحدد هذه المعلمة ما إذا كان يجب حساب احتمالات كل متغير عشوائي تم إنشاؤه في حلقة بدلاً من قيمة واحدة لجميع المثيلات. القيمة الافتراضية false
.
javadoc
ترشد هذه المعلمة المترجم إلى إنشاء JavaDoc لتكمل النموذج. القيمة الافتراضية false
.
javadocDirectory
تحدد هذه المعلمة الموقع الذي يجب وضع المنشأة فيه.
executable
تسمح هذه المعلمة بتحديد JVM بديل لتشغيل برنامج التحويل البرمجي Sandwood.
ما يلي هو مقدمة لكيفية كتابة نماذج Sandwood وكيفية استخدام الفئات الناتجة التي تنفذ النماذج.
يمكن رؤية الخطوط العريضة للخطوات التي يمر بها النموذج في هذا الرسم البياني. تبدأ النماذج كملف .sandwood
الذي يتم تجميعه إلى مجموعة من ملفات الفئات. يمكن إنشاء مثيل لها عدة مرات لإنشاء مثيلات متعددة للنموذج بتكوينات مختلفة.
كمثال على ذلك، سوف نستخدم نموذج ماركوف المخفي (HMM). هذا النموذج مكتوب هنا في Sandwood. يجب حفظ هذا النموذج في ملف يسمى HMM.sandwood
في دليل الحزمة org/sandwood/examples/hmm
. يمكن العثور على وصف أكمل للغة هنا.
package org . sandwood . examples . hmm ;
model HMM ( int [] eventsMeasured , int numStates , int numEvents ) {
//Construct a transition matrix m.
double [] v = new double [ numStates ] <~ 0.1 ;
double [][] m = dirichlet ( v ). sample ( numStates );
//Construct weighting for which state to start in.
double [] initialState = new Dirichlet ( v ). sample ();
//Construct weighting for each event in each state.
double [] w = new double [ numEvents ] <~ 0.1 ;
double [][] bias = dirichlet ( w ). sample ( numStates );
//Allocate space to record the sequence of states.
int sequenceLength = eventsMeasured . length ;
int [] st = new int [ sequenceLength ];
//Calculate the movements between states.
st [ 0 ] = categorical ( initialState ). sampleDistribution ();
for ( int i : [ 1. . sequenceLength ) )
st [ i ] = categorical ( m [ st [ i - 1 ]]). sampleDistribution ();
//Emit the events for each state.
int [] events = new int [ sequenceLength ];
for ( int j = 0 ; j < sequenceLength ; j ++)
events [ j ] = new Categorical ( bias [ st [ j ]]). sample ();
//Assert that the events match the eventsMeasured data.
events . observe ( eventsMeasured );
}
بالإضافة إلى توثيق لغة Sandwood وتعليق JavaDoc الذي يمكن إنشاؤه لنموذج، يوجد عدد من الأمثلة في دليل أمثلة Sandwood ونقترح على المستخدمين الجدد البدء بفحصها وتعديلها.
يمكن العثور هنا على وصف للغة المستخدمة لوصف نماذج Sandwood. تم إنشاء اللغة بهدف أن تكون مألوفة لمطوري Java، ولكنها لا تحتوي على القدرة على إنشاء الكائنات. نحن نخطط لإضافة دعم لأنواع السجلات في المستقبل لتسهيل استيراد البيانات وتصديرها من وإلى النماذج.
عندما يتم تجميع نموذج، يتم إنشاء عدد من ملفات الفئات في نفس الحزمة التي تم تعريف النموذج فيها. سيكون لإحدى هذه الفئات نفس اسم الاسم المقدم للنموذج، لذلك في هذه الحالة HMM.class ، وهذا هي الفئة التي يجب على المستخدم إنشاء مثيل لها من أجل الحصول على مثيل للنموذج. يتوافق كل متغير مرئي بشكل عام في النموذج مع حقل في الفئة التي تم إنشاؤها. يمكن رؤية المثال HMM أدناه.
من خلال تشغيل المترجم باستخدام مجموعة علامات javadoc
، سيتم إنشاء JavaDoc لكل طريقة عامة وفئة في ملف النموذج الذي تم إنشاؤه.
بمجرد تجميع النموذج، نحتاج إلى إنشاء مثيلات له. هذه المثيلات مستقلة ويمكن للمستخدم إنشاء العديد من النسخ المختلفة للنموذج كما يحلو له.
يتم إنشاء مثيلات كائن النموذج عبر مُنشئ الفئة. كما هو موضح سابقًا، يوجد عادةً 3 مُنشئات للنموذج. الحالة الوحيدة التي سيكون فيها العدد أقل هي عندما يتم ربط المتغيرات المختلفة للمنشئ بنفس التوقيع، وفي هذه الحالة سيتم تطبيق مُنشئ واحد على أكثر من واحد من هذه السيناريوهات.
المُنشئ الكامل - يأخذ هذا المُنشئ كافة الوسائط التي تظهر في توقيع النموذج ويقوم بتعيينها. يتم استخدام هذا المنشئ لقيم الاستدلال وعمليات احتمالات الاستدلال.
مُنشئ فارغ - لا يأخذ هذا المُنشئ أية وسائط، ويترك المعلمات للمستخدم ليقوم بتعيينها لاحقًا.
مُنشئ التنفيذ - يقوم هذا المنشئ بإزالة الوسائط التي تمت ملاحظتها فقط، وبالنسبة للوسائط التي تمت ملاحظتها والتي يتم استخدام أبعادها كمدخلات للتعليمات البرمجية، فإنه يأخذ تلك الأبعاد بدلاً من المعلمات الكاملة. لذلك في مثال HMM، ستصبح المعلمة eventsMeasured عددًا صحيحًا يصف طول التسلسل.
توضح نماذج التعليمات البرمجية هذه كيفية إجراء مكالمات إلى النماذج المترجمة.
التفاعلات مع النموذج عبر كائن النموذج تأخذ شكلين:
استدعاء أساليب كائن النموذج للعمليات العالمية مثل تعيين سياسات الاحتفاظ الافتراضية، والتحقق مما إذا كان النموذج جاهزًا للاستدلال، وبدء خطوات الاستدلال، وما إلى ذلك.
استدعاء كائنات المعلمات النموذجية. يتم تمثيل كل متغير عام مسمى في النموذج بحقل مناظر في كائن النموذج. تكون المتغيرات عامة إذا تم الإعلان عنها في النطاق الخارجي للنموذج ولم يتم تصنيفها على private
، أو تم الإعلان عنها في النطاق الداخلي ولم يتم تصنيفها على public
. إذا تم الإعلان عن حقل عام في نطاق تكراري داخلي، على سبيل المثال نص حلقة for، فسيتم تخزين القيمة من كل تكرار.
يعتمد نوع الكائن على المتغير. يمكن تقسيمها إلى 3 فئات:
يشير كل حقل من هذه الحقول إلى كائن بمجموعة من الأساليب التي تسمح للمستخدم بتعيين وقراءة القيم والخصائص من المعلمة. تتضمن الخصائص التي يمكن تعيينها وقراءتها احتمالية المعلمة، وسياسة الاحتفاظ بالمعلمة، وما إذا كان يجب تثبيت المعلمة عند قيمتها الحالية.
بعض الطرق الأكثر أهمية لكائن المعلمة عند إجراء الاستدلال النموذجي هي:
getSamples لإرجاع القيم التي تم أخذ عينات منها.
getMAP لإرجاع القيمة القصوى A اللاحقة.
setValue للسماح بتعيين قيمة على قيمة محددة.
setFixed الذي يأخذ قيمة boolean
لتمييز القيمة على أنها ثابتة، وبالتالي لا يتم تحديثها أثناء الاستدلال. من المهم تعيين قيمة المعلمة قبل إصلاحها.
getLogProbability الذي يحصل على احتمالية السجل للمتغير بعد استنتاج الاحتمالات.
هناك المزيد من الطرق، ونوصي باستشارة JavaDoc للتعرف عليها.
هناك ثلاثة أنواع أساسية من العمليات التي يمكن إجراؤها على النموذج:
setRentionPolicy
في فئة النموذج. اختياريًا، يمكن للمتغيرات الفردية تعيين سياسة الاحتفاظ الخاصة بها عن طريق استدعاء أسلوب setRetentionPolicy
المقابل في كل كائن متغير.هناك 3 سياسات لأخذ العينات:
NONE لا يسجل أية قيم. يعد هذا مفيدًا بشكل خاص إذا كان أحد المتغيرات كبيرًا، لذا فإن تخصيص الوقت والمساحة لتخزينه سيكون مضيعة للوقت.
تسجل SAMPLE القيمة من كل تكرار لخوارزمية الاستدلال، لذلك إذا تم تنفيذ 1000 تكرار، فسيتم أخذ عينات من 1000 قيمة من كل متغير تم تعيينه لسياسة الاستبقاء هذه. وهذا مفيد لحساب التباين وكذلك القيمة المتوسطة. هناك نقطة ضعف في هذا، إذا كانت مواضع القيم داخل النموذج يمكن أن تتحرك أثناء الاستدلال، فلا يمكن حساب متوسط القيم. على سبيل المثال، مع موضوع نموذج الموضوع 2 و3، قد يتم تبديل الأماكن أثناء الاستدلال، لذا فإن متوسط جميع القيم للموضوع 2 ينتج عنه مزيج من الموضوع 2 والموضوع 3. للتغلب على هذا الحد الأقصى A Postiori (MAP) يتم توفيره أيضًا كبديل سياسة الاحتفاظ.
يسجل MAP أو الحد الأقصى A Postiori (MAP) قيم المتغيرات عندما يكون النموذج في حالته الأكثر احتمالية. يؤدي هذا إلى التغلب على مشكلة مواضع القيمة العابرة، مما يعني أنه لا يمكن حساب متوسط القيم، ولكن على حساب القدرة على حساب الحدود. يتمتع هذا الخيار أيضًا بمزايا المساحة إذا كانت بعض المتغيرات كبيرة.
التكوين: تسمح استدعاءات الطريقة الإضافية على كائن النموذج للمستخدم بتعيين خصائص مثل النسخ والتخفيف عند تنفيذ خطوة الاستدلال هذه. يتجاهل Burnin القيم من التكرارات n الأولى مما يسمح للنموذج بالابتعاد عن نقطة بداية منخفضة الاحتمال قبل البدء في أخذ العينات. يؤدي التخفيف إلى تقليل الارتباط الذاتي الناجم عن إجراء MCMC من خلال النظر فقط في القيم من كل تكرار n .
استنتاج الاحتمالات بعد تعيين قيم بعض أو كل المعلمات في النموذج، قم بحساب احتمالية توليد تلك القيم. يمكن حساب ذلك لكل متغير في النموذج وللنموذج ككل.
تنفيذ النموذج قم بتشغيل النموذج كما لو كان كودًا عاديًا يقوم بإنشاء قيم جديدة لأي معلمات لم يتم إصلاحها بواسطة المستخدم. مثال على متى سيتم استخدام هذا السلوك هو نموذج الانحدار الخطي. في هذه الحالة سيتم أولاً استنتاج معاملات النموذج باستخدام بيانات التدريب. بمجرد استنتاجها، سيتم إصلاحها وإنشاء مجموعة بيانات إدخال جديدة. سيتم بعد ذلك تنفيذ النموذج لإنشاء التنبؤات المقابلة لبيانات الإدخال الجديدة هذه. يمكن أيضًا استخدام هذا النوع من التنفيذ لإنشاء بيانات تركيبية تمثيلية من نموذج مُدرب.
بناء وتدريب نموذج
//Load inputs
int nStates = 25 ;
int [] actions = loadActions (....);
int nActions = maxActions (....);
//Construct the model
HMM model = new HMM ( actions , nActions , nStates );
//Set the retention policies
model . setDefaultRetentionPolicy ( RetentionPolicy . MAP );
model . st . setRetentionPolicy ( RetentionPolicy . NONE );
//Pick a random number generator. The ones introduced in Java 17 are faster and better quality.
model . setRNGType ( RandomType . L64X1024MixRandom );
//Instruct the model to use the ForkJoin framework for parallel execution.
model . setExecutionTarget ( ExecutionTarget . forkJoin );
//Run 2000 inference steps to infer model values
model . inferValues ( 2000 );
//Gather the results.
double [] initialState = model . initialState . getMAP ();
double [][] bias = model . bias . getMAP ();
double [][] transitions = model . m . getMAP ();
بناء النموذج واستنتاج الاحتمالات
//Load inputs
int nStates = 25 ;
int [] actions = loadActions (....);
int nActions = maxActions (....);
//Load model parameters
double [][] bias = model . bias . getMAP ();
double [][] transitions = model . m . getMAP ();
//Construct the model
HMM model = new HMM ( actions , nActions , nStates );
//Set and fix trained values
model . bias . setValue ( bias );
Model . m . setValue ( transitions );
//Run 2000 inference steps to infer probabilities
model . inferProbabilities ( 2000 );
//Recover the probabilities of the model parameter actions.
double actionsProbability = model . actions . getProbability ();
//Recover the probability of the model as a whole
double modelProbability = model . getProbability ()
للحصول على مساعدة بشأن Sandwood، يرجى بدء مناقشة أو الانضمام إليها على صفحة المناقشات.
يرحب هذا المشروع بمساهمات المجتمع. قبل تقديم طلب السحب، يرجى مراجعة دليل المساهمة الخاص بنا.
يرجى الرجوع إلى دليل الأمان الخاص بعملية الكشف عن الثغرات الأمنية المسؤولة.
حقوق الطبع والنشر (ج) 2019-2024 مملوكة لشركة Oracle و/أو الشركات التابعة لها.
تم إصداره بموجب الترخيص العالمي المسموح v1.0 كما هو موضح في https://oss.Oracle.com/licenses/upl/.