PowerMachine commited on
Commit
d2dc7dd
·
verified ·
1 Parent(s): 4728297

Delete cnn_bigru/models/multimodal_model.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. cnn_bigru/models/multimodal_model.py +0 -183
cnn_bigru/models/multimodal_model.py DELETED
@@ -1,183 +0,0 @@
1
- """multimodal_model.py — Modelo multimodal CNN-BiGRU completo.
2
-
3
- Combina:
4
- - CooperativeCNNBiGRU para texto (dual-stream A/B)
5
- - ImageEncoder para modalidade visual
6
- - AudioEncoder para modalidade auditiva
7
- - MultimodalFusion com gated fusion
8
- - Cabeçalho de classificação + cabeçalho de geração (LM head)
9
-
10
- Suporta dois modos:
11
- mode="classify": retorna logits de classificação [B, num_classes]
12
- mode="generate": retorna logits de LM [B, T, vocab_size] (autoregressivo)
13
- """
14
- from __future__ import annotations
15
-
16
- import logging
17
- from typing import Optional
18
-
19
- import torch
20
- import torch.nn as nn
21
- import torch.nn.functional as F
22
-
23
- from .cooperative_bigru import CooperativeCNNBiGRU
24
- from .multimodal_encoders import ImageEncoder, AudioEncoder, MultimodalFusion
25
-
26
- logger = logging.getLogger(__name__)
27
-
28
-
29
- class MultimodalCNNBiGRU(nn.Module):
30
- """Modelo multimodal completo: texto (dual A/B) + imagem + áudio.
31
-
32
- Fluxo:
33
- 1. Texto A e Texto B -> CooperativeCNNBiGRU -> fused [B, 256]
34
- 2. Imagem -> ImageEncoder -> mean-pool -> [B, D_img]
35
- 3. Áudio -> AudioEncoder -> mean-pool -> [B, D_aud]
36
- 4. Fusão multimodal -> [B, out_dim]
37
- 5. Classificação: Linear(out_dim, num_classes)
38
- 6. Geração (opcional): Linear(out_dim, vocab_size) autoregressivo
39
- """
40
-
41
- def __init__(
42
- self,
43
- vocab_size: int,
44
- num_classes: int = 3,
45
- embedding_dim: int = 64,
46
- cnn_filters: int = 64,
47
- gru_hidden: int = 64,
48
- n_heads: int = 4,
49
- dropout: float = 0.1,
50
- pad_idx: int = 1,
51
- img_channels: int = 1,
52
- img_hidden: int = 32,
53
- img_out_dim: int = 64,
54
- audio_freq: int = 40,
55
- audio_hidden: int = 32,
56
- audio_out_dim: int = 64,
57
- fusion_dim: int = 128,
58
- use_spectral_norm: bool = False,
59
- ):
60
- super().__init__()
61
- self.pad_idx = pad_idx
62
- self.vocab_size = vocab_size
63
- self.num_classes = num_classes
64
-
65
- # Núcleo cooperativo de texto
66
- self.text_core = CooperativeCNNBiGRU(
67
- vocab_size=vocab_size,
68
- embedding_dim=embedding_dim,
69
- cnn_filters=cnn_filters,
70
- gru_hidden=gru_hidden,
71
- n_heads=n_heads,
72
- dropout=dropout,
73
- pad_idx=pad_idx,
74
- use_spectral_norm=use_spectral_norm,
75
- )
76
- d_text = self.text_core.feat_dim * 2 # 256 (fused A+B = 256, *2 para foco)
77
-
78
- # Encoders multimodais
79
- self.image_encoder = ImageEncoder(
80
- in_channels=img_channels,
81
- out_dim=img_out_dim,
82
- hidden_dim=img_hidden,
83
- )
84
- self.audio_encoder = AudioEncoder(
85
- n_freq=audio_freq,
86
- out_dim=audio_out_dim,
87
- hidden_dim=audio_hidden,
88
- )
89
-
90
- # Pooling de imagem/áudio para vetor fixo
91
- self.img_proj = nn.Linear(img_out_dim, img_out_dim)
92
- self.aud_proj = nn.Linear(audio_out_dim, audio_out_dim)
93
-
94
- # Fusão multimodal
95
- self.fusion = MultimodalFusion(
96
- d_text=d_text,
97
- d_img=img_out_dim,
98
- d_aud=audio_out_dim,
99
- out_dim=fusion_dim,
100
- dropout=dropout,
101
- )
102
-
103
- # Cabeçalho de classificação
104
- self.classifier = nn.Linear(fusion_dim, num_classes)
105
-
106
- # Cabeçalho de geração (LM head) — para modo autoregressivo
107
- self.lm_head = nn.Linear(fusion_dim, vocab_size, bias=False)
108
-
109
- # Dropout final
110
- self.dropout = nn.Dropout(dropout)
111
-
112
- def forward(
113
- self,
114
- input_ids_a: torch.Tensor,
115
- input_ids_b: torch.Tensor,
116
- images: Optional[torch.Tensor] = None,
117
- audios: Optional[torch.Tensor] = None,
118
- attn_mask_a: Optional[torch.Tensor] = None,
119
- attn_mask_b: Optional[torch.Tensor] = None,
120
- mode: str = "classify",
121
- ) -> dict:
122
- """
123
- Args:
124
- input_ids_a, input_ids_b: [B, T] tokens dos streams A e B
125
- images: [B, C, H, W] ou None
126
- audios: [B, 1, T, F] ou None
127
- mode: "classify" | "generate"
128
-
129
- Returns:
130
- dict com logits (classificação ou geração) + features intermediárias
131
- """
132
- # 1. Núcleo cooperativo de texto
133
- text_out = self.text_core(input_ids_a, input_ids_b, return_sequences=(mode == "generate"))
134
- fused_text = text_out["fused"] # [B, 256]
135
-
136
- # 2. Imagem
137
- if images is not None:
138
- img_seq = self.image_encoder(images) # [B, T_img, D_img]
139
- img_feat = img_seq.mean(dim=1) # [B, D_img]
140
- img_feat = self.img_proj(img_feat)
141
- else:
142
- # Vetor zero se não houver modalidade
143
- img_feat = torch.zeros(
144
- fused_text.size(0), self.img_proj.out_features,
145
- device=fused_text.device, dtype=fused_text.dtype,
146
- )
147
-
148
- # 3. Áudio
149
- if audios is not None:
150
- aud_seq = self.audio_encoder(audios) # [B, T_aud, D_aud]
151
- aud_feat = aud_seq.mean(dim=1)
152
- aud_feat = self.aud_proj(aud_feat)
153
- else:
154
- aud_feat = torch.zeros(
155
- fused_text.size(0), self.aud_proj.out_features,
156
- device=fused_text.device, dtype=fused_text.dtype,
157
- )
158
-
159
- # 4. Fusão multimodal
160
- fused = self.fusion(fused_text, img_feat, aud_feat) # [B, fusion_dim]
161
- fused = self.dropout(fused)
162
-
163
- result = {
164
- "fused": fused,
165
- "text_out": text_out,
166
- "img_feat": img_feat,
167
- "aud_feat": aud_feat,
168
- }
169
-
170
- # 5. Cabeçalhos
171
- if mode == "classify":
172
- result["logits"] = self.classifier(fused) # [B, num_classes]
173
- elif mode == "generate":
174
- # Modo geração: projetar fusão para vocab_size
175
- # (modo simplificado: geração single-step baseada na fusão)
176
- result["logits"] = self.lm_head(fused) # [B, vocab_size]
177
- else:
178
- raise ValueError(f"mode deve ser 'classify' ou 'generate', recebeu '{mode}'")
179
-
180
- return result
181
-
182
-
183
- __all__ = ["MultimodalCNNBiGRU"]