Suchen Sie nach ähnlichen Vorfällen und Ansprüchen. Metriken und Optimierung

In einem früheren Artikel habe ich über unsere Suchmaschine für ähnliche Anwendungen gesprochen . Nach dem Start erhielten wir die ersten Bewertungen. Analysten mochten und empfahlen einige Empfehlungen, andere nicht.


Um weiterzumachen und bessere Modelle zu finden, musste zunächst die Leistung des aktuellen Modells bewertet werden. Es war auch notwendig, Kriterien auszuwählen, anhand derer die beiden Modelle miteinander verglichen werden konnten.


Unter dem Schnitt werde ich sprechen über:


  • Feedback zu Empfehlungen sammeln
  • Entwicklung von Metriken zur Bewertung der Qualität von Empfehlungen
  • Erstellen eines Modelloptimierungszyklus
  • erhielt Einblicke und ein neues Modell

Feedback-Sammlung


Es wäre ideal, explizites Feedback von Analysten einzuholen: Wie relevant ist die Empfehlung für jeden der vorgeschlagenen Vorfälle? Auf diese Weise können wir die aktuelle Situation verstehen und das System auf der Grundlage quantitativer Indikatoren weiter verbessern.


Es wurde beschlossen, Bewertungen in einem äußerst einfachen Format zu sammeln:


  • Anzahl der Vorfälle, die wir analysieren
  • empfohlene Vorfallsnummer
  • Empfehlungsbewertung: gut / schlecht

Die "Abstimmung" (ein kleines Projekt, das GET-Anfragen mit Parametern akzeptierte und die Informationen in eine Datei legte) wurde direkt in den Empfehlungsblock eingefügt, sodass Analysten ihr Feedback sofort hinterlassen können, indem sie einfach auf einen der Links klicken: "gut" oder "schlecht".


Zusätzlich wurde für eine nachträgliche Überprüfung der Empfehlung eine sehr einfache Lösung gefunden:


  • Für einen großen Teil der historischen Daten wurde ein Modell gestartet.
  • Die gesammelten Empfehlungen wurden in Form mehrerer eigenständiger HTML-Dateien präsentiert, in denen dieselbe "Abstimmung" verwendet wurde.
  • Die vorbereiteten Dateien wurden den Analysten ausgehändigt, um die Ergebnisse für 50 bis 100 Vorfälle anzuzeigen.

So war es möglich, Daten zu über 4000 Paaren von Vorfallempfehlungen zu sammeln.


Erste Überprüfungsanalyse


Die anfänglichen Kennzahlen waren „so lala“ - der Anteil der „guten“ Empfehlungen betrug laut Kollegen nur etwa 25%.


Die Hauptprobleme des ersten Modells:


  1. Vorfälle mit „neuen“ Problemen erhielten irrelevante Empfehlungen vom System. Es stellte sich heraus, dass das System mangels Übereinstimmungen im Inhalt der Beschwerde Vorfälle in der Nähe der Abteilung des kontaktierenden Mitarbeiters auswählte.
  2. Empfehlungen für einen Vorfall auf einem System treffen Vorfälle auf anderen Systemen. Die in der Berufung verwendeten Wörter waren ähnlich, beschrieben jedoch die Probleme anderer Systeme und waren unterschiedlich.

Mögliche Möglichkeiten zur Verbesserung der Qualität der Empfehlungen wurden ausgewählt:


  • Anpassung der Zusammensetzung und des Gewichts der Behandlungsattribute, die im endgültigen Vektor enthalten sind
  • Auswahl der Vektorisierungseinstellungen TfidfVectorizer
  • Auswahl des "Grenzabstands" der Empfehlungen

Entwicklung von Qualitätskriterien und Bewertungsmethoden


Um nach einer verbesserten Version des Modells zu suchen, muss das Prinzip der Bewertung der Qualität der Modellergebnisse festgelegt werden. Auf diese Weise können Sie zwei Modelle quantitativ vergleichen und das beste auswählen.


Was kann aus den gesammelten Bewertungen erhalten werden


Wir haben viele Tupel der Form: "Vorfall", "Empfohlener Vorfall", "Bewertung der Empfehlung".


  • "Empfehlungsbewertung" ( v ) - wird binär gesetzt: "Gut" | Schlecht (1 / -1);
  • "Incident" und "Recommended Incident" sind einfach Incident-Nummern. Auf ihnen finden Sie den Vorfall in der Datenbank.

Mit solchen Daten können Sie berechnen:


  • n_inc_total - Die Gesamtzahl der Vorfälle, für die Empfehlungen n_inc_total
  • n_inc_good - Die Anzahl der Vorfälle, für die es „gute“ Empfehlungen gibt
  • avg_inc_good - Die durchschnittliche Anzahl „guter“ Empfehlungen für Vorfälle
  • n_rec_total - Gesamtzahl der Empfehlungen
  • n_rec_good - Die Gesamtzahl der "guten" Empfehlungen
  • pct_inc_good - Anteil der Vorfälle, für die es „gute“ Empfehlungen gibt
    pct_inc_good = n_inc_good / n_inc_total
  • pct_rec_good - Gesamtanteil der "guten" Empfehlungen
    pct_rec_good = n_rec_good / n_rec_total

Diese Indikatoren, die auf der Grundlage von Schätzungen der Benutzer berechnet werden, können als „Basisindikatoren“ des ursprünglichen Modells betrachtet werden. Damit werden wir ähnliche Indikatoren für neue Versionen des Modells vergleichen.


Nehmen Sie alle einzigartigen "Vorfälle" von m und fahren Sie sie durch das neue Modell.


Als Ergebnis erhalten wir viele m * Tupel: "Incident", "Recommended Incident", "Distance".
Hier ist "Entfernung" die in NearestNeighbor definierte Metrik. In unserem Modell ist dies der Kosinusabstand. Der Wert "0" entspricht der vollständigen Übereinstimmung von Vektoren.


Auswahl des "Grenzabstands"


Wenn wir den Satz von Empfehlungen m * mit Informationen über die wahre Schätzung von v aus dem anfänglichen Satz von Schätzungen von m ergänzen, erhalten wir die Entsprechung zwischen dem Abstand d und der wahren Schätzung von v für dieses Modell.


Mit der Menge ( d , v ) ist es möglich, den optimalen Grenzwert t zu wählen, der für d <= t die Empfehlung "gut" und für d> t - "schlecht" ist. Die Auswahl von t kann erreicht werden, indem der einfachste binäre Klassifikator v = -1 if d>t else 1 optimiert wird, v = -1 if d>t else 1 Bezug auf den Hyperparameter t ist, und beispielsweise AUC ROC als Metrik verwendet wird.


 #     class BinarizerClassifier(Binarizer): def transform(self, x): return np.array([-1 if _x > self.threshold else 1 for _x in np.array(x, dtype=float)]).reshape(-1, 1) def predict_proba(self, x): z = self.transform(x) return np.array([[0 if _x > 0 else 1, 1 if _x > 0 else 0] for _x in z.ravel()]) def predict(self, x): return self.transform(x) # #   : # -  , # -    m* # -   (d,v)  z_data_for_t # #   t b = BinarizerClassifier() z_x = z_data_for_t[['distance']] z_y = z_data_for_t['TYPE'] cv = GridSearchCV(b, param_grid={'threshold': np.arange(0.1, 0.7, 0.01)}, scoring='roc_auc', cv=5, iid=False, n_jobs=-1) cv.fit(z_x, z_y) score = cv.best_score_ t = cv.best_params_['threshold'] best_b = cv.best_estimator_ 

Der erhaltene t- Wert kann zum Filtern von Empfehlungen verwendet werden.


Natürlich kann dieser Ansatz immer noch die "schlechten" Empfehlungen überspringen und die "guten" abschneiden. Daher zeigen wir zu diesem Zeitpunkt immer die "Top 5" -Empfehlungen an, markieren jedoch speziell diejenigen, die als "gut" gelten, unter Berücksichtigung des gefundenen t .
Alternative: Wenn mindestens eine „gute“ Empfehlung gefunden wird, wird nur „gut“ angezeigt. Andernfalls zeigen Sie alle verfügbaren an (auch - "Top N").


Annahme zum Modellvergleich


Für Trainingsmodelle wird der gleiche Vorfallfall verwendet.
Angenommen, wenn zuvor eine „gute“ Empfehlung gefunden wurde, sollte das neue Modell auch eine „gute“ Empfehlung für denselben Vorfall finden. Insbesondere kann das neue Modell die gleichen „guten“ Empfehlungen finden wie das alte. Mit dem neuen Modell erwarten wir jedoch, dass die Anzahl der "schlechten" Empfehlungen geringer wird.


Unter Berücksichtigung der gleichen Indikatoren für die Empfehlungen m * des neuen Modells können sie dann mit den entsprechenden Indikatoren für m verglichen werden. Basierend auf dem Vergleich können Sie das beste Modell auswählen.


Es gibt zwei Möglichkeiten, die „guten“ Empfehlungen für die Menge m * zu berücksichtigen:


  1. basierend auf dem gefundenen t : Betrachten Sie, dass alle Empfehlungen von m * mit d < t „gut“ sind, und berücksichtigen Sie sie bei der Berechnung der Metriken
  2. Wählen Sie auf der Grundlage der entsprechenden wahren Schätzungen aus der Menge m : Wählen Sie aus den Empfehlungen m * nur diejenigen aus, für die es eine wahre Schätzung in m gibt , und verwerfen Sie den Rest.

Im ersten Fall sollten die "absoluten" Indikatoren ( n_inc_good , n_rec_good ) des neuen Modells größer sein als für das Basismodell. Im zweiten Fall sollten sich die Indikatoren den Indikatoren des Basismodells nähern.
Das Problem der zweiten Methode: Wenn das neue Modell besser als das ursprüngliche ist und etwas bisher Unbekanntes findet, wird eine solche Empfehlung bei der Berechnung nicht berücksichtigt.


Wählen Sie Modellvergleichsoptionen


Bei der Auswahl eines neuen Modells möchte ich, dass sich die Indikatoren im Vergleich zum vorhandenen Modell verbessern:


  • durchschnittliche Anzahl „guter“ Empfehlungen pro Vorfall ( avg_inc_good )
  • Anzahl der Vorfälle, für die es „gute“ Empfehlungen gibt ( n_inc_good ).

Zum Vergleich mit dem ursprünglichen Modell werden wir die Beziehungen dieser Parameter des neuen Modells und des Originals verwenden. Wenn also das Verhältnis des Parameters des neuen Modells zum alten mehr als 1 beträgt, ist das neue Modell besser.


 benchmark_agv_inc_good = avg_inc_good* / avg_inc_good benchmark_n_inc_good = n_inc_good* / n_inc_good 

Um die Auswahl zu vereinfachen, ist es besser, einen einzelnen Parameter zu verwenden. Wir nehmen das harmonische Mittel einzelner relativer Indikatoren und verwenden es als einziges zusammengesetztes Qualitätskriterium für das neue Modell.


 composite = 2 / ( 1/benchmark_agv_inc_good + 1/benchmark_n_inc_good) 

Neues Modell und seine Optimierung


Fügen Sie für das neue Modell im endgültigen Vektor, der den Vorfall darstellt, die Komponenten hinzu, die für den "Vorfallbereich" verantwortlich sind (eines von mehreren Systemen, die von unserem Team gewartet werden).
Informationen über die Einheit und den Standort des Mitarbeiters, der den Vorfall erstellt hat, werden ebenfalls in einer separaten Vektorkomponente abgelegt. Alle Komponenten haben ihr Gewicht im endgültigen Vektor.


 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, min_df=0)) ]), ['short_description', 'comments'] ), ('area', OneHotEncoder(handle_unknown='ignore'), ['area'] ), ('dept', OneHotEncoder(handle_unknown='ignore'), ['u_impacted_department'] ), ('loc', OneHotEncoder(handle_unknown='ignore'), ['u_impacted_location'] ) ], transformer_weights={'text': 1, 'area': 0.5, 'dept': 0.1, 'loc': 0.1}, n_jobs=-1 )), ('norm', Normalizer()), ("nn", NearestNeighborsTransformer(n_neighbors=10, metric='cosine')) ], memory=None) 

Es wird erwartet, dass Modellhyperparameter Modellziele beeinflussen. In der ausgewählten Modellarchitektur werden wir als Hyperparameter betrachten:


  • TF-IDF-Vektorisierungsparameter - verwendete n-Gramm (ngram_range), Wörterbuchgröße (max_features), Mindestlaufzeit (min_df)
  • Komponentenbeitrag zum endgültigen Vektor - Transformatorgewichte.

Die Anfangswerte der Textvektorisierungs-Hyperparameter stammen aus dem vorherigen Modell. Die anfänglichen Komponentengewichte werden basierend auf Expertenurteilen ausgewählt.


Parameterauswahlzyklus


Wie man vergleicht, die Fehlzündungsstufe auswählt und Modelle untereinander vergleicht, wurde bereits ermittelt. Jetzt können wir mit der Optimierung durch Auswahl der Hyperparameter fortfahren.


Optimierungszyklus


 param_grid = { 'grp__text__tfidf__ngram_range': [(1, 1), (1, 2), (1, 3), (2, 2)], 'grp__text__tfidf__max_features': [5000, 10000, 20000], 'grp__text__tfidf__min_df': [0, 0.0001, 0.0005, 0.001], 'grp__transformer_weights': [{'text': 1, 'area': 0.5, 'dept': 0.1, 'loc': 0.1}, {'text': 1, 'area': 0.75, 'dept': 0.1, 'loc': 0.1}, {'text': 1, 'area': 0.5, 'dept': 0.3, 'loc': 0.3}, {'text': 1, 'area': 0.75, 'dept': 0.3, 'loc': 0.3}, {'text': 1, 'area': 1, 'dept': 0.1, 'loc': 0.1}, {'text': 1, 'area': 1, 'dept': 0.3, 'loc': 0.3}, {'text': 1, 'area': 1, 'dept': 0.5, 'loc': 0.5}], } for param in ParameterGrid(param_grid=param_grid): p.set_params(**param) p.fit(x) ... 

Optimierungsergebnisse


Die Tabelle zeigt die Ergebnisse von Experimenten, bei denen interessante Ergebnisse erzielt wurden - Top 5 der besten und schlechtesten Werte für kontrollierte Indikatoren.



Die Zellen mit Indikatoren in der Tabelle sind gekennzeichnet als:


  • Dunkelgrün ist der beste Indikator unter allen Experimenten
  • hellgrün - Indikatorwert ist in den Top-5
  • dunkelrot - der schlechteste Indikator unter allen Experimenten
  • blassrot - der Indikator ist in der schlechtesten 5

Der beste zusammengesetzte Indikator wurde für ein Modell mit Parametern erhalten:


 ngram_range = (1,2) min_df = 0.0001 max_features = 20000 transformer_weights = {'text': 1, 'area': 1, 'dept': 0.1, 'loc': 0.1} 

Ein Modell mit diesen Parametern zeigte eine Verbesserung des zusammengesetzten Indikators im Vergleich zum ursprünglichen Modell um 24%.


Einige Beobachtungen und Schlussfolgerungen


Nach den Optimierungsergebnissen:


  1. Die Verwendung von Trigrammen ( ngram_range = (1,3) ) scheint nicht gerechtfertigt zu sein. Sie blasen das Wörterbuch auf und erhöhen die Genauigkeit im Vergleich zu Bigrams geringfügig.


  2. Ein interessantes Verhalten beim ngram_range = (2,2) eines Wörterbuchs mit nur ngram_range = (2,2) ( ngram_range = (2,2) ): Die "Genauigkeit" von Empfehlungen nimmt zu und die Anzahl der gefundenen Empfehlungen nimmt ab. Genau wie eine Präzisions- / Rückrufbalance in Klassifikatoren. Ein ähnliches Verhalten wird bei der Auswahl des Grenzwerts t beobachtet - für die Bigramme sind ein engerer Grenzkegel und eine bessere Trennung von „guten“ und „schlechten“ Empfehlungen charakteristisch.


  3. Der Parameter min_df ungleich Null erhöht zusammen mit Bigrams die Genauigkeit der Empfehlungen. Sie basieren auf Begriffen, die mindestens mehrmals vorkommen. Wenn der Parameter zunimmt, beginnt das Wörterbuch schnell zu schrumpfen. Bei kleinen Stichproben wie in unserem Fall ist es wahrscheinlich verständlicher, mit der Anzahl der Dokumente (ganzzahliger Wert min_df) zu arbeiten als mit dem Bruchteil der Dokumente (Bruchwert min_df), der den Begriff enthält.


  4. Gute Ergebnisse werden erzielt, wenn das für die "Region" verantwortliche Ereignisattribut im endgültigen Vektor mit einer Gewichtung enthalten ist, die der Textkomponente entspricht oder dieser nahe kommt. Niedrige Werte führen zu einem Anstieg des Anteils "schlechter" Empfehlungen, da ähnliche Wörter in Dokumenten aus anderen Bereichen gefunden werden. Die Anzeichen für den Standort des Kunden wirken sich in unserem Fall jedoch nicht so gut auf die Ergebnisse der Empfehlungen aus.



Einige neue Ideen sind aufgetaucht:


  • Fügen Sie eine Zeitkomponente hinzu, damit kürzlich aufgetretene Vorfälle Vorrang vor ähnlichen Vorfällen haben.
  • Sehen Sie, wie sich die Einführung des Parameters max_df auswirkt - obwohl bei tf-idf zu allgemeine Wörter für den Korpus per Definition kein signifikantes Gewicht haben sollten.
  • Versuchen Sie schließlich andere Möglichkeiten zur Vektorisierung von Inhalten, z. B. basierend auf Wort-zu-Vektor oder basierend auf der Faltung von tf-idf-Ansichten mithilfe von Netzwerken.

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


All Articles