LABORATÓRIO · MINI GAN

Veja um dígito se formar durante o jogo adversário.

Escolha um dígito. O Gerador transforma três números de ruído em 49 pixels; o Discriminador tenta separar os exemplos reais das imagens falsas.

z₁,z₂,z₃ruídoGerador49 pixelsDiscriminadorreal?
Escopo didático: a imagem é reduzida para 7 × 7 e cada rede possui uma única camada. Isso permite mostrar a Regra da Cadeia completa. GANs de imagens reais usam redes profundas e muitos exemplos.
RODADAS0
LOSS D
LOSS G
SEMELHANÇA

A rede neural adversária

Acompanhe o forward do ruído até a decisão e o caminho inverso do gradiente usado para ensinar o Gerador.

Forward inicial
peso positivopeso negativogradiente voltandoD congelado ao treinar G
A rede será desenhada assim que os exemplos forem carregados.
1 · gerar(z)Calcula 49 somas ponderadas e aplica Sigmoid para formar os pixels falsos.
2 · discriminar(x)Soma os 49 pixels ponderados e aplica Sigmoid para estimar a chance de ser real.
3 · treinar DD compara real com alvo 1 e falso com alvo 0; somente seus pesos são ajustados.
4 · treinar GD fica congelado. O erro volta por D e corrige os pesos do Gerador.

Exemplos usados como referência real

Os dez recortes vieram da imagem indicada. O dígito escolhido gera pequenas variações de posição durante o treino.

Preparando imagens

O jogo desta rodada

D recebe um real com alvo 1 e um falso com alvo 0. Depois G tenta fazer o falso receber alvo 1.

Gerador G

D(G(z)) = —
VS

Discriminador D

D(xreal) = —

A imagem se formando

As quatro grades usam o mesmo vetor z para tornar a evolução comparável.

rodada 0
rodada 50
rodada 500
agora

Última rodada, passo a passo

Saídas, perdas, gradientes e atualização de um pixel representativo.

Erro × resposta

A perda média é comparada à semelhança entre a imagem gerada e o protótipo real.

loss normalizadasemelhança
Folha de números manuscritos usada como referência

Preparação dos dados

A folha original foi dividida em dez imagens quadradas. No laboratório, cada imagem é reduzida para 7 × 7 intensidades e deslocada levemente para criar exemplos reais simples.

CÓDIGO COMPLETO E EXECUTÁVEL

Treine uma mini GAN e gere um desenho 7 × 7

O programa inicializa as duas redes, alterna o treino do Discriminador e do Gerador e imprime uma imagem sintética no console. É uma GAN mínima com uma única referência, criada para expor o fluxo matemático — não substitui uma GAN convolucional treinada com MNIST.

iniciarRedes()gerar()discriminar()treinar()mostrarImagem()
// ============================================================
// MINI GAN: vetor aleatório com 3 valores → imagem 7 × 7
// ============================================================
var tamanhoRuido = 3;
var quantidadePixels = 49;
var taxaD = 0.05;
var taxaG = 0.05;
var pesosD = [];
var biasD = 0;
var pesosG = [];
var biasG = [];

// Uma imagem real simples do dígito 1.
var linhasReais = [
  '0011000', '0111000', '0011000', '0011000',
  '0011000', '0011000', '0111110'
];

function converterImagem(linhas) {
  var pixels = [];
  for (var linha = 0; linha < 7; linha++) {
    for (var coluna = 0; coluna < 7; coluna++) {
      pixels.push(Number(linhas[linha][coluna]));
    }
  }
  return pixels;
}

var imagemReal = converterImagem(linhasReais);

function sigmoid(x) {
  return 1 / (1 + Math.exp(-x));
}

function iniciarRedes() {
  pesosD = [];
  pesosG = [];
  biasG = [];
  biasD = 0;

  for (var pixel = 0; pixel < quantidadePixels; pixel++) {
    pesosD[pixel] = Math.sin(pixel + 1) * 0.05;
    biasG[pixel] = 0;
    pesosG[pixel] = [];
    for (var j = 0; j < tamanhoRuido; j++) {
      pesosG[pixel][j] = Math.cos((pixel + 1) * (j + 1)) * 0.05;
    }
  }
}

function criarRuido(passo) {
  return [
    Math.sin(passo * 1.7),
    Math.sin(passo * 2.3 + 1),
    Math.cos(passo * 0.9)
  ];
}

function gerar(z) {
  var imagem = [];
  for (var pixel = 0; pixel < quantidadePixels; pixel++) {
    var u = biasG[pixel];
    for (var j = 0; j < tamanhoRuido; j++) u += pesosG[pixel][j] * z[j];
    imagem[pixel] = sigmoid(u);
  }
  return imagem;
}

function discriminar(imagem) {
  var u = biasD;
  for (var i = 0; i < quantidadePixels; i++) u += pesosD[i] * imagem[i];
  return sigmoid(u); // probabilidade de a imagem ser real
}

// D aprende alvo 1 para a imagem real e alvo 0 para a falsa.
function treinarDiscriminador(real, falso) {
  var dReal = discriminar(real);
  var dFalso = discriminar(falso);

  for (var i = 0; i < quantidadePixels; i++) {
    var gradiente = ((dReal - 1) * real[i] + dFalso * falso[i]) / 2;
    pesosD[i] -= taxaD * gradiente;
  }
  biasD -= taxaD * ((dReal - 1) + dFalso) / 2;
}

// G tenta fazer D(G(z)) aproximar-se de 1.
function treinarGerador(z) {
  var falso = gerar(z);
  var dFalso = discriminar(falso);

  for (var i = 0; i < quantidadePixels; i++) {
    var gradientePixel = (dFalso - 1) * pesosD[i];
    var gradienteU = gradientePixel * falso[i] * (1 - falso[i]);
    for (var j = 0; j < tamanhoRuido; j++) {
      pesosG[i][j] -= taxaG * gradienteU * z[j];
    }
    biasG[i] -= taxaG * gradienteU;
  }
}

function treinar(passos) {
  for (var passo = 1; passo <= passos; passo++) {
    var z = criarRuido(passo);
    var falso = gerar(z);
    treinarDiscriminador(imagemReal, falso); // fase 1
    treinarGerador(z);                       // fase 2
  }
}

function mostrarImagem(imagem) {
  var desenho = '';
  for (var i = 0; i < imagem.length; i++) {
    desenho += imagem[i] >= 0.5 ? '██' : '  ';
    if ((i + 1) % 7 === 0) desenho += '\n';
  }
  console.log(desenho);
}

// ----------------------- USO DO MODELO -----------------------
iniciarRedes();
treinar(3000);
var imagemGerada = gerar([0.2, -0.4, 0.8]);
console.log('D(real):', discriminar(imagemReal));
console.log('D(gerada):', discriminar(imagemGerada));
mostrarImagem(imagemGerada);