كيفية التمييز بين الإصلاح الجيد والإصلاح السيئ ، أو كيف قمنا في SRG بإنشاء مكتبة Java متعددة الخيوط من محلل Tomit

سوف يناقش هذا المقال كيف قمنا بدمج محلل Tomita-parser الذي طورته شركة Yandex في نظامنا ، وتحويله إلى مكتبة ديناميكية ، وتكوين صداقات مع Java ، وجعله متعدد مؤشرات الترابط وحل مشكلة تصنيف النص للتقييم العقاري معه.



بيان المشكلة


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

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

الصورة

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

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

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

الانتقال إلى الحل


من خلال الوسائل المتاحة لاستخراج الحقائق من النص القائم على قواعد خالية من السياق والتي يمكن أن تعمل مع اللغة الروسية ، تم لفت انتباهنا إلى Tomita-parser ومكتبة Yagry في الثعبان. تم رفض Yagry على الفور ، لأنه مكتوب بالكامل في بيثون وبالكاد تم تحسينه بشكل جيد. بدت Tomita جذابة للغاية في البداية: كانت لديها وثائق مفصلة للمطور والكثير من الأمثلة ، وعدت C ++ بسرعة مقبولة. لم يكن من الصعب فهم قواعد كتابة القواعد النحوية ، وكانت النسخة الأولى من المصنف باستخدامه جاهزة في اليوم التالي.

أمثلة على القواعد من قواعدنا التي تستخلص الصفات والأفعال المتعلقة بسياق الإصلاح:

RepairW -> "" | "" | ""; StopWords -> "" | "" | "" | ""; Repair -> RepairW<gnc-agr[1]> Adj<gnc-agr[1]>+ interp (Repair.AdjGroup {weight = 0.5}); Repair -> Verb<gnc-agr[1]> Adj<gnc-agr[1]>* interp (Repair.Verb) RepairW<gnc-agr[1]> {weight = 0.5}; 

القواعد المستخدمة لضمان عدم استرداد المعلومات المتعلقة بحالة الأماكن العامة:

 Repair -> StopWords Verb* Prep* Adj* RepairW; Repair -> Adj+ RepairW Prep* StopWords; 

افتراضيًا ، يكون وزن القاعدة هو 1 ، مع تعيين وزن أصغر للقاعدة ، نضع ترتيب تنفيذها.

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

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

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

كيف جعلنا Tomitha مكتبة متعددة مؤشرات الترابط وتكوين صداقات مع Java


نظامنا مكتوب بلغة Java ، tomita-parser بلغة C ++. كنا بحاجة إلى أن نكون قادرين على استدعاء تحليل نص الإعلان من جافا.

يمكن تقسيم تطوير java-bindings لـ Tomita-parser بشكل مشروط إلى عنصرين - تطبيق إمكانية استخدام Tomita كمكتبة مشتركة ، وفي الواقع ، كتابة طبقة تكامل مع jvm. الصعوبة الرئيسية المعنية الجزء الأول. تم تصميم Tomita نفسها أصلاً للتنفيذ في عملية منفصلة. وتبع ذلك أن العقبات الرئيسية التي تحول دون استخدام المحلل اللغوي في عملية التطبيق هما عاملان.

  1. تم تبادل البيانات من خلال أنواع مختلفة من IO. كان مطلوبًا لتطبيق القدرة على تبادل البيانات مع المحلل اللغوي من خلال الذاكرة. علاوة على ذلك ، كان من الضروري القيام بذلك بطريقة تؤثر إلى الحد الأدنى على رمز المحلل اللغوي نفسه. اقترح تصميم Tomita طريقة لتنفيذ قراءة مستندات الإدخال من الذاكرة كتطبيق لواجهة CDocStreamBase و CDocListRetrieverBase. كان الأمر أكثر صعوبة مع الإخراج - اضطررت إلى لمس رمز مولد xml.
  2. العامل الثاني الناشئ عن مبدأ "محلل واحد - عملية واحدة" هو الحالة العالمية ، المعدلة من حالات مختلفة من المحلل اللغوي. إذا نظرت إلى ملف src / util / generic / singleton.h ، يمكنك رؤية آلية استخدام الحالة المشتركة. من السهل أن تتخيل أنه عند استخدام مثيلين للمحلل اللغوي في نفس مساحة العنوان ، ستحدث حالة سباق. من أجل عدم إعادة كتابة المحلل اللغوي بأكمله ، فقد تقرر تعديل هذه الفئة ، مع استبدال الحالة العامة بدولة محلية بالنسبة إلى سلسلة الرسائل (thread_local). وفقًا لذلك ، قبل استدعاء أي محلل في برنامج التفاف JTextMiner ، نقوم بتعيين متغيرات thread_local هذه على مثيل المحلل اللغوي الحالي ، وبعد ذلك يعمل رمز المحلل اللغوي مع عناوين مثيل المحلل اللغوي الحالي.

بعد القضاء على هذين العاملين ، كان المحلل متاحًا للاستخدام كمكتبة مشتركة من أي بيئة. كتابة jni-binders و java wrapper لم تعد صعبة.

يجب تكوين محلل Tomita قبل الاستخدام. تشبه معلمات التكوين تلك المستخدمة عند استدعاء الأداة المساعدة وحدة التحكم. يتكون التحليل اللغوي نفسه من استدعاء الأسلوب parse () ، الذي يستلم المستندات للتحليل ويعيد xml كسلسلة مع نتائج المحلل اللغوي.

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

مثال على استدعاء مكتبة Tomita من Java:

 /** * @param threadAmount number of threads in the pool * @param tomitaConfigFilename tomita config.proto * @param configDirname dir with configs: grammars, gazetteer, facttypes.proto */ tomitaPooledParser = new TomitaPooledParser(threadAmount, new File(configDirname), new String[]{tomitaConfigFilename}); Future<String> result = tomitaPooledParser.parse(documents); String response = result.get(); 

ردا على ذلك ، سلسلة XML مع نتيجة التحليل.

المشكلات التي واجهناها وكيف حلناها


لذلك ، المكتبة جاهزة ، نبدأ الخدمة باستخدامها على كمية كبيرة من البيانات ونتذكر مشكلة عدم استخراج بعض الكلمات ، مع إدراك أن هذا أمر بالغ الأهمية لمهمتنا.

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

من أجل حل مشكلات تحليل القواعد النحوية ، نضيف كلمة بمفردات غير معروفة إلى المعجم:

 TAuxDicArticle "adjNonExtracted" { key = "" | "-" } 

للمشاركين المختصرة نستخدم الخصائص النحوية ل partcp ، brev.

والآن يمكننا كتابة القواعد لهذه الحالات:

 Repair -> RepairW<gnc-agr[1]> Word<gram="partcp,brev",gnc-agr[1]> interp (Repair.AdjGroup) {weight = 0.5}; Repair -> Word<kwtype="adjNonExtracted",gnc-agr[1]> interp (Repair.AdjGroup) RepairW<gnc-agr[1]> Prep* Adj<gnc-agr[1]>+; 

وآخر المشاكل التي اكتشفناها هي خدمة ذات استخدام متعدد مؤشرات ترابط لمكتبة Tomita تنتج عمليات myStem التي لم يتم إتلافها وبعد مرور بعض الوقت تملأ الذاكرة بالكامل. كان الحل الأسهل هو الحد الأقصى والحد الأدنى لعدد مؤشرات الترابط في Tomcat.

بضع كلمات عن التصنيف


لذلك ، لدينا الآن معلومات الإصلاح المستخرجة من النص. لم يكن من الصعب تصنيفها باستخدام واحدة من خوارزميات تعزيز التدرج. لن نتوقف هنا لفترة طويلة حول هذا الموضوع ، لقد قيل وكُتب الكثير حول هذا الموضوع ، ولم نفعل شيئًا جديدًا بشكل جذري في هذا المجال. سأقدم فقط مؤشرات الجودة للتصنيف التي حصلنا عليها في الاختبارات:

  • دقة = 95 ٪
  • درجة F1 = 93 ٪

الخاتمة


تعمل الخدمة المنفذة باستخدام Tomita-parser في وضع المكتبة حاليًا بشكل مطرد ، حيث تقوم بتحليل وتصنيف عدة ملايين من الإعلانات يوميًا.

PS


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

Source: https://habr.com/ru/post/ar439614/


All Articles