كل من قضى وقتًا معينًا في دعم الأنظمة على دراية بالشعور بـ déjà vu عندما تلقوا تطبيقًا جديدًا: "لقد كان الأمر كذلك ، تم حلها ، لكنني لا أتذكر كيف بالضبط". يمكنك قضاء بعض الوقت ، والتصفح في التطبيقات السابقة ومحاولة العثور على تطبيقات مماثلة. سيساعد ذلك: سيتم إغلاق الحادث بشكل أسرع ، أو قد يكون من الممكن اكتشاف السبب الجذري وإغلاق المشكلة مرة واحدة وإلى الأبد.
الموظفون "الشباب" الذين انضموا للتو إلى الفريق ليس لديهم مثل هذه القصة في رؤوسهم. على الأرجح ، أنهم لا يعرفون أن حادثة مماثلة ، على سبيل المثال ، وقعت قبل ستة أشهر إلى سنة. وقرر الزميل من الغرفة المجاورة هذا الحادث.
على الأرجح ، لن يبحث الموظفون "الشباب" عن شيء مشابه في قاعدة بيانات الحوادث ، لكنهم سيحلون المشاكل من الصفر. قضاء المزيد من الوقت ، واكتساب الخبرة ، والتكيف في المرة القادمة بشكل أسرع. أو ربما ينسون ذلك على الفور ضمن مجموعة التطبيقات الجديدة. وفي المرة القادمة سوف يحدث كل شيء مرة أخرى.
نحن نستخدم بالفعل نماذج ML لتصنيف الحوادث . لمساعدة فريقنا في معالجة التطبيقات بشكل أكثر كفاءة ، أنشأنا نموذج ML آخر لإعداد قائمة من "حوادث مماثلة مغلقة سابقًا". التفاصيل - تحت الخفض.
ماذا نحتاج؟
لكل حادث وارد ، من الضروري إيجاد حوادث مغلقة "مماثلة" في التاريخ. يجب أن يحدث تعريف "التشابه" في بداية الحادث ، ويفضل قبل أن يبدأ فريق الدعم التحليل.
لمقارنة الحوادث ، من الضروري استخدام المعلومات التي يقدمها المستخدم عند الاتصال: وصف موجز ووصف تفصيلي (إن وجد) ، وأية سمات لسجل المستخدم.
يدعم الفريق 4 مجموعات من الأنظمة. يبلغ إجمالي عدد الحوادث التي أريد استخدامها للبحث عن حوادث مماثلة حوالي 10 آلاف حادث.
القرار الأول
لا توجد معلومات مؤكدة عن "تشابه" الحوادث التي تحدث. لذلك ، يجب تأجيل الخيارات الحديثة لتدريب شبكات سيامي في الوقت الحالي.
أول ما يتبادر إلى الذهن هو تجميع بسيط لـ "حقيبة كلمات" مكونة من محتويات الطعون.
في هذه الحالة ، تكون عملية التعامل مع الحوادث كما يلي:
- تسليط الضوء على أجزاء النص اللازمة
- النص قبل المعالجة / التنظيف
- TF- جيش الدفاع الإسرائيلي vectorization
- البحث عن أقرب جار لك
من الواضح أنه مع النهج الموصوف ، سيتم التشابه على أساس مقارنة القواميس: استخدام نفس الكلمات أو n-gram في حادثين مختلفين سيعتبر "تشابه".
بالطبع ، هذا هو نهج مبسط إلى حد ما. لكن تذكر أننا نقوم بتقييم نصوص الزيارات للمستخدم ، إذا تم وصف المشكلة بكلمات مماثلة - على الأرجح تكون الحوادث متشابهة. بالإضافة إلى النص ، يمكنك إضافة اسم قسم المستخدم ، مع توقع أن يواجه مستخدمو نفس الإدارات في مؤسسات مختلفة مشكلات مماثلة.
تسليط الضوء على أجزاء النص اللازمة
بيانات الحوادث التي نحصل عليها من service-now.com بأبسط الطرق - من خلال تشغيل التقارير المخصصة برمجيًا واسترداد نتائجها في شكل ملفات CSV.
يتم إرجاع البيانات على الرسائل المتبادلة بين الدعم والمستخدمين كجزء من الحادث في هذه الحالة في شكل حقل نص كبير واحد ، مع سجل المراسلات بأكمله.
المعلومات المتعلقة بالنداء الأول من مثل هذا الحقل يجب أن "تقطع" بتعبيرات منتظمة.
- جميع الرسائل مفصولة بسطر مميز <عندما> - <عند>.
- غالبًا ما تنتهي الرسائل بتوقيعات رسمية ، خاصة إذا تم تقديم الطعن عن طريق البريد الإلكتروني. هذه المعلومات هي "fonil" بشكل ملحوظ في قائمة الكلمات الهامة ، لذلك كان لا بد من حذف التوقيع.
اتضح شيء مثل هذا:
def get_first_message(messages): res = "" if len(messages) > 0:
تجهيز النصوص الحادث
لتحسين جودة التصنيف ، تتم معالجة نص الاستئناف مسبقًا.
باستخدام مجموعة من التعبيرات العادية في أوصاف الحوادث ، تم العثور على أجزاء مميزة: التواريخ ، وأسماء الخوادم ، ورموز المنتج ، وعناوين IP ، وعناوين الويب ، وأشكال الأسماء غير الصحيحة ، إلخ. تم استبدال هذه الشظايا مع الرموز مفهوم المقابلة.
في النهاية ، تم استخدام stamming لجلب الكلمات إلى شكل شائع. هذا سمح لنا بالتخلص من صيغ الجمع ونهايات الأفعال. تم استخدام snowballstemmer
المعروفة باسم آلة ثقب.
يتم دمج جميع عمليات المعالجة في فئة تحويل واحدة ، والتي يمكن استخدامها في عمليات مختلفة.
بالمناسبة ، اتضح (بشكل تجريبي ، بالطبع) أن طريقة stemmer.stemWord()
ليست آمنة في سلسلة العمليات. لذلك ، إذا حاولت تنفيذ معالجة نصية متوازية داخل خط الأنابيب ، على سبيل المثال ، باستخدام joblib
Prallel / مؤخر ، فيجب حماية الوصول إلى المثيل العام للنصيص مع الأقفال.
__replacements = [ ('(\d{1,3}\.){3}\d{1,3}', 'IPV4'), ('(?<=\W)((\d{2}[-\/ \.]?){2}(19|20)\d{2})|(19|20)\d{2}([-\/ \.]?\d{2}){2}(?=\W)', 'YYYYMMDD'), ('(?<=\W)(19|20)\d{2}(?=\W)', 'YYYY'), ('(?<=\W)(0|1)?\d\s?(am|pm)(?=\W)', 'HOUR'), ('http[s]?:\/\/(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', 'SOMEURL')
كمية موجهة
تتم عملية النقل بواسطة TfidfVectorizer
القياسي TfidfVectorizer
التالية:
max_features
= 10000ngram
= (1،3) - في محاولة للقبض على مجموعات مستقرة والروابط الدلاليةmax_df
/ min_df
- اليسار افتراضيًاstop_words
- قائمة قياسية من الكلمات الإنجليزية ، بالإضافة إلى مجموعة الكلمات الإضافية الخاصة بها. على سبيل المثال ، ذكر بعض المستخدمين أسماء المحللين ، وفي كثير من الأحيان أصبحت الأسماء الصحيحة سمات مهمة.
TfidfVectorizer
نفسه TfidfVectorizer
تطبيع L2 افتراضيًا ، لذلك تكون نواقل الحوادث جاهزة لقياس المسافة بين جيب التمام.
البحث عن حوادث مماثلة
المهمة الرئيسية للعملية هي إرجاع قائمة بأقرب جيران N. فئة sklearn.neighbors.NearestNeighbors
مناسبة تمامًا لهذا الغرض. مشكلة واحدة هي أنها لا تنفذ طريقة transform
، والتي بدونها لا يمكن استخدامها في pipeline
.
لذلك ، كان من الضروري جعله يعتمد على Transformer
، والذي وضعه فقط في الخطوة الأخيرة من pipeline
:
class NearestNeighborsTransformer(NearestNeighbors, TransformerMixin): def __init__(self, n_neighbors=5, radius=1.0, algorithm='auto', leaf_size=30, metric='minkowski', p=2, metric_params=None, n_jobs=None, **kwargs): super(NearestNeighbors, self).__init__(n_neighbors=n_neighbors, radius=radius, algorithm=algorithm, leaf_size=leaf_size, metric=metric, p=p, metric_params=metric_params, n_jobs=n_jobs) def transform(self, X, y=None): res = self.kneighbors(X, self.n_neighbors, return_distance=True) return res
عملية المعالجة
بوضع كل ذلك معا ، نحصل على عملية مدمجة:
p = Pipeline( steps=[ ('grp', ColumnTransformer( transformers=[ ('text', Pipeline(steps=[ ('pp', CommentsTextTransformer(n_jobs=-1)), ("tfidf", TfidfVectorizer(stop_words=get_stop_words(), ngram_range=(1, 3), max_features=10000)) ]), ['short_description', 'comments', 'u_impacted_department'] ) ] )), ("nn", NearestNeighborsTransformer(n_neighbors=10, metric='cosine')) ], memory=None)
بعد التدريب ، يمكن حفظ pipeline
في ملف باستخدام pickle
واستخدامه للتعامل مع الحوادث الواردة.
جنبًا إلى جنب مع النموذج ، سنقوم بحفظ حقول الحوادث الضرورية - من أجل استخدامها لاحقًا في الإخراج عند تشغيل النموذج.
نتائج التطبيق الأول
كان رد فعل الزملاء على إدخال نظام "تلميحات" إيجابيا للغاية بشكل عام. بدأت الحوادث المتكررة يتم حلها بشكل أسرع ، وبدأنا العمل على استكشاف الأخطاء وإصلاحها.
ومع ذلك ، لا يمكن للمرء أن يتوقع معجزة من نظام التعلم دون إشراف. اشتكى الزملاء من أن النظام يقدم أحيانًا روابط غير ذات صلة تمامًا. في بعض الأحيان كان من الصعب فهم من أين تأتي هذه التوصيات.
كان من الواضح أن مجال تحسين النموذج ضخم. يمكن حل بعض أوجه القصور ، بما في ذلك أو استبعاد بعض سمات الحادث. الجزء - عن طريق اختيار مستوى قطع مناسب للمسافة بين الحادث الحالي و "التوصية". ويمكن النظر في طرق مكافحة ناقلات أخرى.
لكن المشكلة الرئيسية كانت عدم وجود مقاييس جودة للتوصيات. وإذا كان الأمر كذلك ، فقد كان من المستحيل فهم "ما هو جيد وما هو سيء ، وكم هو" ، وبناء مقارنة بين النماذج في هذا الشأن.
لم نتمكن من الوصول إلى سجلات http ، لأن نظام الخدمة يعمل عن بعد (SaaS). لقد أجرينا استطلاعات رأي المستخدمين - ولكن نوعيًا فقط. كان من الضروري المضي في التقييمات الكمية ، والبناء على أساس مقاييس الجودة الواضحة.
ولكن المزيد عن ذلك في الجزء التالي ...