Skip to main content

O Python domina a área de inteligência artificial, mas sabia que com Java também é possível fazer algumas coisas?

Neste artigo, irei abordar alguns conceitos e faremos uma aplicação bem simples de recomendação de livros e filmes

Primeiramente, você sabe o que é Machine learning?

Se trata do aprendizado de máquina, um ramo da IA (Inteligência Artificial) que se baseia na ideia de que sistemas são capazes de aprender com dados, identificar padrões e realizar tomadas de decisões com o mínimo de intervenção de um ser humano.

E o que são sistemas de recomendação?

São técnicas de software que fornecem sugestões de itens para ajudar usuários deste sistema nos diversos processos de tomada de decisão.

Seria como um vendedor que só com alguns minutos de conversa já sabe qual produto é o ideal para o seu cliente.

Utilizaremos o algoritmo Person Correlation Similarity que se baseia na similaridade entre pessoas na hora de escolher e atribuir notas, para determinar os resultados de sua recomendação.


E aí bora codar?

Antes de tudo verifique se já tem ou instale o Eclipse (versão Java EE Developers).

Se for sua primeira vez utilizando o Maven, que é um gerenciador de dependências, deverá fazer download do mesmo (descompactar) e executar os seguintes passos:

Configuração inicial do maven
test.md hosted with ❤ by GitHub

Caso você já tenha o Maven configurado, basta criar um novo Maven project do tipo QuickStart.

Agora vamos realizar a seguinte configuração, dentro do arquivo pom.xml, estão as nossas dependências, vamos adicionar o Mahout e o Hadoop client, seu arquivo deverá estar parecido com este (os comentários são para facilitar a compreensão do que foi utilizado em cada parte do projeto):

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>br.com.kamila</groupId>
  <artifactId>sistema-de-recomendacao-java-mahout</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>sistema-de-recomendacao-java-mahout</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    <!--mahout cuida da parte dos algoritmos de similaridade !-->
    <dependency>
    	<groupId>org.apache.mahout</groupId>
    	<artifactId>mahout-mr</artifactId>
    	<version>0.12.2</version>
    </dependency>
    <!--hadoop faz a análise dos nossos dados !-->
    <dependency>
    	<groupId>org.apache.hadoop</groupId>
    	<artifactId>hadoop-client</artifactId>
    	<version>2.7.2</version>
    </dependency>
  </dependencies>
</project>

Dentro da pasta src\main\java\br\com\(nome da sua organização), vamos criar o arquivo Recomendador.java, que guarda os modelos de dados que serão analisados:

package br.com.kamila;

import org.apache.mahout.cf.taste.impl.model.file.FileDataModel;
import org.apache.mahout.cf.taste.model.DataModel;

import java.io.File;
import java.io.IOException;
//nesta classe está a relação dos modelos de filmes e livros para a serem recomendados
public class Recomendador {

    public DataModel getModeloLivros() throws IOException {
        //arquivo usado com a base de usuários, os códigos dos livros e as notas atribuídas
        return getModelo("livros.csv");
    }

    private DataModel getModelo(String path) throws IOException {
        File file = new File("src/main/resources/" + path);
        return new FileDataModel(file);
    }

    public DataModel getModeloDeFilmes() throws IOException {
        //arquivo usado com a base de usuários, os códigos dos filmes e as notas atribuídas
       return getModelo("filmes.csv");
    }

}

Recomendador.java hosted with ❤ by GitHub

Os arquivos livros.csv e filmes.csv você pode acessar neste link: https://github.com/Kamilahsantos/sistema-de-recomendacao-java-mahout/tree/master/src/main/resources

Ainda nesta pasta, vamos criar o arquivo RecomendadorBuilder.java , que como o nome já diz, constrói a lógica para o nosso recomendador:

package br.com.kamila;

import org.apache.mahout.cf.taste.common.TasteException;
import org.apache.mahout.cf.taste.eval.RecommenderBuilder;
import org.apache.mahout.cf.taste.impl.neighborhood.ThresholdUserNeighborhood;
import org.apache.mahout.cf.taste.impl.recommender.GenericUserBasedRecommender;
import org.apache.mahout.cf.taste.impl.similarity.PearsonCorrelationSimilarity;
import org.apache.mahout.cf.taste.model.DataModel;
import org.apache.mahout.cf.taste.neighborhood.UserNeighborhood;
import org.apache.mahout.cf.taste.recommender.Recommender;
import org.apache.mahout.cf.taste.recommender.UserBasedRecommender;
import org.apache.mahout.cf.taste.similarity.UserSimilarity;
//aqui connstruimos nosso recomendador
public class RecomendadorBuilder implements RecommenderBuilder {
    public Recommender buildRecommender(DataModel model) throws TasteException {
        //ele irá se basear na similaridade entre os usuários para contruir recomendações.
        UserSimilarity similarity = new PearsonCorrelationSimilarity(model);
        //pega a maior similaridade (vizinhança) entre os usuários do nosso modelo
        UserNeighborhood neighborhood = new ThresholdUserNeighborhood(0.1, similarity, model);
        //fazemos nossa recomendação baseada no usuário, que é retornada no recommender 
        UserBasedRecommender recommender = new GenericUserBasedRecommender(model, neighborhood, similarity);
        return recommender;
    }
}

RecomendadorBuilder.java hosted with ❤ by GitHub

Vamos recomendar filmes para os nossos usuários? Vamos criar o arquivo RecomendaFilmes.java:

package br.com.kamila;

import org.apache.mahout.cf.taste.common.TasteException;
import org.apache.mahout.cf.taste.model.DataModel;
import org.apache.mahout.cf.taste.recommender.RecommendedItem;
import org.apache.mahout.cf.taste.recommender.Recommender;

import java.io.IOException;
import java.util.List;

public class RecomendaFilmes {
    public static void main(String[] args) throws IOException, TasteException {
        DataModel filmes = new Recomendador().getModeloDeFilmes();
        Recommender recommender = new RecomendadorBuilder().buildRecommender(filmes);
        //listamos as recomedações para o usuário solicitado
        //TODO receber as informações de usuário e número de recomendações do usuário via teclado
        //primeiro parâmentro e usuário , segundo o número de recomendações
        List<RecommendedItem> recommendations = recommender.recommend(4, 3);
        for (RecommendedItem recommendation : recommendations) {
            System.out.println("Voce pode gostar deste filme");
            System.out.println(recommendation);
        }
    }
}

Tamém vamos recomendar livros, crie o arquivo RecomendaLivros.java

package br.com.kamila;

import org.apache.mahout.cf.taste.common.TasteException;
import org.apache.mahout.cf.taste.model.DataModel;
import org.apache.mahout.cf.taste.recommender.RecommendedItem;
import org.apache.mahout.cf.taste.recommender.Recommender;

import java.io.IOException;
import java.util.List;

public class RecomendaLivros {

	public static void main(String[] args) throws TasteException, IOException {
		DataModel produtos = new Recomendador().getModeloLivros();
        Recommender recommender = new RecomendadorBuilder().buildRecommender(produtos);
        //listamos as recomedações para o usuário solicitado
        System.out.println("usuario 1");
        List<RecommendedItem> recommendations = recommender.recommend(1, 4);
        for (RecommendedItem recommendation : recommendations) {
            System.out.println("usuário 1, estes livros combinam com voce");
            System.out.println(recommendation);
        }

        System.out.println("usuario 2");
        recommendations = recommender.recommend(2, 4);
        for (RecommendedItem recommendation : recommendations) {
            System.out.println("usuário 2, estes livros combinam com voce");
            System.out.println(recommendation);
        }       
  }
}

Para avaliar a margem de erro do nosso recomendador, criamos o arquivo Avaliador.java

package br.com.kamila;
//realizando todos os imports necessários:
import org.apache.mahout.cf.taste.common.TasteException;
import org.apache.mahout.cf.taste.eval.RecommenderBuilder;
import org.apache.mahout.cf.taste.eval.RecommenderEvaluator;
import org.apache.mahout.cf.taste.impl.eval.AverageAbsoluteDifferenceRecommenderEvaluator;
import org.apache.mahout.cf.taste.model.DataModel;
import org.apache.mahout.common.RandomUtils;

import java.io.IOException;
//esta classe avaliador mede a taxa de erro do  nosso recomendador
public class Avaliador {
    public static void main(String[] args) throws IOException, TasteException {
        //o método usetestseed permite fixar valores para teste, impedindo resultados aleatórios a cada teste
        RandomUtils.useTestSeed();
        //usa  o modelo de de análise
        DataModel modelo = new Recomendador().getModeloDeFilmes();
        //calcula a média absoluta dos testes para informar a taxa de erro
        RecommenderEvaluator evaluator = new AverageAbsoluteDifferenceRecommenderEvaluator();
        RecommenderBuilder builder = new RecomendadorBuilder();
        //90% para treino e 10% para teste
        double erro = evaluator.evaluate(builder, null, modelo, 0.9, 1.0);
        System.out.println("A taxa de erro desse sistema de recomendacao atualmente e:");
        System.out.println(erro);

    }
}

Agora só executar!!! Escolha se quer executar o Avaliador, RecomendaLivros ou RecomendaFilmes.

Se ao executar exibir um erro referente ao log4j, devemos criar o arquivo log4j.xml com este conteúdo:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
    <appender name="main" class="org.apache.log4j.ConsoleAppender">
        <param name="Target" value="System.out"/>
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="[%t] %d{HH:mm:ss} %-5p %l-%m%n"/>
        </layout>
    </appender>
    <category name="org.apache">
        <priority value="DEBUG"/>
        <appender-ref ref="main"/>
    </category>

</log4j:configuration>

Alguma dúvida ou sugestão?

Kamila de Fátima Santos Oliveira é Analista de Sistemas na BRQ

Sobre o Autor