Inteligência artificial na educação

Como detectar se um aluno terá dificuldades no andamento de seu curso e interferir para ajudá-lo? Como conectar alunos de níveis semelhantes para que aprendam junto?

Desde que a Caelum decidiu enfrentar o desafio de criar uma plataforma online nos perguntamos como poder ajudar o aluno de maneiras diferentes. Desde então participamos de diversos cursos online nas mais variadas plataformas como os disponibilizados por Stanford através do Coursera.

Após estudar o curso de Machine Learning do instrutor Andrew Ng, um dos responsáveis pelo resultado de auto-detecção de faces e gatos do Google, participamos do Intelligent Tutor Systems 2012 na Grécia, onde discutimos abordagens de AI para a educação com equipes especializadas na área, em especial com desenvolvedores das plataformas de Carnegie Mellow e MIT.

Diversas das perguntas citadas anteriormente podem ser resolvidas com algoritmos de AI e muitas delas são utilizadas faz muito tempo.

Tomando como exemplo a deteção de aluno que está ficando atrasado no curso, temos os dados de quanto tempo cada aluno gasta para fazer um exercício:

Paulo: exercício 1, 12 minutos. exercício 2, 150 minutos. exercício 3, 3 minutos. exercicio 4, 15 minutos.
Ana: exercício 1, 4 minutos. exercício 2, 170 minutos. exercício 3, 32 minutos. exercicio 4, 25 minutos.
Maria: exercício 1, 1 minuto. exercício 2, 10 minutos. exercício 3, 3 minutos. exercicio 4, 25 minutos.
Carlos: exercício 1, 12 minutos. exercício 2, 20 minutos. exercício 3, 31 minutos. exercicio 4, 15 minutos.

E sabemos que o Paulo e a Ana demoraram mais do que o tempo desejado para obter aproveitamento máximo do conteúdo apresentado. Isto é, classificamos eles como sendo alunos que atrasaram mais de 3 meses e portanto não aproveitaram tanto o curso.

Podemos representar esses dados através de uma matriz onde cada linha é um aluno, as 4 primeiras colunas o tempo gasto. Em Ruby, teríamos algo como:

alunos = []
alunos << [12, 150, 3, 15]
alunos << [4, 170, 32, 25]
alunos << [1, 10, 3, 25]
alunos << [12, 20, 31, 15]

Podemos também definir zero como sendo a classificação de quem atrasou e gostaríamos de motivá-lo, e um como quem não atrasou. Como temos que os dois primeiros não atrasaram e os dois últimos atrasaram, podemos dar um label para cada um deles:

labels = [1, 1, 0, 0]

Note que cada aluno fez muito mais de 4 exercícios para acabar o curso, mas só estou analisando os 4 primeiros exercícios. Com essas informações e um novo aluno (Guilherme), como poderíamos dizer se o Guilherme terá dificuldades ou não? Existem diversos algoritmos e técnicas que podem ser utilizados. Nesse simples exemplo veremos a aplicação de Support Vector Machines através da libsvm em Ruby (o código original é em C e portanto para dezenas de diferentes linguagens):

require 'libsvm'
problem = Libsvm::Problem.new
problem.set_examples(labels, alunos.map {|ary| Libsvm::Node.features(ary) })

Configuramos os parâmetros do algoritmo, que no nosso caso não estudaremos mas em uma aplicação real é importante encontrar parâmetros que otimizem seu aprendizado:

parameter = Libsvm::SvmParameter.new
parameter.cache_size = 4
parameter.eps = 0.001
parameter.c = 1

Por fim, pedimos para o algoritmo ser treinado e criar um modelo de como os estudantes funcionam:

model = Libsvm::Model.train(problem, parameter)

E agora dado o Guilherme:

guilherme = [ 6, 140, 25, 10 ]

O algoritmo é capaz de prever:

prediction = model.predict(Libsvm::Node.features(guilherme))
puts prediction

E o resultado é 1, isto é, o Guilherme vai atrasar no curso e é importante avisá-lo para que não perca o ritmo. Claro, tudo isso aconteceu com uma base de dados muito pequena e irreal. Note que o segundo exercício é visualmente um indicador se o aluno vai ou não atrasar: acima de 100, todos atrasaram! O código Octave abaixo gera um gráfico que fica mais fácil visualizar:

X = [12,150,3,15,1;4,170,32,25,1;1,10,3,25,0;12,20,31,15,0];
y = [1 1 0 0]';
primeiro = X(:,1);
segundo = X(:,2);
terceiro = X(:,3);

plot3(primeiro, segundo, terceiro, '^');

O gráfico a seguir mostra essas três primeiras dimensões do exercício:

Já o gráfico a seguir tenta “reduzir” os 4 exercícios em 3 (usando PCA), para que possamos “visualizar” todos os 4 exercícios em 3 dimensões, para tentar detectar um padrão:

Pode ser que o algoritmo tenha pego essa regra, que até mesmo um ser humano detecta rapidamente. O que aconteceria com dados reais?

     2.81670     7.40000     0.63330     0
     0.55000    21.65000     4.76670     0
     1.25000    53.36670    43.05000     1
     1.20000    36.10000    12.00000     0
     0.83330   180.00000    22.41670     1
     1.06670   180.00000   180.00000     0
     1.33330    95.26670    42.83330     0
     2.06670   180.00000    23.13330     0
     5.51670   180.00000    10.78330     1
   180.00000   180.00000    12.65000     1

Esses são alguns dados reais de 3 exercícios de um curso. Note como não existe uma regra visual tão fácil que indique se o aluno terá ou não dificuldade para continuar o curso em um andamento bom para seu aprendizado:

O aluno [1.06670 180 180] demorou muito nos dois exercícios mas pode ser que ele fez uma viagem no fim de semana e por isso não respondeu naquela hora, mas mesmo assim conseguiu terminar o curso a tempo.

Treinando o SVM com C=0.08 o algoritmo é capaz de detectar um padrão muito mais complexo. Mas mesmo assim o algoritmo é capaz de prever com exatidão 86% dos casos.

C utilizado        ACERTOS NO TREINO    PREVISOES COM ACERTO
0.08	           93.18%	        85.71%

Por fim, ao fazer o fine tuning do algoritmo, encontramos funções capazes de detectar com muita exatidão se o aluno terá dificuldade em completar o curso a tempo.

C utilizado		ACERTOS NO TREINO	PREVISOES COM ACERTO
0.001			70.45454545454545	61.904761904761905
0.04			88.63636363636364	71.42857142857143
0.08			93.18181818181819	85.71428571428571
0.2			100.0			100.0

Essa implementação básica de SVM em Ruby é capaz de ir além prevendo o quão difícil será um exercício para um aluno, mas na prática utilizamos Octave, uma alternativa que balanceia melhor a simplifidade do código e o desempenho de algoritmos matemáticos como esse.

17 Comentários

  1. Bruno 11/07/2012 at 13:06 #

    Como posso aprender mais sobre IA?

  2. Guilherme Silveira 11/07/2012 at 13:35 #

    Oi Bruno!

    Você pode fazer o curso de Stanford no http://www.coursera.org que já é um ótimo começo.

    Abraço!

  3. Bani 12/07/2012 at 11:29 #

    Uma pena que a empresa que detém as patentes sobre SVMs começou cobrar licença de universidades e empresas que fazem a implementação. Espero que essa de Ruby não tenha problemas…

  4. Giulliano Morroni 12/07/2012 at 12:13 #

    Recentemente terminei de ler um livro chamado “Fundamentos da inteligência Artificial” que é um material teórico. E agora estou lendo “Programando a Inteligência Coletiva” que é um livro prático (utiliza python como linguagem). Confesso que o assunto é cativante. Parabéns pela sua aplicação na prática.

  5. Dann Luciano 12/07/2012 at 21:39 #

    Uma outra abordagem seria utilizar redes neurais artificiais, na minha opinião elas são bem superiores comparadas com o SVM, pois pode detectar mais do que 0 e 1.
    O único problema seria os parâmetros a serem configurados, como quantidade de camadas, número de neuronios por camada.

  6. Guilherme Silveira 13/07/2012 at 09:24 #

    O Collective Intelligence é muito interessante mesmo, ele é mais superficial em cada algoritmo do que o curso de stanford, mas aborda muitas variações e vale muito a pena!

    Dann, nesse caso específico o resultado das redes neurais não foram tão satisfatórios quanto os do SVM, talvez justamente por não ter encontrado uma parametrização de camadas e nós adequada. Com certeza está no leque de algoritmos em cada um dos treinos que tentamos aqui.

    Abraço!

  7. Paulo H 13/07/2012 at 15:31 #

    Muito Legal o post… Só falta tempo pra estudar tanta coisa bacana…

    abraço!

  8. Gune 26/07/2012 at 04:16 #

    Estou a interesar-me pela inteligência artificial ,as nao tenho como achar os livros para estudar e gostaria desse umas dicas de como achar alguns

  9. Guilherme Silveira 26/07/2012 at 23:08 #

    Oi Gune,

    Você pode achar os livros online em sites de livrarias ou assistir o curso do http://www.coursera.org que é gratuito

    Abraço

  10. Ricardo Soares 02/08/2012 at 11:40 #

    Putz…eu não sabia que ja existia esse tipo de plataforma. A dois anos eu venho pensando exatamente sobre, como desenvolver uma aplicação online, com IA para auxiliar na educação, achei otimo e vou pesquisar mais.

  11. Jesiel Viana 05/08/2012 at 21:11 #

    Guilherme Silveira,
    Qual a diferença da libsvm em Ruby para
    a libsvm em Java.
    Tem como usar libsvm em um projeto usando eclipse.
    Algum link de tutorial básico de como usar a libsvm em Ruby
    ou Java com alguma IDE?

  12. Jesiel Viana 23/08/2012 at 10:35 #

    Tem como trabalhar com libsvm ruby e octave juntos?
    qual a diferença entre os dois?
    Se alguém poder responder,
    Grato!

    Excelente artigo Guilherme Silveira, essa é uam área que tenho muito interesse.

  13. Freitas 04/09/2012 at 21:10 #

    o problema acima pode ser resolvido com um único perceptron tb, pois se trata de um problema de classificação bem simples. A dica do coursera.org foi ótima. Estudo aprendizado de máquina lah e as aulas são perfeitas.

  14. Freitas 04/09/2012 at 21:12 #

    Jesiel Viana, você pode utilizar o octave para modelar seu problema e depois implementar em qualquer outra linguagem. Fica a dica de visitar o coursera.org e ver o preview disponível lah na classe de machine learning.

  15. Jesiel viana 05/09/2012 at 11:00 #

    Obrigado Freitas….
    Estou fazendo o curso do coursera.org,
    estou com um pouco de difuldade nos vídeos devido não entender o inglês falado, más ta legal.

  16. Freitas 05/09/2012 at 21:38 #

    Jesiel, o pior é que mesmo pra quem entende inglês de ouvido, os vídeos estão com uma qualidade sonora um pouco fraca. Nas próprias legendas, às vezes, aparece a tag [inaudível]. Na dúvida joga o texto no google translate 😉

  17. Luiz Carvalho 15/12/2015 at 12:34 #

    Muito bom o conteúdo!
    Estava procurando um exemplo prático usando Ruby!
    =D

Deixe uma resposta