ou nominais, classes numericas ou nominais, classes ausentes etc.2) public double classifyInstance(Instance instance) throws Exception {Chamado para testar a classificacao de uma instancia, previamente conhecida.3) public double[] distributionForInstance(Instance instance) throws Exception {Esse metodo e legal, o vetor de double deve ter o mesmo numero de classes que o padrao de entrada (instance) e informar a probabilidade de cada classe. Segundo a documentacao, o metodo anterior deve chamar esse metodo e pegar o de maior probabilidade como resposta.Alem disso, existem alguns metodos auxiliares, que ajudam a integrar o seu classificador com a interface do weka, entre outros, os provenientes da interface OptionHandler, sao eles:Enumeration listOptions();void setOptions(String[] options) throws Exception;String[] getOptions();Basicamente, o primeiro lista as opcoes, com uma descricao e o tipo de dado esperado para o parametro ou seja, a descricao de cada parametro do seu algoritmo. No meu caso: public Enumeration listOptions() { Vector newVector = new Vector(6); newVector.addElement(new Option( "\tRadius diffuse or neighborhood size (default 6)\n", "FR", 1, "-FR ")); newVector.addElement(new Option( "\tsupport FAN space (default is 100).\n", "FS", 1, "-FS ")); newVector.addElement(new Option( "\tNumber of epochs to train through.\n" + "\t(Default = 2000).", "N", 1, "-N ")); newVector.addElement(new Option( "\tGUI will be opened.\n" + "\t(Use this to bring up a GUI).", "G", 0, "-G")); newVector.addElement(new Option( "\tscramble the training set every n epochs.\n" + "\t(Default = 50).", "SE", 1, "-SE ")); newVector.addElement(new Option( "\tThe value used to seed the random number generator\n" + "\t(Value should be >= 0 and and a long, Default = 0).", "S", 1, "-S ")); newVector.addElement(new Option( "\tReseting the network will NOT be allowed.\n" +"\t(Set this to not allow the network to reset).", "R", 0,"-R")); Enumeration enu = super.listOptions(); while (enu.hasMoreElements()) { newVector.addElement((Option) enu.nextElement()); } return newVector.elements(); }Um pequeno trecho do setOptions: public void setOptions(String[] options) throws Exception { String auxRadius = Utils.getOption("FR", options); try { setRadius(Integer.decode(auxRadius)); } catch (NumberFormatException ne) { setRadius(6); }//.... if (Utils.getFlag('R', options)) { setReset(false); } else { setReset(true); } super.setOptions(options); }Mais um pequeno trecho, agora do getOptions: public String[] getOptions() { String[] superOptions = super.getOptions(); String[] options = new String[superOptions.length + 11]; int current = 0; options[current++] = "-FR"; options[current++] = String.format("%d", getRadius());//... if (!isReset()) { options[current++] = "-R"; } else { options[current++] = ""; } System.arraycopy(superOptions, 0, options, current, superOptions.length); current += superOptions.length; while (current < options.length) { options[current++] = ""; } return options; }O TreinamentoO metodo previsto na classe AbstractClassifier para realizar o treinamento e o buildClassifier, mas olhando a implementacao dos outros classificadores, observei que eles tendem a separar o processo de treinamento do processo de inicializacao do modelo. Isso nos levou a criacao do metodo initializeClassifier que recebe os mesmos parametros do buildClassifier e retorna a colecao dos dados para treinamento. No caso do FAN, os dados originais ficam armazenados no atributo m_data, enquanto que os dados normalizados para o treinamento ficam em m_norm_data. Entao o metodo build foi inicialmente criado dessa forma: public void buildClassifier(Instances data) throws Exception { // Set up the initial arrays m_data = initializeClassifier(data);Agora vamos ver o que faremos na inicializacao do modelo FAN, dentro da perspectiva do ambiente WEKA. Aqui podemos