Notebook com códigos R para a implementação do Perceptron - ERAMIA 2020

Carregando os dados - Exemplo com o dataset Iris

data(iris)

Estatísticas sobre os dados

dim(iris)
names(iris)
summary(iris$Species)

Vamos ver como os atributos separam os dados

pairs(iris[,1:4], col=iris$Species)

Vamos pegar os atributos Sepal Width e Petal Width, pois o Percetron só consegue separar dados linearmente separáveis

x <- cbind(iris$Sepal.Width,iris$Petal.Width)

Agora vamos rotular Iris Setosa como positivo e o resto dos dados como negativo

y <- ifelse(iris$Species == "setosa", +1, -1)

Vamos iniciar a implementação do Perceptron. Inicialmente vamos definir o bias e utilizá-lo como uma das entradas

bias <- rep(1,nrow(x))
x <- cbind(x,bias)

Vamos agora concatenar as classes

x <- cbind(x,y)

Vamos gerar os pesos iniciar aleatoriamente

pesos <- runif(3,-1,1)

Código principal da função de treinamento do Perceptron. Essa função nos retornará os pesos atualizados do Perceptron. O treinamento será realizado até todos os exemplos de treino serem corretamente classificados.

perceptron.treino <- function(dados,pesos){

    # Taxa de aprendizado
    n <- 0.3

    # Controle
    erro <- 1
    epocas <- 0

    while(erro == 1){
        erro <- 0
        epocas <- epocas + 1
        erroMedio <- 0
        for(i in 1:nrow(dados)){
            v <- 0
            # Potencial de ativacao
            for(j in 1:length(pesos)){
                v <- v + dados[i,j]*pesos[j]
            }

            # Funcao sinal
            y <- sign(v)
            erroMedio <- erroMedio + (dados[i,4] - y)*(dados[i,4] - y)

            # Atualizacao dos pesos
            if(dados[i,4] != y){
                erro <- 1
                for(j in 1:length(pesos)){
                    pesos[j] <- pesos[j] + n*(dados[i,4] - y)*dados[i,j]
                }
            }
        }
        erroMedio <- erroMedio/nrow(dados)
        cat("\nErro Medio = ",erroMedio)

    }
    cat("\nFinalizado com ",epocas," epocas\n")
    return(pesos)
}

Agora vamos chamar a função de treino do Perceptron, passsando como parâmetros os dados e os pesos.

pesos.iris <- perceptron.treino(x,pesos)

Vamos comparar os pesos iniciais com os pesos finais

print(pesos)
print(pesos.iris)

Vamos ver como ficou o hiperplano aprendido pelo Perceptron. Inicialmente vamos plotar os dados de treinamento e depois traçar o hiperplano

# Plotando os dados
plot(x,cex=0.2)
points(subset(x,y==1),col="black",pch="+",cex=2)
points(subset(x,y==-1),col="red",pch="-",cex=2)

# Traçando o hiperplano
# Toda equação na forma y = mx + q é chamada equação reduzida da reta, em que m é o coeficiente angular, e q é a ordenada do ponto no qual a reta cruza o eixo y. A equação reduzida pode ser obtida diretamente da equação geral ax + by + c = 0. Assim:

# ax + by + c = 0 -> by = -ax –c

# y = -a/b x  - c/b

# m = -a/b
# q = -c/b
intercept <- - pesos.iris[3] / pesos.iris[2]
slope <- - pesos.iris[1] / pesos.iris[2]
abline(intercept,slope,col="green")

Precisamos agora de uma função para classificação de novos dados.

perceptron <- function(exemplo,pesos){
    v <- 0
    for(i in 1:length(exemplo)){
        # Potencial de ativacao
        v <- v + exemplo[i]*pesos[i]
        # Funcao sinal
    }
    y <- sign(v)
    return(y)
}

Vamos agora criar alguns dados novos para testar nosso Perceptron

novo.dado <- c(2.5,0.3,1)
perceptron(novo.dado,pesos.iris)

novo.dado <- c(2.5,1,1)
perceptron(novo.dado,pesos.iris)
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayAtIFBlcmNlcHRyb24iCm91dHB1dDogaHRtbF9ub3RlYm9vawoKLS0tCgojIyBOb3RlYm9vayBjb20gY8OzZGlnb3MgUiBwYXJhIGEgaW1wbGVtZW50YcOnw6NvIGRvIFBlcmNlcHRyb24gLSBFUkFNSUEgMjAyMAoKQ2FycmVnYW5kbyBvcyBkYWRvcyAtIEV4ZW1wbG8gY29tIG8gZGF0YXNldCBJcmlzCmBgYHtyfQpkYXRhKGlyaXMpCmBgYAoKCkVzdGF0w61zdGljYXMgc29icmUgb3MgZGFkb3MKYGBge3J9CmRpbShpcmlzKQpuYW1lcyhpcmlzKQpzdW1tYXJ5KGlyaXMkU3BlY2llcykKYGBgCgoKVmFtb3MgdmVyIGNvbW8gb3MgYXRyaWJ1dG9zIHNlcGFyYW0gb3MgZGFkb3MKYGBge3J9CnBhaXJzKGlyaXNbLDE6NF0sIGNvbD1pcmlzJFNwZWNpZXMpCmBgYAoKCgpWYW1vcyBwZWdhciBvcyBhdHJpYnV0b3MgU2VwYWwgV2lkdGggZSBQZXRhbCBXaWR0aCwgcG9pcyBvIFBlcmNldHJvbiBzw7MgY29uc2VndWUgc2VwYXJhciBkYWRvcyBsaW5lYXJtZW50ZSBzZXBhcsOhdmVpcwpgYGB7cn0KeCA8LSBjYmluZChpcmlzJFNlcGFsLldpZHRoLGlyaXMkUGV0YWwuV2lkdGgpCmBgYAoKCkFnb3JhIHZhbW9zIHJvdHVsYXIgSXJpcyBTZXRvc2EgY29tbyBwb3NpdGl2byBlIG8gcmVzdG8gZG9zIGRhZG9zIGNvbW8gbmVnYXRpdm8KYGBge3J9CnkgPC0gaWZlbHNlKGlyaXMkU3BlY2llcyA9PSAic2V0b3NhIiwgKzEsIC0xKQpgYGAKCgpWYW1vcyBpbmljaWFyIGEgaW1wbGVtZW50YcOnw6NvIGRvIFBlcmNlcHRyb24uIEluaWNpYWxtZW50ZSB2YW1vcyBkZWZpbmlyIG8gYmlhcyBlIHV0aWxpesOhLWxvIGNvbW8gdW1hIGRhcyBlbnRyYWRhcwpgYGB7cn0KYmlhcyA8LSByZXAoMSxucm93KHgpKQp4IDwtIGNiaW5kKHgsYmlhcykKYGBgCgpWYW1vcyBhZ29yYSBjb25jYXRlbmFyIGFzIGNsYXNzZXMKYGBge3J9CnggPC0gY2JpbmQoeCx5KQpgYGAKCgpWYW1vcyBnZXJhciBvcyBwZXNvcyBpbmljaWFyIGFsZWF0b3JpYW1lbnRlCmBgYHtyfQpwZXNvcyA8LSBydW5pZigzLC0xLDEpCmBgYAoKCkPDs2RpZ28gcHJpbmNpcGFsIGRhIGZ1bsOnw6NvIGRlIHRyZWluYW1lbnRvIGRvIFBlcmNlcHRyb24uCkVzc2EgZnVuw6fDo28gbm9zIHJldG9ybmFyw6Egb3MgcGVzb3MgYXR1YWxpemFkb3MgZG8gUGVyY2VwdHJvbi4gTyB0cmVpbmFtZW50byBzZXLDoSByZWFsaXphZG8gYXTDqSB0b2RvcyBvcyBleGVtcGxvcyBkZSB0cmVpbm8gc2VyZW0gY29ycmV0YW1lbnRlIGNsYXNzaWZpY2Fkb3MuCmBgYHtyfQpwZXJjZXB0cm9uLnRyZWlubyA8LSBmdW5jdGlvbihkYWRvcyxwZXNvcyl7CgogICAgIyBUYXhhIGRlIGFwcmVuZGl6YWRvCiAgICBuIDwtIDAuMwoKICAgICMgQ29udHJvbGUKICAgIGVycm8gPC0gMQogICAgZXBvY2FzIDwtIDAKCiAgICB3aGlsZShlcnJvID09IDEpewogICAgICAgIGVycm8gPC0gMAogICAgICAgIGVwb2NhcyA8LSBlcG9jYXMgKyAxCiAgICAgICAgZXJyb01lZGlvIDwtIDAKICAgICAgICBmb3IoaSBpbiAxOm5yb3coZGFkb3MpKXsKICAgICAgICAgICAgdiA8LSAwCiAgICAgICAgICAgICMgUG90ZW5jaWFsIGRlIGF0aXZhY2FvCiAgICAgICAgICAgIGZvcihqIGluIDE6bGVuZ3RoKHBlc29zKSl7CiAgICAgICAgICAgICAgICB2IDwtIHYgKyBkYWRvc1tpLGpdKnBlc29zW2pdCiAgICAgICAgICAgIH0KCiAgICAgICAgICAgICMgRnVuY2FvIHNpbmFsCiAgICAgICAgICAgIHkgPC0gc2lnbih2KQogICAgICAgICAgICBlcnJvTWVkaW8gPC0gZXJyb01lZGlvICsgKGRhZG9zW2ksNF0gLSB5KSooZGFkb3NbaSw0XSAtIHkpCgogICAgICAgICAgICAjIEF0dWFsaXphY2FvIGRvcyBwZXNvcwogICAgICAgICAgICBpZihkYWRvc1tpLDRdICE9IHkpewogICAgICAgICAgICAgICAgZXJybyA8LSAxCiAgICAgICAgICAgICAgICBmb3IoaiBpbiAxOmxlbmd0aChwZXNvcykpewogICAgICAgICAgICAgICAgICAgIHBlc29zW2pdIDwtIHBlc29zW2pdICsgbiooZGFkb3NbaSw0XSAtIHkpKmRhZG9zW2ksal0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBlcnJvTWVkaW8gPC0gZXJyb01lZGlvL25yb3coZGFkb3MpCiAgICAgICAgY2F0KCJcbkVycm8gTWVkaW8gPSAiLGVycm9NZWRpbykKCiAgICB9CiAgICBjYXQoIlxuRmluYWxpemFkbyBjb20gIixlcG9jYXMsIiBlcG9jYXNcbiIpCiAgICByZXR1cm4ocGVzb3MpCn0KYGBgCgoKQWdvcmEgdmFtb3MgY2hhbWFyIGEgZnVuw6fDo28gZGUgdHJlaW5vIGRvIFBlcmNlcHRyb24sIHBhc3NzYW5kbyBjb21vIHBhcsOibWV0cm9zIG9zIGRhZG9zIGUgb3MgcGVzb3MuCmBgYHtyfQpwZXNvcy5pcmlzIDwtIHBlcmNlcHRyb24udHJlaW5vKHgscGVzb3MpCmBgYAoKClZhbW9zIGNvbXBhcmFyIG9zIHBlc29zIGluaWNpYWlzIGNvbSBvcyBwZXNvcyBmaW5haXMKYGBge3J9CnByaW50KHBlc29zKQpwcmludChwZXNvcy5pcmlzKQpgYGAKCgpWYW1vcyB2ZXIgY29tbyBmaWNvdSBvIGhpcGVycGxhbm8gYXByZW5kaWRvIHBlbG8gUGVyY2VwdHJvbi4gSW5pY2lhbG1lbnRlIHZhbW9zIHBsb3RhciBvcyBkYWRvcyBkZSB0cmVpbmFtZW50byBlIGRlcG9pcyB0cmHDp2FyIG8gaGlwZXJwbGFubwpgYGB7cn0KIyBQbG90YW5kbyBvcyBkYWRvcwpwbG90KHgsY2V4PTAuMikKcG9pbnRzKHN1YnNldCh4LHk9PTEpLGNvbD0iYmxhY2siLHBjaD0iKyIsY2V4PTIpCnBvaW50cyhzdWJzZXQoeCx5PT0tMSksY29sPSJyZWQiLHBjaD0iLSIsY2V4PTIpCgojIFRyYcOnYW5kbyBvIGhpcGVycGxhbm8KIyBUb2RhIGVxdWHDp8OjbyBuYSBmb3JtYSB5ID0gbXggKyBxIMOpIGNoYW1hZGEgZXF1YcOnw6NvIHJlZHV6aWRhIGRhIHJldGEsIGVtIHF1ZSBtIMOpIG8gY29lZmljaWVudGUgYW5ndWxhciwgZSBxIMOpIGEgb3JkZW5hZGEgZG8gcG9udG8gbm8gcXVhbCBhIHJldGEgY3J1emEgbyBlaXhvIHkuIEEgZXF1YcOnw6NvIHJlZHV6aWRhIHBvZGUgc2VyIG9idGlkYSBkaXJldGFtZW50ZSBkYSBlcXVhw6fDo28gZ2VyYWwgYXggKyBieSArIGMgPSAwLiBBc3NpbToKCiMgYXggKyBieSArIGMgPSAwIC0+IGJ5ID0gLWF4IOKAk2MKCiMgeSA9IC1hL2IgeCAgLSBjL2IKCiMgbSA9IC1hL2IKIyBxID0gLWMvYgppbnRlcmNlcHQgPC0gLSBwZXNvcy5pcmlzWzNdIC8gcGVzb3MuaXJpc1syXQpzbG9wZSA8LSAtIHBlc29zLmlyaXNbMV0gLyBwZXNvcy5pcmlzWzJdCmFibGluZShpbnRlcmNlcHQsc2xvcGUsY29sPSJncmVlbiIpCmBgYAoKClByZWNpc2Ftb3MgYWdvcmEgZGUgdW1hIGZ1bsOnw6NvIHBhcmEgY2xhc3NpZmljYcOnw6NvIGRlIG5vdm9zIGRhZG9zLgpgYGB7cn0KcGVyY2VwdHJvbiA8LSBmdW5jdGlvbihleGVtcGxvLHBlc29zKXsKICAgIHYgPC0gMAogICAgZm9yKGkgaW4gMTpsZW5ndGgoZXhlbXBsbykpewogICAgICAgICMgUG90ZW5jaWFsIGRlIGF0aXZhY2FvCiAgICAgICAgdiA8LSB2ICsgZXhlbXBsb1tpXSpwZXNvc1tpXQogICAgICAgICMgRnVuY2FvIHNpbmFsCiAgICB9CiAgICB5IDwtIHNpZ24odikKICAgIHJldHVybih5KQp9CmBgYAoKClZhbW9zIGFnb3JhIGNyaWFyIGFsZ3VucyBkYWRvcyBub3ZvcyBwYXJhIHRlc3RhciBub3NzbyBQZXJjZXB0cm9uCmBgYHtyfQpub3ZvLmRhZG8gPC0gYygyLjUsMC4zLDEpCnBlcmNlcHRyb24obm92by5kYWRvLHBlc29zLmlyaXMpCgpub3ZvLmRhZG8gPC0gYygyLjUsMSwxKQpwZXJjZXB0cm9uKG5vdm8uZGFkbyxwZXNvcy5pcmlzKQpgYGAKCgoK