class_docstr: Manages post-hoc SVM training for a single object class.
class_docstr_tok: ["Manages","post-hoc","SVM","training","for","a","single","object","class","."]
code: def train(self):
      print(">>> Updating {} detector <<<".format(self.cls))
      num_pos = self.pos.shape[0]
      num_neg = self.neg.shape[0]
      print(
          "Cache holds {} pos examples and {} neg examples".format(
              num_pos, num_neg
          )
      )
      X = np.vstack((self.pos, self.neg)) * self.feature_scale
      y = np.hstack((np.ones(num_pos), -np.ones(num_neg)))
      self.svm.fit(X, y)
      w = self.svm.coef_
      b = self.svm.intercept_[0]
  
      scores = self.svm.decision_function(X)
      pos_scores = scores[:num_pos]
      neg_scores = scores[num_pos:]
  
      num_neg_wrong = sum(neg_scores > 0)
      num_pos_wrong = sum(pos_scores < 0)
      meanAcc = (
          0.5 * (num_pos - num_pos_wrong) / num_pos
          + 0.5 * (num_neg - num_neg_wrong) / num_neg
      )
      if type(self.pos_weight) == str:
          pos_loss = 0
      else:
          pos_loss = (
              self.C
              * self.pos_weight
              * np.maximum(0, 1 - pos_scores).sum()
          )
      neg_loss = self.C * np.maximum(0, 1 + neg_scores).sum()
      reg_loss = 0.5 * np.dot(w.ravel(), w.ravel()) + 0.5 * b**2
      tot_loss = pos_loss + neg_loss + reg_loss
      self.loss_history.append(
          (
              meanAcc,
              num_pos_wrong,
              num_pos,
              num_neg_wrong,
              num_neg,
              tot_loss,
              pos_loss,
              neg_loss,
              reg_loss,
          )
      )
      for i, losses in enumerate(self.loss_history):
          print(
              (
                  "    {:4d}: meanAcc={:.3f} -- pos wrong: {:5}/{:5}; neg wrong: {:5}/{:5};  "
                  "     obj val: {:.3f} = {:.3f}  (posUnscaled) + {:.3f} (neg) + {:.3f} (reg)"
              ).format(i, *losses)
          )
  
      # Sanity check
  
      scores_ret = (X * 1.0 / self.feature_scale).dot(
          w.T * self.feature_scale
      ) + b
      assert np.allclose(
          scores, scores_ret[:, 0], atol=1e-5
      ), "Scores from returned model don't match decision function"
  
      return ((w * self.feature_scale, b), pos_scores, neg_scores)
  
imports: from timer import Timer
  from sklearn import svm
  import numpy
label_desc: Use image node_id 4 for calling the SVMClassTrainer obj's underlying member method code with example usage: obj.train() and returns: unknown,  b,  pos_scores,  neg_scores