ProCreations commited on
Commit
3f30f83
·
verified ·
1 Parent(s): 33e524a

Add hard-negative token ranking objective

Browse files
Files changed (1) hide show
  1. modeling_betterwright.py +34 -1
modeling_betterwright.py CHANGED
@@ -21,6 +21,8 @@ class BetterWrightEncoderOutput(ModelOutput):
21
  logits: Optional[torch.Tensor] = None
22
  token_logits: Optional[torch.Tensor] = None
23
  uncertainty_logits: Optional[torch.Tensor] = None
 
 
24
  last_hidden_state: Optional[torch.Tensor] = None
25
 
26
 
@@ -84,6 +86,8 @@ class BetterWrightEncoder(Lfm2PreTrainedModel):
84
  logits = self.relevance_head(pooled).squeeze(-1)
85
  uncertainty_logits = self.uncertainty_head(pooled).squeeze(-1)
86
  loss = None
 
 
87
  if labels is not None:
88
  labels = labels.to(logits.dtype)
89
  positive_weight = float(getattr(self.config, "betterwright_positive_weight", 3.0))
@@ -122,12 +126,41 @@ class BetterWrightEncoder(Lfm2PreTrainedModel):
122
  dtype=token_logits.dtype,
123
  ),
124
  )
125
- loss = token_loss if loss is None else loss + 0.35 * token_loss
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126
  result = BetterWrightEncoderOutput(
127
  loss=loss,
128
  logits=logits,
129
  token_logits=token_logits,
130
  uncertainty_logits=uncertainty_logits,
 
 
131
  last_hidden_state=hidden,
132
  )
133
  return result if return_dict else tuple(result.values())
 
21
  logits: Optional[torch.Tensor] = None
22
  token_logits: Optional[torch.Tensor] = None
23
  uncertainty_logits: Optional[torch.Tensor] = None
24
+ token_loss: Optional[torch.Tensor] = None
25
+ token_rank_loss: Optional[torch.Tensor] = None
26
  last_hidden_state: Optional[torch.Tensor] = None
27
 
28
 
 
86
  logits = self.relevance_head(pooled).squeeze(-1)
87
  uncertainty_logits = self.uncertainty_head(pooled).squeeze(-1)
88
  loss = None
89
+ token_loss = None
90
+ token_rank_loss = None
91
  if labels is not None:
92
  labels = labels.to(logits.dtype)
93
  positive_weight = float(getattr(self.config, "betterwright_positive_weight", 3.0))
 
126
  dtype=token_logits.dtype,
127
  ),
128
  )
129
+ # Runtime pruning ranks lines by their highest-scoring token.
130
+ # BCE alone can achieve a reasonable average while leaving a
131
+ # few distractor tokens above the evidence. Explicitly compare
132
+ # each positive row against its hardest negative tokens so the
133
+ # training objective matches that production ranking behavior.
134
+ token_rank_losses = []
135
+ for row_index in range(token_logits.shape[0]):
136
+ row_valid = valid[row_index]
137
+ row_labels = token_labels[row_index]
138
+ positives = token_logits[row_index][row_valid & (row_labels == 1)]
139
+ negatives = token_logits[row_index][row_valid & (row_labels == 0)]
140
+ if positives.numel() == 0 or negatives.numel() == 0:
141
+ continue
142
+ hard_count = min(64, negatives.numel())
143
+ hard_negatives = torch.topk(
144
+ negatives.float(), hard_count, sorted=False
145
+ ).values
146
+ token_rank_losses.append(
147
+ F.softplus(
148
+ 1.0 + hard_negatives.mean() - positives.float().mean()
149
+ )
150
+ )
151
+ if token_rank_losses:
152
+ token_rank_loss = torch.stack(token_rank_losses).mean()
153
+ else:
154
+ token_rank_loss = token_loss.new_zeros(())
155
+ token_objective = 0.75 * token_loss + token_rank_loss
156
+ loss = token_objective if loss is None else loss + token_objective
157
  result = BetterWrightEncoderOutput(
158
  loss=loss,
159
  logits=logits,
160
  token_logits=token_logits,
161
  uncertainty_logits=uncertainty_logits,
162
+ token_loss=token_loss,
163
+ token_rank_loss=token_rank_loss,
164
  last_hidden_state=hidden,
165
  )
166
  return result if return_dict else tuple(result.values())