PowerMachine commited on
Commit
9429490
·
verified ·
1 Parent(s): 0f5a166

Delete cnn_bigru/losses/losses.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. cnn_bigru/losses/losses.py +0 -207
cnn_bigru/losses/losses.py DELETED
@@ -1,207 +0,0 @@
1
- """losses.py — Sistema de múltiplas perdas para o CNN-BiGRU cooperativo.
2
-
3
- Implementa as perdas descritas na seção 8 de dados.txt:
4
-
5
- L_G = CrossEntropy(logits_prova, prova_alvo)
6
- L_penal = λ * Σ (1 - v_t) (penalidade linear)
7
- L_exp_penal = μ * Σ exp(γ * (1 - v_t)) (penalidade exponencial)
8
- L_V = BCE(v_t, rotulo_real) (perda do verificador)
9
- L_AH = Σ (1 - τ_t) (perda anti-alucinação)
10
- L_reg = L2 + estimativa de curvatura (regularização)
11
- L_total = α * L_G_total + β * L_V + γ_loss * L_AH + δ * L_reg
12
-
13
- onde:
14
- L_G_total = L_G + λ_penal * L_penal + μ_exp * L_exp_penal
15
- """
16
- from __future__ import annotations
17
-
18
- import logging
19
- import math
20
- from dataclasses import dataclass, field
21
- from typing import Dict, List, Optional
22
-
23
- import torch
24
- import torch.nn as nn
25
- import torch.nn.functional as F
26
-
27
- logger = logging.getLogger(__name__)
28
-
29
-
30
- @dataclass
31
- class LossConfig:
32
- """Configuração das perdas e pesos."""
33
- # Pesos das perdas (ALPHA, BETA, GAMMA, DELTA do pseudocódigo)
34
- alpha: float = 1.0 # peso de L_G_total
35
- beta: float = 0.5 # peso de L_V
36
- gamma_loss: float = 0.3 # peso de L_AH
37
- delta: float = 0.01 # peso de L_reg
38
-
39
- # Penalidades
40
- lambda_penal: float = 0.1 # LAMBDA_PENAL
41
- mu_exp_penal: float = 0.05 # MU_EXP_PENAL
42
- gamma_exp: float = 1.0 # GAMMA_EXP
43
- threshold_err: float = 0.5 # THRESHOLD_ERR para penalidade exponencial
44
-
45
- # Regularização
46
- l2_reg: float = 1e-5
47
-
48
- # Curvatura
49
- use_curvature: bool = True
50
- curvature_eps: float = 1e-3
51
-
52
-
53
- class MultiLoss(nn.Module):
54
- """Computa todas as perdas do sistema cooperativo.
55
-
56
- Uso:
57
- loss_fn = MultiLoss(cfg)
58
- result = loss_fn(logits, targets, v_list, tau_list, generator, verifier)
59
- loss = result['total']
60
- loss.backward()
61
- """
62
-
63
- def __init__(self, config: LossConfig, pad_idx: int = 1):
64
- super().__init__()
65
- self.cfg = config
66
- self.pad_idx = pad_idx
67
- self.ce = nn.CrossEntropyLoss(ignore_index=pad_idx, reduction='mean')
68
- self.bce = nn.BCELoss(reduction='mean')
69
-
70
- def generation_loss(
71
- self,
72
- logits: torch.Tensor, # [B, T, V]
73
- targets: torch.Tensor, # [B, T]
74
- ) -> torch.Tensor:
75
- """L_G: CrossEntropy ignorando padding."""
76
- B, T, V = logits.shape
77
- return self.ce(logits.reshape(B * T, V), targets.reshape(B * T))
78
-
79
- def penalty_loss(
80
- self,
81
- v_list: List[torch.Tensor], # lista de [B, 1] probabilidades do verificador
82
- ) -> Dict[str, torch.Tensor]:
83
- """Calcula L_penal (linear) e L_exp_penal (exponencial)."""
84
- if not v_list:
85
- zero = torch.tensor(0.0)
86
- return {"linear": zero, "exp": zero}
87
-
88
- # Stack: [T, B, 1] -> [T, B]
89
- v_stack = torch.stack([v.squeeze(-1) if v.dim() == 2 else v for v in v_list], dim=0)
90
- # Penalidade linear: Σ (1 - v)
91
- l_penal = (1.0 - v_stack).sum() / max(v_stack.numel(), 1)
92
-
93
- # Penalidade exponencial: Σ exp(γ * (1 - v)) onde v < threshold
94
- mask = v_stack < self.cfg.threshold_err
95
- if mask.any():
96
- # exp(γ * (1 - v)) para os graves
97
- exp_vals = torch.exp(self.cfg.gamma_exp * (1.0 - v_stack[mask]))
98
- l_exp = exp_vals.sum() / max(v_stack.numel(), 1)
99
- else:
100
- l_exp = torch.tensor(0.0, device=v_stack.device)
101
-
102
- return {"linear": l_penal, "exp": l_exp}
103
-
104
- def verifier_loss(
105
- self,
106
- v_list: List[torch.Tensor],
107
- labels: List[torch.Tensor], # lista de [B, 1] com 0/1
108
- ) -> torch.Tensor:
109
- """L_V: BCE entre v_t e rotulo_real."""
110
- if not v_list:
111
- return torch.tensor(0.0)
112
- total = torch.tensor(0.0)
113
- for v, label in zip(v_list, labels):
114
- v_flat = (v.squeeze(-1) if v.dim() == 2 else v).clamp(1e-7, 1 - 1e-7)
115
- label_flat = label.squeeze(-1) if label.dim() == 2 else label
116
- total = total + self.bce(v_flat, label_flat.float())
117
- return total / max(len(v_list), 1)
118
-
119
- def anti_hallucination_loss(
120
- self,
121
- tau_list: List[torch.Tensor], # lista de [B, 1] valores de verdade suave
122
- ) -> torch.Tensor:
123
- """L_AH = Σ (1 - τ_t)."""
124
- if not tau_list:
125
- return torch.tensor(0.0)
126
- total = torch.tensor(0.0)
127
- for tau in tau_list:
128
- tau_flat = tau.squeeze(-1) if tau.dim() == 2 else tau
129
- total = total + (1.0 - tau_flat).mean()
130
- return total / max(len(tau_list), 1)
131
-
132
- def regularization_loss(
133
- self,
134
- models: List[nn.Module],
135
- ) -> torch.Tensor:
136
- """L_reg = L2 + estimativa de curvatura (aproximada via norma de pesos)."""
137
- l2 = torch.tensor(0.0)
138
- for model in models:
139
- for p in model.parameters():
140
- if p.requires_grad:
141
- l2 = l2 + p.pow(2).sum()
142
- l2 = self.cfg.l2_reg * l2
143
-
144
- # Estimativa de curvatura aproximada: variância das normas dos gradientes
145
- # (calculada externamente e passada via attr, aqui só placeholder)
146
- curv = getattr(self, '_curvature_estimate', torch.tensor(0.0))
147
- return l2 + (curv if isinstance(curv, torch.Tensor) else torch.tensor(float(curv)))
148
-
149
- def set_curvature_estimate(self, value: torch.Tensor) -> None:
150
- """Define a estimativa de curvatura (calculada externamente)."""
151
- self._curvature_estimate = value
152
-
153
- def forward(
154
- self,
155
- logits: torch.Tensor,
156
- targets: torch.Tensor,
157
- v_list: List[torch.Tensor],
158
- tau_list: List[torch.Tensor],
159
- verifier_labels: Optional[List[torch.Tensor]] = None,
160
- models_for_reg: Optional[List[nn.Module]] = None,
161
- ) -> Dict[str, torch.Tensor]:
162
- """Computa todas as perdas e combina."""
163
- # L_G
164
- l_g = self.generation_loss(logits, targets)
165
-
166
- # Penalidades
167
- pens = self.penalty_loss(v_list)
168
- l_g_total = l_g + self.cfg.lambda_penal * pens["linear"] + self.cfg.mu_exp_penal * pens["exp"]
169
-
170
- # L_V
171
- if verifier_labels is not None:
172
- l_v = self.verifier_loss(v_list, verifier_labels)
173
- else:
174
- # Sem rótulos reais: assume que v deveria ser 1 (passo correto)
175
- labels_ones = [torch.ones_like(v) for v in v_list]
176
- l_v = self.verifier_loss(v_list, labels_ones)
177
-
178
- # L_AH
179
- l_ah = self.anti_hallucination_loss(tau_list)
180
-
181
- # L_reg
182
- if models_for_reg:
183
- l_reg = self.regularization_loss(models_for_reg)
184
- else:
185
- l_reg = torch.tensor(0.0)
186
-
187
- # Combinação
188
- total = (
189
- self.cfg.alpha * l_g_total
190
- + self.cfg.beta * l_v
191
- + self.cfg.gamma_loss * l_ah
192
- + self.cfg.delta * l_reg
193
- )
194
-
195
- return {
196
- "total": total,
197
- "l_g": l_g,
198
- "l_g_total": l_g_total,
199
- "l_penal_linear": pens["linear"],
200
- "l_penal_exp": pens["exp"],
201
- "l_v": l_v,
202
- "l_ah": l_ah,
203
- "l_reg": l_reg,
204
- }
205
-
206
-
207
- __all__ = ["LossConfig", "MultiLoss"]