From d832595cc5e63ff435d2d81b6c94c17b0abcb550 Mon Sep 17 00:00:00 2001 From: Francisco Aranda Date: Sun, 20 Feb 2022 22:14:02 +0100 Subject: [PATCH] feat(#1144): weak supervision for multilabel datasets (#1166) (cherry picked from commit 18035318c967c9f5d81da95b858e18891c638917) feat(#1144): weak multi labels (#1190) (cherry picked from commit 1ba663f0e66636809139f4613481c57e54957660) feat(#1144): weak multi labels (#1190) (cherry picked from commit 1ba663f0e66636809139f4613481c57e54957660) fix: computation of correct/incorrect in weak multi label summary (#1237) (cherry picked from commit 2167296a42c810ec100b5f53f0f0d835282dd0be) feat(#1144): allow multilabel records in weak supervision (#1233) (cherry picked from commit 7deaf165a62a9dd2c2f8f3f16351ac0a8c200004) feat(#1144): allow all labels deselection in weak supervision (#1326) (cherry picked from commit 6e017d46289c7cd7d60da22ec581edcda916179b) --- docs/reference/python/python_labeling.rst | 9 +- .../commons/sidebar/SidebarMenu.vue | 6 +- frontend/components/core/ReTableInfo.vue | 29 +- .../labeling-rules/RuleDefinition.vue | 13 +- .../labeling-rules/RuleLabelsDefinition.vue | 50 +- .../labeling-rules/RulesManagement.vue | 6 +- .../labeling-rules/RulesMetrics.vue | 32 - frontend/models/TextClassification.js | 50 +- .../client/sdk/text_classification/models.py | 3 +- .../labeling/text_classification/__init__.py | 2 +- .../labeling/text_classification/rule.py | 22 +- .../text_classification/weak_labels.py | 627 ++++++++++-- src/rubrix/server/commons/es_wrapper.py | 6 +- src/rubrix/server/commons/helpers.py | 2 +- .../tasks/text_classification/api/api.py | 8 +- .../tasks/text_classification/api/model.py | 21 +- .../service/labeling_service.py | 109 +- .../text_classification/service/service.py | 26 +- .../text_classification/test_label_models.py | 2 +- .../text_classification/test_weak_labels.py | 933 ++++++++++++------ .../text_classification/test_api_rules.py | 286 ++++-- 21 files changed, 1556 insertions(+), 686 deletions(-) diff --git a/docs/reference/python/python_labeling.rst b/docs/reference/python/python_labeling.rst index 35d684d9d4..59180b21a8 100644 --- a/docs/reference/python/python_labeling.rst +++ b/docs/reference/python/python_labeling.rst @@ -17,13 +17,10 @@ Labeling tools for the text classification task. :exclude-members: RuleNotAppliedError .. automodule:: rubrix.labeling.text_classification.weak_labels - :members: - :exclude-members: WeakLabelsError, DuplicatedRuleNameError, NoRecordsFoundError, MultiLabelError, MissingLabelError + :members: WeakLabels, WeakMultiLabels .. automodule:: rubrix.labeling.text_classification.label_models - :members: - :exclude-members: TieBreakPolicy, LabelModelError, MissingAnnotationError, TooFewRulesError, NotFittedError + :members: Snorkel, FlyingSquid .. automodule:: rubrix.labeling.text_classification.label_errors - :members: - :exclude-members: SortBy, LabelErrorsException, NoRecordsError, MissingPredictionError + :members: find_label_errors diff --git a/frontend/components/commons/sidebar/SidebarMenu.vue b/frontend/components/commons/sidebar/SidebarMenu.vue index f76410002b..bbb85da56d 100644 --- a/frontend/components/commons/sidebar/SidebarMenu.vue +++ b/frontend/components/commons/sidebar/SidebarMenu.vue @@ -128,11 +128,7 @@ export default { return this.dataset !== undefined; }, showLabellingRules() { - return ( - this.isDatasetView && - !this.dataset.isMultiLabel && - this.dataset.task === "TextClassification" - ); + return this.isDatasetView && this.dataset.task === "TextClassification"; }, }, watch: { diff --git a/frontend/components/core/ReTableInfo.vue b/frontend/components/core/ReTableInfo.vue index b9cb1091e7..fa14679455 100644 --- a/frontend/components/core/ReTableInfo.vue +++ b/frontend/components/core/ReTableInfo.vue @@ -110,6 +110,11 @@ > {{ itemValue(item, column) | percent }} + +

+ {{arrayItem}}{{index + 1 === itemValue(item, column).length ? '' : ','}} +

+

1 ? "these labels" : "this label" + } is already saved as rule`; } }, coveredRecords() { @@ -190,16 +197,21 @@ export default { }, }, watch: { - selectedLabel(newValue) { - // Here send description too --> update Rule - this.$emit("update-rule", { - query: this.query, - label: newValue, - }); + selectedLabels: { + handler: function (newValue) { + if (!_.isEqual(_.sortBy(newValue), _.sortBy(this.currentRule.labels))) { + // Here send description too --> update Rule + this.$emit("update-rule", { + query: this.query, + labels: newValue, + }); + } + }, + deep: true, }, currentRule(newValue) { - if (newValue && newValue.label) { - this.selectedLabelsVModel = [newValue.label]; + if (newValue && newValue.labels) { + this.selectedLabelsVModel = [...newValue.labels]; } }, }, @@ -211,7 +223,7 @@ export default { this.collapseLabels(); this.$emit("save-rule", { query: this.currentRule.query, - label: this.selectedLabel, + labels: this.selectedLabels, }); }, expandLabels() { diff --git a/frontend/components/text-classifier/labeling-rules/RulesManagement.vue b/frontend/components/text-classifier/labeling-rules/RulesManagement.vue index 9461fc58af..513ebb2707 100644 --- a/frontend/components/text-classifier/labeling-rules/RulesManagement.vue +++ b/frontend/components/text-classifier/labeling-rules/RulesManagement.vue @@ -79,7 +79,7 @@ export default { class: "table-info__title", type: "action", }, - { name: "Label", field: "label", class: "text" }, + { name: "Labels", field: "labels", class: "array", type: "array" }, { name: "Coverage", field: "coverage", @@ -158,7 +158,7 @@ export default { name: r.description, query: r.query, kind: "select", - label: r.label, + labels: r.labels, ...this.metricsForRule(r), created_at: r.created_at, }; @@ -244,7 +244,7 @@ export default {