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