CAPÍTULO 04 · MADALINE

Muitas ADALINEs, mais de uma fronteira.

MADALINE significa Many ADALINEs. Em vez de depender de uma única separação linear, a arquitetura combina as decisões de várias unidades adaptativas.

Experimentar a rede →
x₁x₂
ADALINE 1ADALINE 2
ORŷ

01 · ARQUITETURA

De uma reta para uma combinação de regiões.

Cada ADALINE calcula seu próprio potencial e cria uma fronteira linear. Uma lógica fixa combina as respostas dessas unidades.

1

Entradas bipolares

No experimento, os valores binários 0 e 1 são convertidos internamente em −1 e +1.

0 → −1  ·  1 → +1
2

ADALINEs adaptativas

Cada unidade possui pesos e bias próprios. O potencial é linear; a decisão usa o sinal.

uⱼ = Σᵢwⱼᵢxᵢ + bⱼ
zⱼ = sinal(uⱼ)
3

Saída lógica fixa

Na MADALINE I deste exemplo, a saída vale +1 quando pelo menos uma ADALINE responde +1.

ŷ = OR(z₁, z₂)
ADALINE

Uma unidade adaptativa, uma fronteira linear e ajuste LMS pelo erro antes do limitador.

MADALINE

Várias ADALINEs, várias fronteiras e uma lógica que combina suas decisões.

MLP moderna

Camadas com ativações diferenciáveis, pesos de saída treináveis e backpropagation.

02 · MADALINE RULE I

Corrigir apenas quem pode assumir a responsabilidade.

A MR-I procura alterar o menor número possível de unidades. Essa ideia é conhecida como princípio da mínima perturbação.

1 · Forward

Calcule os potenciais u₁ e u₂ e as decisões bipolares z₁ e z₂.

uⱼ = wⱼ₁x₁ + wⱼ₂x₂ + bⱼ
2 · Lógica fixa

A função OR reúne as decisões ocultas e produz a previsão final.

ŷ = +1 se algum zⱼ = +1
3 · Responsabilidade

Se o alvo é +1, corrija a unidade mais próxima de mudar. Se é −1, corrija as unidades positivas.

menor |uⱼ| → menor perturbação
4 · LMS

A unidade selecionada é aproximada da resposta bipolar desejada.

eⱼ = dⱼ − uⱼ
wⱼᵢ ← wⱼᵢ + ηeⱼxᵢ
bⱼ ← bⱼ + ηeⱼ

03 · EXPERIMENTO AO VIVO

Treine uma MADALINE para resolver XOR.

Observe as duas fronteiras, as unidades escolhidas pela MR-I e cada conta da atualização LMS.

Rede MADALINE · 2 → 2 → OR → 1

Cada ligação colorida representa um peso adaptativo.

Rede nova
Selecione uma entrada para acompanhar o cálculo.
Épocas0
Acertos XOR
Erro médio

Duas fronteiras no plano

As retas tracejadas pertencem às duas ADALINEs.

ADALINE 1ADALINE 2ŷ = 1ŷ = 0

Passo a passo da última amostra

Forward, responsabilidade, erro linear e novos parâmetros.

Treine uma amostra para visualizar as contas.

Erro × resposta

Compare a taxa de erro com os acertos ao longo das épocas.

Erro médioTaxa de acerto

Tabela XOR

Potenciais e respostas de cada ADALINE.

x₁x₂u₁ → z₁u₂ → z₂alvoŷresultado

CÓDIGO COMPLETO E EXECUTÁVEL

Treine, avalie e use uma MADALINE no XOR

O exemplo agora inclui a rede, a tabela XOR, o laço de treinamento, a parada por acerto total, a avaliação e uma previsão final.

forward()selecionarUnidades()treinarAmostra()treinar()avaliar()
madaline-xor-completa.jsexecute do início ao fim
// Converte a entrada binária usada na interface para a notação bipolar.
function bipolar(valorBinario) {
  return valorBinario === 1 ? +1 : -1;
}

// Calcula a saída linear de uma unidade ADALINE.
function potencial(adaline, entradas) {
  return adaline.w1 * entradas[0]
       + adaline.w2 * entradas[1]
       + adaline.bias;
}

// O limitador transforma o potencial contínuo em uma decisão bipolar.
function sinal(u) {
  return u >= 0 ? +1 : -1;
}

// Cada ADALINE faz seu cálculo; a saída fixa executa uma lógica OR.
function forward(rede, entradas) {
  const ocultas = rede.map(adaline => {
    const u = potencial(adaline, entradas);
    return { u, z: sinal(u) };
  });
  const saida = ocultas.some(unidade => unidade.z === +1) ? +1 : -1;
  return { ocultas, saida };
}

// A MR-I altera somente as unidades necessárias para corrigir a resposta.
function selecionarUnidades(resultado, alvo) {
  if (resultado.saida === alvo) return [];

  // Para produzir +1, escolhe a unidade mais próxima do limiar.
  if (alvo === +1) {
    return [resultado.ocultas.reduce((melhor, atual, indice, lista) =>
      Math.abs(atual.u) < Math.abs(lista[melhor].u) ? indice : melhor, 0)];
  }

  // Para produzir -1, todas as unidades que votaram +1 devem ser corrigidas.
  return resultado.ocultas
    .map((unidade, indice) => unidade.z === +1 ? indice : -1)
    .filter(indice => indice >= 0);
}

// A Regra Delta/LMS usa o erro linear, calculado antes do limitador.
function atualizarLMS(adaline, entradas, respostaDesejada, eta) {
  const u = potencial(adaline, entradas);
  const erroLinear = respostaDesejada - u;
  adaline.w1 += eta * erroLinear * entradas[0];
  adaline.w2 += eta * erroLinear * entradas[1];
  adaline.bias += eta * erroLinear;
}

// Um passo completo: forward, responsabilidade e atualização das escolhidas.
function treinarAmostra(rede, entradas, alvo, eta) {
  const resultado = forward(rede, entradas);
  const escolhidas = selecionarUnidades(resultado, alvo);
  escolhidas.forEach(indice =>
    atualizarLMS(rede[indice], entradas, alvo, eta)
  );
}

// Tabela XOR em notação bipolar: -1 representa 0 e +1 representa 1.
const dados = [
  { entradas: [-1, -1], alvo: -1 },
  { entradas: [-1, +1], alvo: +1 },
  { entradas: [+1, -1], alvo: +1 },
  { entradas: [+1, +1], alvo: -1 }
];

// Duas ADALINEs formam a camada oculta da MADALINE.
const rede = [
  { w1: 0, w2: 0, bias: 0 },
  { w1: 0, w2: 0, bias: 0 }
];

function treinar(rede, dados, maximoEpocas, taxa) {
  for (let epoca = 1; epoca <= maximoEpocas; epoca++) {
    let erros = 0;

    for (let i = 0; i < dados.length; i++) {
      const antes = forward(rede, dados[i].entradas).saida;
      if (antes !== dados[i].alvo) erros++;
      treinarAmostra(rede, dados[i].entradas, dados[i].alvo, taxa);
    }
    if (erros === 0) return epoca;
  }
  return maximoEpocas;
}

function avaliar(rede, dados) {
  let acertos = 0;
  for (let i = 0; i < dados.length; i++) {
    if (forward(rede, dados[i].entradas).saida === dados[i].alvo) acertos++;
  }
  return acertos / dados.length;
}

function preverBinario(rede, x1, x2) {
  const entradas = [bipolar(x1), bipolar(x2)];
  return forward(rede, entradas).saida === +1 ? 1 : 0;
}

// ----------------------- USO DO MODELO -----------------------
const epocas = treinar(rede, dados, 500, 0.08);
console.log('Épocas:', epocas);
console.log('Acurácia:', avaliar(rede, dados));
console.log('XOR(1, 0):', preverBinario(rede, 1, 0));
console.log('Pesos aprendidos:', rede);

CONTINUE PRATICANDO

Compare MADALINE, Perceptron e MLP.

Observe como cada arquitetura atribui responsabilidade pelo erro e constrói suas fronteiras.

Ver todos os laboratórios →