docs: def train(self, content_objs, idx_labels):
          '''Trains and returns a model using sklearn.
  
          If there are new labels to add, they can be added, returns an
          sklearn model which can be used for prediction and getting
          features.
  
          This method may return ``None`` if there is insufficient
          training data to produce a model.
  
          :param labels: Ground truth data.
          :type labels: list of ``({-1, 1}, index1, index2)``.
          '''
          # We have insufficient training data when there is only one or
          # fewer classes of labels.
          if len(set([lab[0] for lab in idx_labels])) <= 1:
              return None
  
          fcs = [fc for _, fc in content_objs]
          feature_names = vectorizable_features(fcs)
          dis = dissimilarities(feature_names, fcs)
  
          phi_dicts, labels = [], []  # lists are in correspondence
          for coref_value, i, j in idx_labels:
              # i, j are indices into the list `fcs`
              labels.append(coref_value)  # either -1 or 1
              phi_dict = dict([(name, dis[name][i,j]) for name in feature_names])
              phi_dicts.append(phi_dict)
  
          vec = dict_vector()
          training_data = vec.fit_transform(phi_dicts)
  
          model = LogisticRegression(class_weight='auto', penalty='l1')
          model.fit(training_data, labels)
          self.feature_weights = dict([(name, model.coef_[0][i])
                                       for i, name in enumerate(feature_names)])
          return feature_names, model, vec