Repository: mozilla/bugbug

Issue:
Add options to the Duplicate classifier to select number of bugs in the training set



Discussion:
https://github.com/mozilla/bugbug/blob/5b367e2107c0382b861133643d9aca6c6d1e0f24/bugbug/models/duplicate.py#L17-L19
@marco-c  we can do this by changing the values of these three parameters, is there something else to it?
@chidauri right now it's configurable only by changing those numbers in the source code. We need to somehow make it configurable more easily so you can run the model with different options without having to modify the source.

Resolving patch:
diff --git a/bugbug/models/duplicate.py b/bugbug/models/duplicate.py
--- a/bugbug/models/duplicate.py
+++ b/bugbug/models/duplicate.py
@@ -14,10 +14,6 @@
 from bugbug import bug_features, bugzilla, feature_cleanup
 from bugbug.model import BugCoupleModel
 
-NUM_DUPLICATES = 7000
-NUM_DUP_NONDUPS = 3500
-NUM_NONDUPS_NONDUPS = 3500
-
 REPORTERS_TO_IGNORE = {"intermittent-bug-filer@mozilla.bugs", "wptsync@mozilla.bugs"}
 
 
@@ -32,7 +28,10 @@ def fit(self, X, y):
 
 
 class DuplicateModel(BugCoupleModel):
-    def __init__(self, lemmatization=False):
+    def __init__(self, training_size=14000, lemmatization=False):
+        self.num_duplicates = training_size // 2
+        self.num_nondups_nondups = self.num_dup_nondups = training_size // 4
+
         BugCoupleModel.__init__(self, lemmatization)
 
         self.calculate_importance = False
@@ -90,7 +89,7 @@ def get_labels(self):
 
                 duplicate_ids.append(duplicate_bug_id)
 
-                if duplicates_num < NUM_DUPLICATES:
+                if duplicates_num < self.num_duplicates:
                     classes[(bug_id, duplicate_bug_id)] = 1
                 duplicates_num += 1
 
@@ -100,29 +99,29 @@ def get_labels(self):
         # Store all remaining ids
         non_duplicate_ids = list(all_ids - set(duplicate_ids))
 
-        print(f"Number of duplicate labels is: {NUM_DUPLICATES}")
+        print(f"Number of duplicate labels is: {self.num_duplicates}")
 
         # When the bug has no duplicates, we create dup-nondup labels.
         dup_nondup_num = 0
-        while dup_nondup_num < NUM_DUP_NONDUPS:
+        while dup_nondup_num < self.num_dup_nondups:
             bug_id1 = random.choice(duplicate_ids)
             bug_id2 = random.choice(non_duplicate_ids)
 
             classes[(bug_id1, bug_id2)] = 0
             dup_nondup_num += 1
 
-        print(f"Number of hybrid labels is: {NUM_DUP_NONDUPS}")
+        print(f"Number of hybrid labels is: {self.num_dup_nondups}")
 
         # Now we map non-dup to non-dup bug.
         nondup_nondup_num = 0
-        while nondup_nondup_num < NUM_DUP_NONDUPS:
+        while nondup_nondup_num < self.num_nondups_nondups:
             bug_id1 = random.choice(non_duplicate_ids)
             bug_id2 = random.choice(non_duplicate_ids)
             if bug_id1 != bug_id2:
                 classes[(bug_id1, bug_id2)] = 0
                 nondup_nondup_num += 1
 
-        print(f"Number of purely non-duplicate labels is: {NUM_NONDUPS_NONDUPS}")
+        print(f"Number of purely non-duplicate labels is: {self.num_nondups_nondups}")
 
         return classes, [0, 1]
 
diff --git a/run.py b/run.py
--- a/run.py
+++ b/run.py
@@ -22,6 +22,13 @@ def parse_args(args):
         help="Perform lemmatization (using spaCy)",
         action="store_true",
     )
+    parser.add_argument(
+        "--training-set-size",
+        nargs="?",
+        default=14000,
+        type=int,
+        help="The size of the training set for the duplicate model",
+    )
     parser.add_argument("--train", help="Perform training", action="store_true")
     parser.add_argument(
         "--goal", help="Goal of the classifier", choices=MODELS.keys(), default="defect"
@@ -76,6 +83,8 @@ def main(args):
 
         if args.goal in historical_supported_tasks:
             model = model_class(args.lemmatization, args.historical)
+        elif args.goal == "duplicate":
+            model = model_class(args.training_set_size, args.lemmatization)
         else:
             model = model_class(args.lemmatization)
         model.train()


Test patch: