1 Resumo

A coluna vertebral, também chamada de espinha dorsal, estende-se do crânio até a pelve. Ela é responsável por dois quintos do peso corporal total e é composta por tecido conjuntivo e por uma série de ossos, chamados vértebras, as quais estão sobrepostas em forma de uma coluna, daí o termo coluna vertebral. A coluna vertebral é constituída por 24 vértebras, sacro, cóccix e constitui, junto com a cabeça, esterno e costelas, o esqueleto axial. Este trabalho tem como objetivo apresentar resultados sobre a aplicação de um modelo de rede neural artificial para auxiliar na classificação de pacientes que possuem coluna vertebral Normal, Hérnia de disco ou Espondilolistese.

2 Introdução

O presente trabalho busca abordar e aplicar a computação neural usando o Pacote neuralnet do R. O R é uma linguagem de programação e também um ambiente de desenvolvimento integrado para cálculos estatísticos e gráficos. O problema desse trabalho foi estudado considerando o banco de dados “Vertebral Column Data Set”, disponível no site UCI - Machine Learning Repository. Os dados foram trabalhados por meio de um problema de classificação. O site traz a seguinte descrição do banco de dados: " O conjunto de dados biomédicos desenvolvidos pelo Dr. Henrique da Mota durante um período de residência médica no Grupo de Pesquisas Aplicadas em Ortopedia (GARO) do Centro Médico-Cirúrgico de Adaptação de Massues, Lyon, França. Os dados foram organizados em duas tarefas de classificação diferentes, mas relacionadas.
A primeira tarefa consiste em classificar os pacientes como pertencentes a uma das três categorias: Normal (100 pacientes), Hérnia do disco (60 pacientes) ou Espondilolistese (150 pacientes). Para a segunda tarefa, as categorias Hérnia de disco e Espondilolistese foram incorporadas em uma única categoria rotulada como “anormal”. Assim, a segunda tarefa consiste em classificar os pacientes como pertencentes a uma das duas categorias: Normal (100 pacientes) ou anormal (210 pacientes). Neste trabalho foi abordada a primeira tarefa apresentada, classificando-a de acordo com o que foi descrito acima.
E cada paciente estudado será avaliado considerando 6 variáveis, como também foi explicado no banco de dados: “Cada paciente é representado no conjunto de dados por seis atributos biomecânicos derivados da forma e orientação da pélvis e da coluna lombar (nesta ordem): incidência pélvica, inclinação pélvica, ângulo de lordose lombar, inclinação sacra, raio pélvico e grau de espondilolistese. A convenção a seguir é usada para os rótulos das classes: DH (Hérnia do Disco), Espondilolistese (SL), Normal (NO) e Anormal (AB).”

3 Definição do problema e Metodologia

3.1 Classificação

Em um problema de classificação tradicional temos um conjunto de n objetos e um conjunto de m classes e queremos classificar cada objeto como pertencente a uma classe, de modo que esta classificação seja consistente com alguns dados que temos sobre o problema.
“Classificador é o elemento que possui como entrada um padrão e, como saída, o rótulo que identifica a que classe tal padrão pertence” (CAMPOS, 2001). As decisões tomadas pelo classificador se dão pelo aprendizado obtido através do conjunto de treinamento. Este deve possuir os exemplos dos padrões que o sistema receberá através do sistema de aquisição dos dados.
A classificação por similaridade é a base da maioria dos classificadores. Se um padrão apresentado “X” for similar a outro que pertence a uma classe “C”, a tendência é classificar “X” como pertencente à classe “C”. De acordo com Télvio Orrú (n.d.), em sua revisão bibliográfica com tema:Redes Neurais Artificiais para Reconhecimento e Classificação de Padrões, uma rede neural pode receber uma coleção de padrões de entrada com a categoria à qual cada padrão particular pertence. Depois, pode-se apresentar um novo padrão ainda desconhecido e apresenta-lo a rede, e a tarefa dela é classificar este novo padrão corretamente. Este tipo de classificação pode ser resolvido por um aprendizado supervisionado. A vantagem de usar uma rede neural para realizar a classificação de padrões é que ela pode construir fronteiras de decisões não lineares entre as diferentes classes e oferecer um método prático para resolver problemas altamente complexos de classificação de padrões. Há também uma importante função para o aprendizado não supervisionado na classificação de padrões, especialmente quando não há um conhecimento a priori das categorias em que os padrões serão classificados. É interessante diferenciar Agrupamento de Classificação: agrupamento é o processo de agrupar amostras de entradas que são vizinhos espaciais enquanto classificação consiste na rotulação de amostras de entrada através de algum critério externo (Nievola, 1996). É certo que para que o processo de classificação de padrões tenha sucesso é necessário que exista o mapeamento dos padrões de entrada em um espaço de classificação. Este espaço é definido por regiões de decisão que separam os padrões, atribuindo cada padrão em uma classe.

Neste trabalho o objetivo foi de utilizar a computação neural para construir um modelo de classificação, no qual pudesse prever dado que não se conhece o paciente, a qual classe ele pertenceria (Normal, Hérnia do disco ou Espondilolistese), através das 6 variáveis observadas.

3.2 Computação Neural

Em geral, as redes neurais são os modelos matemáticos representados por uma coleção de unidades computacionais simples interligadas por um sistema de conexões. O número de unidades pode ser muito grande e as conexões intrincadas. Em geral, as redes neurais são (os modelos matemáticos representados por) uma coleção de unidades computacionais simples interligadas por um sistema de conexões. O número de unidades pode ser muito grande e as conexões intrincadas.
Redes neurais constituem um campo da ciência da computação ligado à inteligência artificial, buscando implementar modelos matemáticos que se assemelhem às estruturas neurais biológicas. Nesse sentido, apresentam capacidade de adaptar os seus parâmetros como resultado da interação com o meio externo, melhorando gradativamente o seu desempenho na solução de um determinado problema. Sabe-se que o cérebro é composto de bilhões de neurônios. Um neurônio é uma célula formada por três seções com funções específicas e complementares: corpo, dendritos e axônio. Os dendritos captam os estímulos recebidos em um determinado período de tempo e os transmitem ao corpo do neurônio, onde são processados. Quando tais estímulos atingirem determinado limite, o corpo da célula envia novo impulso que se propaga pelo axônio e é transmitido às células vizinhas por meio de sinapses. Este processo pode se repetir em várias camadas de neurônios. Como resultado, a informação de entrada é processada, podendo levar o cérebro a comandar reações físicas.
A busca por um modelo computacional que simule o funcionamento das células do cérebro data dos anos 40, com o trabalho de McCulloch e Pitts (1943). O entusiasmo pela pesquisa neste campo cresceu durante os anos 50 e 60. Nesse período, Rosenblatt (1958) propôs um método inovador de aprendizagem para as redes neurais artificiais denominado perceptron. Até 1969, muitos trabalhos foram realizados utilizando o perceptron como modelo. No final dos anos 60, Minsky e Pappert (1969) publicam um livro no qual apresentam importantes limitações do perceptron. As dificuldades metodológicas e tecnológicas, juntamente com os ataques extremamente pessimistas de Papert e Minsky, fizeram com que as pesquisas arrefecessem nos anos seguintes. Durante os anos 70, a pesquisa contava apenas com um número ínfimo de cientistas. Porém, durante os anos 80, o entusiasmo ressurge graças a avanços metodológicos importantes e ao aumento dos recursos computacionais disponíveis. O modelo de neurônio artificial da figura 1 é uma simplificação do modelo apresentado por Haykin (2001, p. 36).

Figura 1 - Modelo matemático de um neurônio

“Figura 1 - Modelo matemático de um neurônio”

Este modelo é composto por três elementos básicos: . um conjunto de n conexões de entrada (x1 , x2 , …, xn ), caracterizadas por pesos (p1 , p2 , …, pn ); . um somador (\(\sum\)) para acumular os sinais de entrada; . uma função de ativação (\(\phi\)) que limita o intervalo permissível de amplitude do sinal de saída (y) a um valor fixo. O comportamento das conexões entre os neurônios é simulado por meio de seus pesos. Os valores de tais pesos podem ser negativos ou positivos, dependendo de as conexões serem inibitórias ou excitatórias. O efeito de um sinal proveniente de um outro neurônio é determinado pela multiplicação do valor (intensidade) do sinal recebido pelo peso da conexão correspondente (\(xi * pi\)). É efetuada a soma dos valores \(xi * pi\) de todas as conexões, e o valor resultante é enviado para a função de ativação, que define a saída (y) do neurônio. Combinando diversos neurônios, forma-se uma rede neural artificial. As redes neurais artificiais são modelos que buscam simular o processamento de informação do cérebro humano. São compostas por unidades de processamentos simples, os neurônios, que se unem por meio de conexões sinápticas. De uma forma simplificada, uma rede neural artificial pode ser vista como um grafo onde os nós são os neurônios e as ligações fazem a função das sinapses, como exemplificado na figura 2.

Figura 2 - Representação simplificada de uma rede neural artificial

“Figura 2 - Representação simplificada de uma rede neural artificial”

As redes neurais artificiais se diferenciam pela sua arquitetura e pela forma como os pesos associados às conexões são ajustados durante o processo de aprendizado. A arquitetura de uma rede neural restringe o tipo de problema no qual a rede poderá ser utilizada, e é definida pelo número de camadas (camada única ou múltiplas camadas), pelo número de nós em cada camada, pelo tipo de conexão entre os nós (feedforward ou feedback) e por sua topologia (HAYKIN, 2001, p. 46-49). Uma das propriedades mais importantes de uma rede neural artificial é a capacidade de aprender por intermédio de exemplos e fazer inferências sobre o que aprendeu, melhorando gradativamente o seu desempenho. As redes neurais utilizam um algoritmo de aprendizagem cuja tarefa é ajustar os pesos de suas conexões (BRAGA; CARVALHO; LUDEMIR, 2000, cap. 2). Existem duas formas básicas de aprendizado de redes neurais: aprendizado supervisionado e aprendizado não supervisionado. No aprendizado supervisionado, um agente externo (professor) apresenta à rede neural alguns conjuntos de padrões de entrada e seus correspondentes padrões de saída. Portanto, é necessário ter um conhecimento prévio do comportamento que se deseja ou se espera da rede. Para cada entrada, o professor indica explicitamente se a resposta calculada é boa ou ruim. A resposta fornecida pela rede neural é comparada à resposta esperada. O erro verificado é informado à rede para que sejam feitos ajustes a fim de melhorar suas futuras respostas. Na aprendizagem não supervisionada, ou aprendizado auto-supervisionado, não existe um agente externo para acompanhar o processo de aprendizado. Neste tipo de aprendizagem, somente os padrões de entrada estão disponíveis para a rede neural. A rede processa as entradas e, detectando suas regularidades, tenta progressivamente estabelecer representações internas para codificar características e classificá-las automaticamente. Este tipo de aprendizado só é possível quando existe redundância nos dados de entrada, para que se consiga encontrar padrões em tais dados.

4 Resultados e discussões

4.1 Simulação de dados

Para efeito de melhor visualização e entendimento do problema de classificação, foi simulado um banco de dados no R contendo 20 observações, 2 variáveis e 3 classes. O intuito foi de utilizar a rede neural para classificar a observação corretamente levando em consideração suas características (as 2 variáveis). Para isso, o banco de dados é dividido em 2 partes: uma de treino e uma de teste. Não existe uma regra, mas costuma-se dividi-lo em 70% para treino e 30% para teste. Essa parcela destinada para treino é utilizada na implementação da rede como parâmetro de entrada e servirá como base para as próximas predições que serão realizadas. Então, a parcela do banco de dados separada para teste, é classificada pela rede neural. Para saber o quanto o classificador está acertando, ou seja, o quão eficiente ele é, calcula-se a chamada “matriz de classificação”. Uma matriz de classificação é criada classificando-se todos os casos do modelo em categorias, determinando se o valor previsto correspondeu ao valor real. Todos os casos em cada categoria são contabilizados e os totais são exibidos na matriz. A matriz de classificação é uma ferramenta padrão para avaliação de modelos estatísticos e é muitas vezes chamada de matriz de confusão. Uma matriz de classificação é uma ferramenta importante para avaliar os resultados de previsão porque facilita o entendimento e reage aos efeitos de previsões erradas. Ao exibir a quantidade e os percentuais em cada célula desta matriz, você pode consultar rapidamente com que frequência o modelo é previsto com precisão.
Para um entendimento mais rápido, calcula-se o que se chama de “acurácia”. Essa medida é obtida dividindo-se o total de acertos do modelo, ou seja, a diagonal principal da matriz de classificação pelo total de dados que seu conjunto possui. A acurácia nos retorna a proporção de predições corretas, isto é, quantos por cento (%) seu modelo está acertando, classificando as observações corretamente.

# Classificação Não Linear Múltipla com 3-Classes
#----------------------------------------------------------------
#
# Simula os dados
#
N <- 20 
x1max <- 5; x2max <- 25
x1 <- runif(N,0,x1max)
x2 <- runif(N,0,x2max)
y <- rep(NA,N);yn <- rep(NA,N)
for(n in 1:N){
if(x2[n]<=x1[n]^2){y[n] <- "C1";yn[n] <- 1
}else{
if(x2[n]>(x1[n]-5)^2){y[n] <- "C3";yn[n] <- 3
}else{
y[n] <- "C2";yn[n] <- 2
}
}
}
aux <- data.frame(x1,x2,y,yn)
dados <- rbind(subset(aux,subset=(yn==1)),subset(aux,subset=(yn==2)),subset(aux,subset=(yn==3)))
rownames(dados) <- 1:N
colnames(dados) <- c("x1","x2","y","yn")
dados
##            x1          x2  y yn
## 1  4.44290878  9.63695626 C1  1
## 2  4.56101014 19.27494472 C1  1
## 3  2.21969132  0.03628503 C1  1
## 4  3.33650175  3.49235336 C1  1
## 5  4.60374948 13.46004588 C1  1
## 6  4.74381595  2.52892635 C1  1
## 7  2.65780192  4.62885731 C1  1
## 8  0.21889233 10.19713147 C2  2
## 9  0.36958512  0.37138448 C2  2
## 10 0.49262902 19.61791111 C2  2
## 11 0.80797744 17.27636321 C2  2
## 12 0.03137294 11.16161409 C2  2
## 13 1.88226265  7.87256928 C2  2
## 14 0.71818877 11.67102826 C2  2
## 15 2.65164751 20.49031840 C3  3
## 16 2.77047398 15.77946864 C3  3
## 17 4.15065513 21.77270940 C3  3
## 18 2.28272401 20.02580445 C3  3
## 19 0.39148201 23.05456420 C3  3
## 20 2.65753139 14.41623978 C3  3
#----------------------------------------------------------------
#
# Aleatoriza a ordem dos dados simulados
#
aux <- sample(1:N,N,replace=FALSE,prob=rep(1/N,N))
aux
##  [1]  5 20 11 10 12  7 16  9 13  2 14 15  6  4 18  3  1 19  8 17
dados <- dados[aux,]
rownames(dados) <- 1:N # APENAS PARA REINDEXAR OS ÍNDICES DAS LINHAS PARA 1, 2,..., 20 !!!!
#----------------------------------------------------------------
#
# Plota os dados simulados
var.x1 <- seq(0,5,0.1)
var.y <- var.x1^(2)
plot(var.x1,var.y,type="l",xlim=c(0,5),ylim=c(0,25),xlab="x1",ylab="x2",col="blue")
curve((x-5)^(2),0,2.5,col="blue",add=TRUE)
abline(h=c(0,25));abline(v=c(0,5))
points(dados$x1,dados$x2,pch=dados$yn)
#----------------------------------------------------------------
#----------------------------------------------------------------
library("neuralnet") # Carrega o pacote neuralnet
## Warning: package 'neuralnet' was built under R version 3.4.2
#----------------------------------------------------------------
#
# Separação dos dados em treinamento e teste, usando a regra prática 70%/30%
#
df.dados <- dados[,1:3]
df.dados
##            x1          x2  y
## 1  4.60374948 13.46004588 C1
## 2  2.65753139 14.41623978 C3
## 3  0.80797744 17.27636321 C2
## 4  0.49262902 19.61791111 C2
## 5  0.03137294 11.16161409 C2
## 6  2.65780192  4.62885731 C1
## 7  2.77047398 15.77946864 C3
## 8  0.36958512  0.37138448 C2
## 9  1.88226265  7.87256928 C2
## 10 4.56101014 19.27494472 C1
## 11 0.71818877 11.67102826 C2
## 12 2.65164751 20.49031840 C3
## 13 4.74381595  2.52892635 C1
## 14 3.33650175  3.49235336 C1
## 15 2.28272401 20.02580445 C3
## 16 2.21969132  0.03628503 C1
## 17 4.44290878  9.63695626 C1
## 18 0.39148201 23.05456420 C3
## 19 0.21889233 10.19713147 C2
## 20 4.15065513 21.77270940 C3
alvo <- model.matrix(~ y - 1, data=df.dados)
colnames(alvo) <- c("c1","c2","c3")
M <- floor(0.7*N)
index <- sample(1:N,M)
index # índices dos dados de treino
##  [1] 14 10  3  6 20 19  2 12  9 11 17  4  5 13
(1:N)[-index] # índices dos dados de teste
## [1]  1  7  8 15 16 18
treino <- df.dados[index,1:2]
teste <- df.dados[-index,1:2]
minimo.treino <- apply(treino,2,min)
alcance.treino <- apply(treino,2,max)-apply(treino,2,min)
minimo.teste <- apply(teste,2,min)
alcance.teste <- apply(teste,2,max)-apply(teste,2,min)
treino.escalado <- cbind(scale(treino,minimo.treino,alcance.treino),alvo[index,])
teste.escalado <- cbind(scale(teste,minimo.teste,alcance.teste),alvo[-index,])
#----------------------------------------------------------------
#
# Visualização dos dados escalados (treinamento e teste) e medidas resumo
#
treino.escalado
##            x1         x2 c1 c2 c3
## 14 0.70136208 0.05006433  1  0  0
## 10 0.96120785 0.87020407  1  0  0
## 3  0.16479870 0.76634811  0  1  0
## 6  0.55733915 0.10912256  1  0  0
## 20 0.87412881 1.00000000  0  0  1
## 19 0.03979239 0.39847701  0  1  0
## 2  0.55728174 0.61772227  0  0  1
## 12 0.55603316 0.93336076  0  0  1
## 9  0.39276649 0.27768152  0  1  0
## 11 0.14574517 0.47506781  0  1  0
## 17 0.93614625 0.36936760  1  0  0
## 4  0.09788046 0.88802626  0  1  0
## 5  0.00000000 0.44859619  0  1  0
## 13 1.00000000 0.00000000  1  0  0

summary(treino.escalado)
##        x1               x2               c1               c2        
##  Min.   :0.0000   Min.   :0.0000   Min.   :0.0000   Min.   :0.0000  
##  1st Qu.:0.1505   1st Qu.:0.3006   1st Qu.:0.0000   1st Qu.:0.0000  
##  Median :0.5567   Median :0.4618   Median :0.0000   Median :0.0000  
##  Mean   :0.4989   Mean   :0.5146   Mean   :0.3571   Mean   :0.4286  
##  3rd Qu.:0.8309   3rd Qu.:0.8442   3rd Qu.:1.0000   3rd Qu.:1.0000  
##  Max.   :1.0000   Max.   :1.0000   Max.   :1.0000   Max.   :1.0000  
##        c3        
##  Min.   :0.0000  
##  1st Qu.:0.0000  
##  Median :0.0000  
##  Mean   :0.2143  
##  3rd Qu.:0.0000  
##  Max.   :1.0000
teste.escalado
##            x1         x2 c1 c2 c3
## 1  1.00000000 0.58317830  1  0  0
## 7  0.56702779 0.68394268  0  0  1
## 8  0.00000000 0.01455797  0  1  0
## 15 0.45183388 0.86841937  0  0  1
## 16 0.43694719 0.00000000  1  0  0
## 18 0.00517148 1.00000000  0  0  1
summary(teste.escalado)
##        x1               x2               c1               c2        
##  Min.   :0.0000   Min.   :0.0000   Min.   :0.0000   Min.   :0.0000  
##  1st Qu.:0.1131   1st Qu.:0.1567   1st Qu.:0.0000   1st Qu.:0.0000  
##  Median :0.4444   Median :0.6336   Median :0.0000   Median :0.0000  
##  Mean   :0.4102   Mean   :0.5250   Mean   :0.3333   Mean   :0.1667  
##  3rd Qu.:0.5382   3rd Qu.:0.8223   3rd Qu.:0.7500   3rd Qu.:0.0000  
##  Max.   :1.0000   Max.   :1.0000   Max.   :1.0000   Max.   :1.0000  
##        c3     
##  Min.   :0.0  
##  1st Qu.:0.0  
##  Median :0.5  
##  Mean   :0.5  
##  3rd Qu.:1.0  
##  Max.   :1.0

#----------------------------------------------------------------
#
# Modelo neural para classificação não linear múltipla com 3-Classes
#
nn.dados <- neuralnet(c1+c2+c3 ~ x1+x2,data=treino.escalado,hidden=c(4),err.fct="sse",act.fct="logistic",linear.output=FALSE)
valores.preditos <- compute(nn.dados,teste.escalado[,1:2])
y.predito <- apply(valores.preditos$net.result,1,which.max)
y.verdadeiro <- apply(teste.escalado[,3:5],1,which.max)
matriz.confusao <- table(y.verdadeiro,y.predito)
acuracia <- sum(diag(matriz.confusao))/sum(matriz.confusao)
print(matriz.confusao)
##             y.predito
## y.verdadeiro 1 2 3
##            1 2 0 0
##            2 0 1 0
##            3 0 1 2
y.predito
##  1  7  8 15 16 18 
##  1  3  2  3  1  2
y.verdadeiro
##  1  7  8 15 16 18 
##  1  3  2  3  1  3
print(paste("Acuracia:",acuracia))
## [1] "Acuracia: 0.833333333333333"


cbind(df.dados[-index,1:2],alvo[-index,],y.verdadeiro,y.predito)[which(y.verdadeiro!=y.predito),]
##              x1         x2 c1 c2 c3 y.verdadeiro y.predito
## 18 0.3914820135 23.0545642  0  0  1            3         2

#----------------------------------------------------------------
#
# Gráficos
#
# Mostra os DADOS classificados erroneamente COMO um triângulo vermelho apontando para baixo
#
points(df.dados[-index,1:2][which(y.verdadeiro!=y.predito),],pch=25,col="red")

A figura 3 abaixo corresponde a rede neural que foi gerada para classificar esses dados simulados.

Figura 3: Rede neural dos dados simulados

“Figura 3: Rede neural dos dados simulados”

4.2 Aplicação real

Com base nas informações já citadas na simulação de dados, foi criada uma rede para ser aplicada em um banco de dados real. O banco de dados utilizado contém 310 dados, sendo classificados em 3 classes, a partir de 6 variáveis. Para a divisão dos dados de treino e teste foi usada a regra usual 70/30, foram separados 217 dados para treino e 93 dados para teste. Esses dados foram utilizados para a construção da nova rede, que foi construída com 6 neurônios (3 na primeira camada oculta e 3 na segunda camada oculta).


library(foreign)
column3Cweka = read.arff(file.choose())
head(column3Cweka)
##   pelvic_incidence  pelvic_tilt lumbar_lordosis_angle sacral_slope
## 1      63.02781750 22.552585970           39.60911701  40.47523153
## 2      39.05695098 10.060991470           25.01537822  28.99595951
## 3      68.83202098 22.218482050           50.09219357  46.61353893
## 4      69.29700807 24.652877910           44.31123813  44.64413017
## 5      49.71285934  9.652074879           28.31740600  40.06078446
## 6      40.25019968 13.921906580           25.12494960  26.32829311
##   pelvic_radius degree_spondylolisthesis  class
## 1   98.67291675             -0.254399986 Hernia
## 2  114.40542540              4.564258645 Hernia
## 3  105.98513550             -3.530317314 Hernia
## 4  101.86849510             11.211523440 Hernia
## 5  108.16872490              7.918500615 Hernia
## 6  130.32787130              2.230651729 Hernia

summary(column3Cweka)
##  pelvic_incidence     pelvic_tilt        lumbar_lordosis_angle
##  Min.   : 26.14792   Min.   :-6.554948   Min.   : 14.00000    
##  1st Qu.: 46.43029   1st Qu.:10.667069   1st Qu.: 37.00000    
##  Median : 58.69104   Median :16.357689   Median : 49.56240    
##  Mean   : 60.49665   Mean   :17.542822   Mean   : 51.93093    
##  3rd Qu.: 72.87770   3rd Qu.:22.120395   3rd Qu.: 63.00000    
##  Max.   :129.83404   Max.   :49.431864   Max.   :125.74239    
##   sacral_slope       pelvic_radius       degree_spondylolisthesis
##  Min.   : 13.36693   Min.   : 70.08257   Min.   :-11.058179      
##  1st Qu.: 33.34712   1st Qu.:110.70920   1st Qu.:  1.603727      
##  Median : 42.40491   Median :118.26818   Median : 11.767934      
##  Mean   : 42.95383   Mean   :117.92066   Mean   : 26.296694      
##  3rd Qu.: 52.69589   3rd Qu.:125.46767   3rd Qu.: 41.287352      
##  Max.   :121.42957   Max.   :163.07104   Max.   :418.543082      
##                class    
##  Hernia           : 60  
##  Normal           :100  
##  Spondylolisthesis:150  
##                         
##                         
## 
dim(column3Cweka)
## [1] 310   7
#----------------------------------------------------------------
library("MASS")
library("neuralnet")
library("nnet")
## Warning: package 'nnet' was built under R version 3.4.2
#--------------------------------------------------------

set.seed(101) # fixa a semente aleatoria
index <- sample(1:nrow(column3Cweka),217)
treino <- column3Cweka[index,1:7]
teste <- column3Cweka[-index,1:7]
treinos <-cbind(treino[,1:6],class.ind(treino$class))
testes <- cbind(teste[,1:6],class.ind(teste$class))
set.seed(102) # fixa a semente aleatoria
rede <- neuralnet(Normal + Hernia + Spondylolisthesis ~pelvic_incidence+pelvic_tilt+lumbar_lordosis_angle+sacral_slope+pelvic_radius+degree_spondylolisthesis,data=treinos,hidden=c(3,3),err.fct="sse",act.fct="logistic",linear.output=FALSE)
plot(rede)
#################### 
predictions <- compute(rede,testes[,1:6])

y.predito <- apply(predictions$net.result,1,which.max)
y.verdadeiro <- apply(testes[,7:9],1,which.max)

matriz.confusao <- table(y.verdadeiro,y.predito)
matriz.confusao
##             y.predito
## y.verdadeiro  1  2  3
##            1 17  2  3
##            2 19  2  0
##            3  2  0 48
acuracia <- sum(diag(matriz.confusao))/sum(matriz.confusao)
acuracia
## [1] 0.7204301075


print(paste("Acuracia:",acuracia))
## [1] "Acuracia: 0.720430107526882"

#################

Para saber o acerto do classificador, foi calculada a matriz de confusão. A primeira vista essa matriz retorna algo que não seria esperado, pois na segunda classe retornou poucos acertos, mas analisando os dados pode-se entender esse fator, as classes Normal (1) e Espondilolistese (3), apresentam 100 e 150 pacientes, respectivamente, já a classe Hérnia do disco (2) apresenta somente 60 pacientes, pode-se dizer que os dados de teste podem não ter selecionado um número considerável de dados da classe 2, assim a matriz de confusão não apresenta o melhor resultado, da mesma forma que a acurácia. Levando em consideração essa quantidade muito inferior em relação às demais classes, é possível que a amostra de dados selecionada para teste não contenha ou contenha poucas observações que pertencem a essa classe, dificultando a predição do modelo.
E por meio da matriz de confusão foi calculada a acurácia, que para esses dados resultou em 72,04%. Por meio disso, pode-se perceber que o acerto não é tão grande, mas existe uma margem de erro.

Figura 4: Rede Neural

“Figura 4: Rede Neural”

Como pode ser visto na figura 4, essa foi a rede neural gerada que fez a classificação dos dados.

5 Conclusão

Neste trabalho foi feito o uso de redes neurais artificiais (RNA) para resolver um problema de classificação. A precisão do classificador não foi tão boa porque provavelmente a amostra selecionada continha poucos dados referentes à classe 2 (Hérnia do disco), por conta disso houve um erro maior na predição dessa classe.
No entanto, atingimos o objetivo proposto. As redes neurais artificiais são ferramentas muito úteis para analisar problemas que utilizam classificação. Observou-se a eficiência desse método.
Este trabalho foi muito importante para o conhecimento e aprofundamento desta técnica, uma vez que permitiu o desenvolvimento de uma rede neural em uma aplicação real e aperfeiçoou competências de análise e tratamento de dados.