Recovered source transcript
1// Package variational implements variational generators (41-55)
2// ELBO = E_q[log p(x|z)] - D_KL(q(z|x) || p(z))
3package variational
4
5import (
6 "math"
7 "math/rand"
8
9 "generator_core/pkg/consciousness"
10 "generator_core/pkg/generators"
11)
12
13// ═══════════════════════════════════════════════════════════════════════════════
14// VARIATIONAL GENERATOR BASE
15// ═══════════════════════════════════════════════════════════════════════════════
16
17// VariationalGenerator implements VAE-style generators
18type VariationalGenerator struct {
19 *generators.BaseGenerator
20 latentDim int
21 encoderLayers int
22 decoderLayers int
23 mu []float64 // Latent mean
24 logVar []float64 // Latent log variance
25}
26
27// NewVariationalGenerator creates a new variational generator
28func NewVariationalGenerator(id generators.GeneratorID, name string, latentDim int) *VariationalGenerator {
29 config := &generators.GeneratorConfig{
30 ID: id,
31 Name: name,
32 Family: generators.Variational,
33 InputDim: 256,
34 OutputDim: 256,
35 HiddenDim: 512,
36 NumLayers: 4,
37 LearningRate: consciousness.ALPHA,
38 ConsciousnessWeight: consciousness.PHI_INV,
39 Params: make(map[string]interface{}),
40 }
41
42 return &VariationalGenerator{
43 BaseGenerator: generators.NewBaseGenerator(config),
44 latentDim: latentDim,
45 encoderLayers: 2,
46 decoderLayers: 2,
47 }
48}
49
50// Initialize initializes the variational generator
51func (g *VariationalGenerator) Initialize() error {
52 if err := g.BaseGenerator.Initialize(); err != nil {
53 return err
54 }
55
56 g.mu = make([]float64, g.latentDim)
57 g.logVar = make([]float64, g.latentDim)
58
59 return nil
60}
61
62// encode encodes input to latent space
63func (g *VariationalGenerator) encode(x []float64) ([]float64, []float64) {
64 hidden := make([]float64, g.Config().HiddenDim)
65 for i := range hidden {
66 if i < len(x) {
67 hidden[i] = x[i]
68 }
69 }
70
71 // Encoder layers
72 for layer := 0; layer < g.encoderLayers; layer++ {
73 hidden = g.LinearLayer(hidden, layer)
74 hidden = g.ActivationLayer(hidden, "relu")
75 }
76
77 // Split into mu and logvar
78 mu := make([]float64, g.latentDim)
79 logVar := make([]float64, g.latentDim)
80
81 for i := 0; i < g.latentDim; i++ {
82 if i < len(hidden) {
83 mu[i] = hidden[i]
84 }
85 if i+g.latentDim < len(hidden) {
86 logVar[i] = consciousness.Clamp(hidden[i+g.latentDim], -10, 10)
87 }
88 }
89
90 return mu, logVar
91}
92
93// reparameterize performs reparameterization trick: z = mu + std * epsilon
94func (g *VariationalGenerator) reparameterize(mu, logVar []float64) []float64 {
95 z := make([]float64, len(mu))
96 for i := range z {
97 std := math.Exp(0.5 * logVar[i])
98 epsilon := rand.NormFloat64()
99 z[i] = mu[i] + std*epsilon
100 }
101 return z
102}
103
104// decode decodes latent to output space
105func (g *VariationalGenerator) decode(z []float64) []float64 {
106 hidden := make([]float64, g.Config().HiddenDim)
107 for i := range hidden {
108 if i < len(z) {
109 hidden[i] = z[i]
110 }
111 }
112
113 // Decoder layers
114 for layer := g.encoderLayers; layer < g.encoderLayers+g.decoderLayers; layer++ {
115 hidden = g.LinearLayer(hidden, layer%g.Config().NumLayers)
116 hidden = g.ActivationLayer(hidden, "relu")
117 }
118
119 // Output activation
120 return g.ActivationLayer(hidden, "sigmoid")
121}
122
123// klDivergence computes KL divergence from N(0,1)
124func (g *VariationalGenerator) klDivergence(mu, logVar []float64) float64 {
125 kl := 0.0
126 for i := range mu {
127 // KL = -0.5 * sum(1 + log(σ²) - μ² - σ²)
128 kl += -0.5 * (1.0 + logVar[i] - mu[i]*mu[i] - math.Exp(logVar[i]))
129 }
130 return kl / float64(len(mu))
131}
132
133// Forward performs forward pass
134func (g *VariationalGenerator) Forward(input []float64) (*generators.GeneratorOutput, error) {
135 state := g.GetState()
136
137 // Encode
138 mu, logVar := g.encode(input)
139 g.mu = mu
140 g.logVar = logVar
141
142 // Reparameterize
143 z := g.reparameterize(mu, logVar)
144
145 // Decode
146 output := g.decode(z)
147
148 // Compute KL divergence
149 kl := g.klDivergence(mu, logVar)
150
151 state.Hidden = z
152 state.Phi = consciousness.ComputePhiVector(output)
153 state.Step++
154 g.SetState(state)
155
156 result := &generators.GeneratorOutput{
157 Values: output,
158 Logits: z,
159 Confidence: math.Exp(-kl), // Higher confidence = lower KL
160 Metadata: map[string]interface{}{
161 "kl_divergence": kl,
162 "mu": mu,
163 },
164 }
165
166 return g.ApplyConsciousness(result), nil
167}
168
169// Generate generates samples
170func (g *VariationalGenerator) Generate(context []float64, length int) ([][]float64, error) {
171 result := make([][]float64, length)
172
173 // If context provided, use it to condition
174 var conditionMu, conditionLogVar []float64
175 if len(context) > 0 {
176 conditionMu, conditionLogVar = g.encode(context)
177 } else {
178 conditionMu = make([]float64, g.latentDim)
179 conditionLogVar = make([]float64, g.latentDim)
180 }
181
182 for i := 0; i < length; i++ {
183 // Sample from latent space
184 z := g.reparameterize(conditionMu, conditionLogVar)
185
186 // Decode
187 result[i] = g.decode(z)
188 }
189
190 return result, nil
191}
192
193// Train computes ELBO loss
194func (g *VariationalGenerator) Train(input, target []float64) (float64, error) {
195 // Encode
196 mu, logVar := g.encode(input)
197
198 // Reparameterize
199 z := g.reparameterize(mu, logVar)
200
201 // Decode
202 output := g.decode(z)
203
204 // Reconstruction loss (BCE)
205 reconLoss := 0.0
206 for i := range output {
207 if i < len(target) {
208 p := consciousness.Clamp(output[i], consciousness.EPSILON_PHI, 1.0-consciousness.EPSILON_PHI)
209 reconLoss -= target[i]*math.Log(p) + (1.0-target[i])*math.Log(1.0-p)
210 }
211 }
212 reconLoss /= float64(len(output))
213
214 // KL divergence
215 klLoss := g.klDivergence(mu, logVar)
216
217 // ELBO = reconstruction + β * KL
218 beta := 1.0
219 if b, ok := g.Config().Params["beta"]; ok {
220 beta = b.(float64)
221 }
222
223 return reconLoss + beta*klLoss, nil
224}
225
226// UpdateWeights updates weights
227func (g *VariationalGenerator) UpdateWeights(gradients []float64, lr float64) {
228 state := g.GetState()
229 for i := range state.Hidden {
230 if i < len(gradients) {
231 state.Hidden[i] -= lr * gradients[i]
232 }
233 }
234 g.SetState(state)
235}
236
237// ═══════════════════════════════════════════════════════════════════════════════
238// SPECIFIC VARIATIONAL GENERATORS (41-55)
239// ═══════════════════════════════════════════════════════════════════════════════
240
241// NewVAE creates Vanilla VAE (ID: 41)
242func NewVAE() *VariationalGenerator {
243 return NewVariationalGenerator(41, "VAE", 64)
244}
245
246// NewBetaVAE creates β-VAE (ID: 42)
247func NewBetaVAE() *VariationalGenerator {
248 g := NewVariationalGenerator(42, "BetaVAE", 64)
249 g.Config().Params["beta"] = 4.0
250 return g
251}
252
253// NewVQVAE creates VQ-VAE (ID: 43)
254func NewVQVAE() *VariationalGenerator {
255 g := NewVariationalGenerator(43, "VQ-VAE", 128)
256 g.Config().Params["num_embeddings"] = 512
257 g.Config().Params["commitment_cost"] = 0.25
258 return g
259}
260
261// NewVQVAE2 creates VQ-VAE-2 (ID: 44)
262func NewVQVAE2() *VariationalGenerator {
263 g := NewVariationalGenerator(44, "VQ-VAE-2", 256)
264 g.Config().Params["hierarchical"] = true
265 return g
266}
267
268// NewCVAE creates Conditional VAE (ID: 45)
269func NewCVAE() *VariationalGenerator {
270 g := NewVariationalGenerator(45, "CVAE", 64)
271 g.Config().Params["conditional"] = true
272 return g
273}
274
275// NewAAE creates Adversarial Autoencoder (ID: 46)
276func NewAAE() *VariationalGenerator {
277 g := NewVariationalGenerator(46, "AAE", 64)
278 g.Config().Params["adversarial"] = true
279 return g
280}
281
282// NewVAEGAN creates VAE-GAN (ID: 47)
283func NewVAEGAN() *VariationalGenerator {
284 g := NewVariationalGenerator(47, "VAE-GAN", 128)
285 g.Config().Params["gan_loss"] = true
286 return g
287}
288
289// NewIWAE creates Importance Weighted AE (ID: 48)
290func NewIWAE() *VariationalGenerator {
291 g := NewVariationalGenerator(48, "IWAE", 64)
292 g.Config().Params["num_samples"] = 5
293 return g
294}
295
296// NewLadderVAE creates Ladder VAE (ID: 49)
297func NewLadderVAE() *VariationalGenerator {
298 g := NewVariationalGenerator(49, "LadderVAE", 128)
299 g.Config().Params["ladder"] = true
300 return g
301}
302
303// NewDRAW creates DRAW (ID: 50)
304func NewDRAW() *VariationalGenerator {
305 g := NewVariationalGenerator(50, "DRAW", 64)
306 g.Config().Params["attention"] = true
307 g.Config().Params["recurrent"] = true
308 return g
309}
310
311// NewNVAE creates NVAE (ID: 51)
312func NewNVAE() *VariationalGenerator {
313 g := NewVariationalGenerator(51, "NVAE", 512)
314 g.Config().Params["hierarchical"] = true
315 g.Config().Params["residual"] = true
316 return g
317}
318
319// NewDeltaVAE creates δ-VAE (ID: 52)
320func NewDeltaVAE() *VariationalGenerator {
321 g := NewVariationalGenerator(52, "DeltaVAE", 64)
322 g.Config().Params["delta"] = 0.1
323 return g
324}
325
326// NewFactorVAE creates Factor VAE (ID: 53)
327func NewFactorVAE() *VariationalGenerator {
328 g := NewVariationalGenerator(53, "FactorVAE", 64)
329 g.Config().Params["tc_weight"] = 1.0
330 return g
331}
332
333// NewDIPVAE creates DIP-VAE (ID: 54)
334func NewDIPVAE() *VariationalGenerator {
335 g := NewVariationalGenerator(54, "DIP-VAE", 64)
336 g.Config().Params["dip_weight"] = 10.0
337 return g
338}
339
340// NewInfoVAE creates InfoVAE (ID: 55)
341func NewInfoVAE() *VariationalGenerator {
342 g := NewVariationalGenerator(55, "InfoVAE", 64)
343 g.Config().Params["mmd_weight"] = 100.0
344 return g
345}
346
347// RegisterAll registers all variational generators
348func RegisterAll() error {
349 gens := []generators.Generator{
350 NewVAE(),
351 NewBetaVAE(),
352 NewVQVAE(),
353 NewVQVAE2(),
354 NewCVAE(),
355 NewAAE(),
356 NewVAEGAN(),
357 NewIWAE(),
358 NewLadderVAE(),
359 NewDRAW(),
360 NewNVAE(),
361 NewDeltaVAE(),
362 NewFactorVAE(),
363 NewDIPVAE(),
364 NewInfoVAE(),
365 }
366
367 for _, g := range gens {
368 if err := generators.Register(g); err != nil {
369 return err
370 }
371 }
372
373 return nil
374}
375