Skip to content
Gislaine Martins edited this page Sep 4, 2024 · 104 revisions

Students Performance Dataset - Wiki

Descrição do Projeto de Análise de Dados

Título: Análise e Classificação de Dados Students Performance

Introdução

Este projeto foi desenvolvido com o objetivo de responder à pergunta: Qual será a classificação de nota (GradeClass) de um aluno novo, dado seu perfil (por exemplo, idade, tempo de estudo semanal, faltas, etc.)? Utilizando um modelo de classificação. Os dados foram retirados da plataforma Kaggle, um repositório popular de datasets para análise de dados e aprendizado de máquina.

Variaveis presentes no dataset:

  • StudentID(EstudantesID): Indentificador exclusivo para cada aluno (1001 a 3392)

  • Detalhes demograficos

    • Age/IDADE: A idade dos alunos variam de 15 a 18 anos
    • Gender/Genero: Masculino e Feminino
    • Ethnicity/Etinia: Tipos de etinia: Caucasian, African American, Asian, Other
    • ParentalEducation/nivelEscolaridadePais: Nível de escolaridade dos pais, codificado da seguinte forma:
      • None/nao tem
      • High School/Ensino medio
      • Some College/Alguma faculdade
      • Bachelor's/Bacharelado
      • Higher/Mais alto
  • Habitos de estudo

    • StudyTimeWeekly: tempo de estudo semanal em horas
    • Absences: Número de faltas durante o ano letivo, variando de 0 a 30.
    • Tutoring: Status da tutoria, onde 0 indica Não e 1 indica Sim.
  • Envolvimento Parental

    • ParentalSupport: nivel de apoio da familia
      • Nenhum
      • Baixo
      • Moderado
      • Alto
      • Muito Alto
  • Atividades extrcurriculares

    • Extracurricular: Participação em atividades extracurriculares
    • Sports: participação em esportes
    • Music: participação em atividades musicais
    • Volunteering: possui particiação voluntária
  • Performance academica

    • GPA: media de pontuação em uma escala de 2,0 a 4,0, influenciada por hábitos de estudo, envolvimento dos pais e atividades extracurriculares.
  • Variável alvo: classe de notas(GradeClass)

  • GradeClass: Classificação das notas dos alunos com base no GPA:

    • 0: 'A' (GPA >= 3,5)
    • 1: 'B' (3,0 <= GPA <3,5)
    • 2: 'C' (2,5 <= GPA <3,0)
    • 3: 'D' (2,0 <= GPA <2,5)
    • 4: 'F' (GPA <2,0)

Pergunta de Pesquisa

A pergunta que buscamos responder neste projeto é: Qual será a classificação de nota (GradeClass) de um aluno novo, dado seu perfil (por exemplo, idade, tempo de estudo semanal, faltas, etc.)?

Instalação de bibliotecas

Para fazer a instalação das bibliotecas foi necessário utilizar os seguintes comandos:

install.packages("class")
install.packages("corrplot")
install.packages("caret")
install.packages("C50")
install.packages("e1071")
install.packages("kernlab")
install.packages("mlbench")

Utilização das bibliotecas:

library(ggplot2) # visualização dos dados 
library(dplyr) # Usado para as funções de filtro e tratamento de dados
library(reshape2) # Converter a matriz de correlação em um data frame
library(caret) # Usada para usar a função createDataPartition (partição dos dados)
library(corrplot) # Visualizar as variaveis correlacionadas
library(C50) # pacote para arvore de binaria (classificação)
library(class)# pacote para modelo KNN 
library(e1071) # pacote para modelo  naiveBayes
library(kernlab) # pacote para modelo  SVM
library(mlbench) # pacote para modelo  SVM

Metodologia

1) Coleta de Dados: Carregando os dados do arquivo do excel.

tabela = read.table("Student_performance_data.csv", sep = ";", dec = ",", header = TRUE)

2) Análise Exploratória dos Dados (EDA):

  • Resumo estatisticos dos dados
summary(tabela)

Resumo dos dados

  • Visualização dos dados Visualização dados

Através do resumo estatístico é possível perceber que:

  • idade: apesar de os alunos estarem entre 15 e 18 anos a média é 16
  • A média do nível de educação dos pais é 1.74. Isso significa que todos possui ensino médio.
  • A mediana é 2 que significa que os pais possuem também alguma faculdade. É possível perceber também que mais de 75% possui alguma faculdade, pois o nível 2 esta concentrado no terceiro quartil.
  • As variáveis StudyTimeWeekly, GPA e GradeClass possuem valores muito discrepantes. O que pode ser necessário uma normalização das variáveis
  • A variável Absences possui muitos números aleatórios. Isso poderia ser resolvido com uma escala de notas.
  • A média de faltas é muita alta. Pois, 75% dos alunos tiveram 22 faltas

3) Pré-processamento dos Dados:
Para entender melhor a distribuição dos dados. Alguns passos serão seguidos nessa etapa.

  1. Identificar as variáveis numéricas e categóricas na base de dados
str(tabela)

Função str

É possível perceber que as variaveis: StudyTimeWeekly, GPA e GradeClass são do tipo caracter e as demais são do tipo inteiros

  1. Transformar as variáveis de caracteres para numéricas.
    2.1) StudyTimeWeekly
    Verificando valores únicos para entender melhor a natureza dos dados e identificar padrões de formatação ou possíveis erros nos dados. Utilizaremos a função unique.
unique(tabela$StudyTimeWeekly)

Limpeza dos dados
Remover pontos e transformar para numéricos.

tabela$StudyTimeWeekly <- gsub("\\.", "", tabela$StudyTimeWeekly) # Remove os pontos
tabela$StudyTimeWeekly <- as.numeric(tabela$StudyTimeWeekly) # Converte para numérico

Verificar e validar os dados
Verificar se a conversão foi bem sucedida

  summary(tabela$StudyTimeWeekly)  # Resumo estatístico da variavel

Observando o resultado é possível observar que os valores são extremamente grandes. Sendo assim, será necessário fazer uma normalização para ajustar os valores para um intervalo especifico. Neste caso será feito um Escalamento Logarítmico pois os dados seguem uma distribuição exponencial que pode ser útil para reduzir a dispersão.

Aplicar escalamento logarítmico à coluna StudyTimeWeekly

tabela$StudyTimeWeekly_log_scaled <- log(tabela$StudyTimeWeekly)

Visualizando o boxplot da variavel StudyTimeWeekly

ggplot(tabela, aes(y = StudyTimeWeekly_log_scaled)) +
  geom_boxplot() +
  labs(title = "StudyTimeWeekly", y = "") +
  theme(plot.title = element_text(hjust = 0.5))  

StudyTimeWeekly-boxplot

2.2) GPA
Verificando valores únicos

unique(tabela$GPA)

Limpeza dos dados
Remover pontos e transformar para numéricos

tabela$GPA <- gsub("\\.", "", tabela$GPA) # Remove os pontos
tabela$GPA <- as.numeric(tabela$GPA) # Converte para numérico

Verificar e validar os dados
Verificar se a conversão foi bem sucedida

  summary(tabela$GPA)  # Resumo estatístico da variavel

Aplicar escalamento logarítmico à coluna GPA

tabela$GPA_log_scaled <- log(tabela$GPA)

Visualizando o boxplot da variavel GPA

ggplot(tabela, aes(y = GPA_log_scaled)) +
  geom_boxplot() +
  labs(title = "GPA", y = "") +
  theme(plot.title = element_text(hjust = 0.5)) 

StudyTimeWeekly-boxplot

Verificar resumo dos valores de GPA

summary(tabela$GPA_log_scaled)

É possível perceber que a média apresentou valor -inf. Isso significa que a presença desses valores afetou o calculo da media.

Resolver o Problema com Valores -Inf
Identificar os índices onde os valores são -Inf

indices_inf <- which(is.infinite(tabela$GPA_log_scaled))

Exibir os índices ou valores problemáticos

tabela$GPA_log_scaled[indices_inf]

Filtrando os valores -Inf

tabela_inf <- tabela %>%
  filter(is.infinite(GPA_log_scaled))

Exibir o resultado

print(tabela_inf)

numero inf

É possível perceber que somente 16 linhas contem o valor -Inf. Sendo assim, será necessário excluir esses valores.

Remover valores -Inf na coluna GPA_log_scaled

tabela_filtrada <- tabela %>%
  filter(!is.infinite(GPA_log_scaled))

Removendo a coluna GPA

nova_tabela <- tabela_filtrada %>%
  select(-GPA)

Removendo a coluna StudyTimeWeekly

nova_tabela <- nova_tabela %>%
  select(-StudyTimeWeekly)

Renomeando variavel GPA_log_scaled

nova_tabela <- nova_tabela %>%
  rename(GPA = GPA_log_scaled)

Renomeando variável StudyTimeWeekly

nova_tabela <- nova_tabela %>%
  rename(StudyTimeWeekly = StudyTimeWeekly_log_scaled)

Como não vamos precisar do ID dos estudantes, também será removido da base de dados
Removendo a coluna StudentID

nova_tabela <- nova_tabela %>%
  select(-StudentID)

2.3) GradeClass
Convertendo a coluna GradeClass para formato numérico

nova_tabela$GradeClass <- as.numeric(nova_tabela$GradeClass)

Verificar quantos valores foram convertidos para NA

sum(is.na(nova_tabela$GradeClass))

Verificar estatísticas descritivas

summary(nova_tabela$GradeClass)

summary grade_class

  1. Análise de Correlação.
    Verificar as variáveis correlacionada
correlation_matrix <- cor(nova_tabela)

Converter a matriz de correlação em um data frame

melted_correlation_matrix <- melt(correlation_matrix)

Transformar em formato de dados para visualização

melted_cor_matrix <- melt(cor_matrix)

Visualização de correlação entre as variáveis

library(ggplot2) # utilização da biblioteca de visualização
ggplot(data = melted_cor_matrix, aes(x = Var1, y = Var2, fill = value)) +
  geom_tile() +
  scale_fill_gradient2(low = "blue", high = "red", mid = "white", midpoint = 0,
                       limit = c(-1, 1), name = "Correlação") +
  labs(title = "Matriz de Correlação") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1, margin = margin(t = 0.6, r = 0, b = 0, l = 0)),
        axis.text.y = element_text(margin = margin(t = 0.6, r = 0, b = 0, l = 0))) +
  coord_fixed()

StudyTimeWeekly-boxplot

Como podemos observar no gráfico acima, podemos observar que a variavel GradeClass é a mais correlacionada com o GPA em relação a outras variáveis.

4) Modelagem e Treinamento:
Divisão dos dados em conjuntos de treino e teste

Definindo a proporção de divisão

set.seed(123)  # Definindo uma seed para reprodutibilidade
proporcao_treino <- 0.8

Criando uma partição estratégica

indice_treino <- createDataPartition(nova_tabela$GradeClass, p = proporcao_treino, list = FALSE)

Criando conjuntos de treinamento e teste

dados_treino <- nova_tabela[indice_treino, ]
dados_teste <- nova_tabela[-indice_treino, ]

Nessa próxima etapa é importante utilizar mais de um modelo de classificação para fazer a comparação. Sendo assim, foi escolhido os seguintes modelos: Árvore de classificação, KNN (K-Nearest Neighbours), Bayes (Naïve Bayes), SVM (Support Vector Machine)

4.1) Classificação
Separar as variáveis preditoras e a variável de resposta

Identificar o índice da coluna de resposta

response_col_index <- which(colnames(nova_tabela) == "GradeClass")

Separar as variáveis preditoras e a variável de resposta para os dados de treino

train_target <- dados_treino[, response_col_index] # Variável de resposta
train_features <- dados_treino[, -response_col_index] # Variáveis preditoras

Separar as variáveis preditoras e a variável de resposta para os dados de teste

test_target <- dados_teste[, response_col_index] # Variável de resposta
test_features <- dados_teste[, -response_col_index] # Variáveis preditoras

No R, um fator é usado para representar variáveis categóricas. Sendo assim, é necessario garantir que a variável de resposta seja tratada como um fator.

Convertendo a variável de resposta para fator

train_target <- factor(dados_treino[, response_col_index])
test_target <- factor(dados_teste[, response_col_index])

Criar o modelo de Árvore de classificação

c50_model <- C5.0(train_features, train_target)

Fazer previsões nos dados de teste

predictions_c50 <- predict(c50_model, test_features)

Avaliar o modelo Árvore binária

# Avaliar o desempenho
confusion_matrix_c50 <- table(predictions_c50, test_target)

# Convertendo a matriz de confusão para um data frame no formato long
confusion_df_matrix_c50 <- as.data.frame(as.table(confusion_matrix_c50))

# Renomeando as colunas
colnames(confusion_df_matrix_c50) <- c("Predicted", "Actual", "Count")

# Visualização matriz confusão 
ggplot(confusion_df_matrix_c50, aes(x = Actual, y = Predicted, fill = Count)) +
  geom_tile() +
  scale_fill_gradient(low = "white", high = "blue") +
  geom_text(aes(label = Count), color = "black") +
  labs(title = "Matriz confusão Arvore binaria", x = "Actual", y = "Predicted") +
  theme_minimal()

Matriz confusao Arvore

accuracy_c50 <- sum(diag(confusion_matrix_c50)) / sum(confusion_matrix_c50)
print(paste("Acurácia arvore:", accuracy_c50 * 100))

Acuracia Arvore

4.2) KNN (K-Nearest Neighbours)

Separar as características (features) e o alvo (target)

train_x <- dados_treino[, -response_col_index]  # Todas as colunas exceto GradeClass
train_y <- dados_treino$GradeClass  # Apenas a coluna GradeClass
test_x <- dados_teste[, -response_col_index]  # Todas as colunas exceto GradeClass
test_y <- dados_teste$GradeClass  # Apenas a coluna GradeClass

Ajustar o modelo KNN

k <- 5
predict_knn <- knn(train = train_x, test = test_x, cl = train_y, k = k)

Avaliar o modelo

# Avaliar o modelo
confusion_matrix_knn <- table(Predicted = predict_knn, Actual = test_y)

# Convertendo a matriz de confusão para um data frame no formato long
confusion_df_matrix_knn <- as.data.frame(as.table(confusion_matrix_knn))

# Renomeando as colunas
colnames(confusion_df_matrix_knn) <- c("Predicted", "Actual", "Count")

# Visualização matriz confusão 
ggplot(confusion_df_matrix_knn, aes(x = Actual, y = Predicted, fill = Count)) +
  geom_tile() +
  scale_fill_gradient(low = "white", high = "blue") +
  geom_text(aes(label = Count), color = "black") +
  labs(title = "Matriz confusão KNN", x = "Actual", y = "Predicted") +
  theme_minimal()

Matriz confusao knn

# Acuracia modelo KNN
accuracy_knn <- sum(diag(confusion_matrix_knn)) / sum(confusion_matrix_knn)
print(paste("Acurácia:", accuracy_knn * 100))

Acuracia knn

4.3) Bayes (Naïve Bayes)

Ajustar o modelo Naive Bayes

model <- naiveBayes(GradeClass ~ ., data = dados_treino)

Fazer previsões

predictions_bayes <- predict(model, dados_teste)

Avaliar o modelo

# Avaliar o modelo
confusion_matrix_bayes <- table(dados_teste$GradeClass, predictions_bayes)

# Convertendo a matriz de confusão para um data frame no formato long
confusion_df_matrix_bayes <- as.data.frame(as.table(confusion_matrix_bayes))

# Renomeando as colunas
colnames(confusion_df_matrix_bayes) <- c("Predicted", "Actual", "Count")

# Visualização matriz confusão 
ggplot(confusion_df_matrix_bayes, aes(x = Actual, y = Predicted, fill = Count)) +
  geom_tile() +
  scale_fill_gradient(low = "white", high = "blue") +
  geom_text(aes(label = Count), color = "black") +
  labs(title = "Matriz confusão Bayes", x = "Actual", y = "Predicted") +
  theme_minimal()

Matriz Confusao bayes

#Acuracia bayes
accuracy_bayes <- sum(diag(confusion_matrix_bayes)) / sum(confusion_matrix_bayes)
print(paste("Acurácia bayes:", accuracy_bayes * 100))

Acuracia bayes

5) Avaliação do Modelo:

Grafico de comparacao

É possível perceber, segundo o gráfico, que o modelo de Árvore Binária apresentou a melhor acurácia, com um desempenho significativamente superior aos modelos k-NN e Bayes. Enquanto a Árvore Binária atingiu uma acurácia de aproximadamente 91,79%, os modelos k-NN e Bayes tiveram acurácias consideravelmente menores, em torno de 65,47% e 64,84%, respectivamente. Isso indica que, para este conjunto de dados, a Árvore Binária é a abordagem mais eficaz para a tarefa de classificação

Resultados

  • O modelo de classificação atingiu uma acurácia de 94% no conjunto de teste.
  • Observando a acurácia é possivel perceber que a proporção de previsões corretas feitas pelo modelo em relação ao total de previsões foi de quase 100%.
  • Ao inserir novos dados de novos alunos podemos concluir que o modelo será capaz de prever a classificação de alunos em grupos com 94% de acerto.

Futuras Direções

Para melhorar ainda mais este projeto, futuras análises podem incluir:

  • Outras métrica como precisão, Precisão, Recall, F1-Score, entre outras.