SlideShare uma empresa Scribd logo
1 de 19
Implementation of SMOTE algorithm for imbalanced classification
                         problems

                           Marcelo Beckmann
             Universidade Federal do Rio de Janeiro – COPPE
                      beckmann.marcelo@gmail.com
1.0 - Objetivos

Este trabalho tem como objetivo reportar a implementação feita do algoritmo SMOTE proposto por
[1] na plataforma de mineração de dados de código livre Weka, bem como demonstrar os resultados
do algoritmo implementado, nas mesmas bases de dados avaliadas pelo autor no referido artigo.

1.0 - Introdução
Em mineração de dados, um dos principais problemas da atividade de classificação reside no
tratamento de conjuntos de dados onde uma das classes possui uma quantidade minoritária de
instâncias, onde esse desbalanceamento leva o algoritmo a classificar incorretamente uma instância
da classe minoritária como sendo da classe majoritária. Todavia, a classe minoritária, que representa
a informação anormal em um conjunto de dados, costuma ser a informação interessante a qual se
quer predizer. A abordagem proposta por [1] para o tratamento de problemas desse tipo visa a
criação de instâncias sintéticas a partir de k vizinhos mais próximos de uma instância da classe
desbalanceada.

2.0 - Implementação
O algoritmo foi implementado em Java versão 5.0, como um plugin na plataforma Weka. Por ser
basicamente o processo de preparação de dados, o SMOTE foi implementado como um plugin de
Filtro, no pacote weka.filters.supervised.instance. Foi criada uma classe com o nome de
SMOTE neste pacote. Esta classe estende weka.filters.SimpleBatchFilter e implementa
as interfaces weka.core.OptionHandler, weka.core.TechnicalInformationHandler e
weka.filters.SupervisedFilter.

O algoritmo reside nos métodos process(Instances data), o qual recebe as instâncias da base a
ser processada e retorna a base original mais as instâncias sintéticas, e populate(...) que é
encarregado de gerar as instâncias sintéticas. Nestes métodos foi implementado o algoritmo
propriamente dito, conforme demonstrado no pseudocódigo da página 329 de [1].

Também foram criados os métodos generateNnnList(...) que se encarregará de gerar uma lista
de k vizinhos mais próximos (utilizando distância euclidiana), conforme especificado em [9], e
processUnderSampling(Instances data), o qual opcionalmente irá retirar randomicamente um
percentual de instâncias da classe majoritária. Para maiores detalhes da implementação, vide o
código completo no anexo A.

A parametrização do algoritmo, pode ser feita em uma caixa de diálogo, conforme demonstrado na
figura 2.2, e na tabela 2.1 contém uma descrição detalhada dos parâmetros. O significado de cada
parâmetro também pode consultado no botão More da caixa de diálogos da figura 2.2.

  Parâmetro                   Símbolo      Descrição
  amountOfSMOTE               N            Percentual de instâncias sintéticas a serem criadas a partir
                                           da classe minoritária. Use múltiplos de 100.
  k                    k                   Número de vizinhos mais próximos
  minorityClass        w                   Índice da classe minoritária, começando com 0.
  percentToUndersample U                   Percentual de instâncias a serem removidas da(s)
                                           classe(s) diferente(s) da classe minoritária.
 Tabela 2.1 – Descrição dos parâmetros utilizados no algoritmo SMOTE.
Figura 2.2 – Caixa de diálogo com os parâmetros necessários para utilização do SMOTE a partir da aba Preprocess.


3.0 – Experimentos

Para os experimentos foram utilizadas quatro bases avaliadas em [1], e disponibilizadas em [8]
(Pima, Satimage, Forest Cover), e mais uma base de balanços e falências disponibilizada por [3].
Outras bases utilizadas em [1] não se encontram disponíveis para download imediato, e serão
avaliadas em trabalhos futuros.

Repetindo o que foi testado em [1], as bases em estudo possuem problemas de classificação binária,
onde uma das classes é desbalanceada. Seguindo ainda o artigo, os experimentos de classificação
foram executados com o algoritmo C4.5 e comparados com o SMOTE + C4.5.

Para os nossos experimentos, foi utilizado o J48, uma versão mais nova do C4.5. Em todos os
experimentos, os conjuntos de dados foram padronizados com o filtro Standarize, e não foi
executado um pré-processamento de análise de correlação, outliers e componentes principais. O
algoritmo J48 foi parametrizado com os valores padrões fornecidos pelo Weka (-C 0.25 –M 2) As
subseções a seguir irão demonstrar os resultados obtidos em cada conjunto de dados com o
algoritmo implementado. Pelo SMOTE ser um algoritmo probabilístico, os valores demonstrados
neste relatório são os melhores obtidos em 3 execuções..
3.1 – Pima




Figura 3.1.1 – Comparativo de AUC entre os algoritmos J48 e SMOTE 400 + J48 para a base Pima.




Figura 3.1.2 – Plotagem das instâncias antes e depois da aplicação do SMOTE 400 para a base Pima.
J48                                           SMOTE 400 + J48

   Estatísticas                                Valor      Estatísticas                              Valor
   Total de instâncias                           768      Total de instâncias                       1840
   Instâncias da classe 1                        500      Instâncias da classe 1                      500
   Instâncias da classe 2                        268      Instâncias da classe 2                     1340
   % Classificações corretas                   73,83      % Classificações corretas                 86,30
   % Classificações incorretas                 26,17      % Classificações incorretas               13,70
   AUC                                         70,55      AUC                                       82,51

  Matriz de confusão                                     Matriz de confusão
  Real/Prev. c1                      c2                  Real/Prev. c1                       c2
  c1           407                   93                  c1           371                    129
  c2           108                   160                 c2           123                    1217

Tabela 3.1.3 – Resultados e métricas obtidas com o J48 e SMOTE 400 + J48 para a base Pima.

Analisando o gráfico da figura 3.1.1, verifica-se um desempenho superior do AUC (82,51) do
SMOTE com 400% de aumento sintético dos registros, em relação ao AUC do J48 simples (70,55).
Avalia-se ainda a que o comportamento centrado , isto é, nem conservador nem agressivo do
classificador [6], se mantém nas duas abordagens. Os gráficos de plotagem de instâncias da figura
3.1.2 demonstram que a criação de instâncias sintéticas aumentou a separabilidade entre classes.

Na tabela 3.1.3 verifica-se um aumento de falsos positivos e falsos negativos, apesar do aumento de
verdadeiros positivos na classe minoritária c2. Todavia, este aumento de desempenho trata-se de
uma melhoria tão sintética quanto as instâncias criadas, pois pode-se concluir que o mecanismo de
cálculo de métricas fornecido pelo Weka deveria computar somente as instâncias originais e não as
originais + sintéticas.

Apesar de não ser citado no artigo, estamos assumindo que para se efetuar uma comparação precisa
com o melhor valor obtido para esta base em [1], que foi de 73.07, será necessário remover as
instâncias sintéticas.
3.2 – Satimage




Figura 3.2.1 – Comparativo de AUC entre os algoritmos J48 e SMOTE 100 + J48 para a base Satimage.




Figura 3.2.2 – Plotagem das instâncias antes e depois da aplicação do SMOTE 100 para a base Satimage.



Conforme orientação dos autores [8], não se deve utilizar a validação cruzada para a base Satimage,
e sim utilizar uma base para treinamento e outra para teste no processo de classificação. Desta
maneira, o mecanismo de cálculo do Weka computou corretamente as métricas de classificação.

Analisando o gráfico da figura 3.2.1, verifica-se um desempenho superior do AUC (93,26) com
SMOTE de 100% de aumento sintético dos registros, em relação ao AUC J48 sem preparação
(82,22). Os gráficos de plotagem de instâncias da figura 3.2.2 demonstram a criação de instâncias
sintéticas, as quais podem levar a classificações incorretas da classe majoritária, em favor da
minoritária (falsos positivos).
J48                                           SMOTE 100 + J48

   Estatísticas                                Valor      Estatísticas                             Valor
   Total de instâncias                         2000       Total de instâncias                      2000
   Instâncias da classe 1                      1789       Instâncias da classe 1                    1789
   Instâncias da classe 2                        211      Instâncias da classe 2                     211
   % Classificações corretas                   94,00      % Classificações corretas                95,80
   % Classificações incorretas                  6,00      % Classificações incorretas               4,20
   AUC                                         82,22      AUC                                      93,26

  Matriz de confusão                                     Matriz de confusão
  Real/Prev. c1                       c2                 Real/Prev. c1                       c2
  c1           1738                   51                 c1           1726                   63
  c2           69                     142                c2           21                     190

Tabela 3.2.3 – Resultados e métricas obtidas com o J48 e SMOTE 400 + J48 para a base Satimage.

Avaliando a tabela 3.2.3, pode-se notar um aumento de verdadeiros positivos na classe minoritária
c2, de 142 no J48, para 190 com o SMOTE 100% + J48, bem como a diminuição dos falsos
negativos de 69 para 21, o que atesta o bom desempenho do SMOTE. Conforme foi previsto na
análise do gráfico 3.2.2, a criação das instâncias sintéticas diminuiu o número de verdadeiros
negativos de 1738 para 1726 na classe majoritária c1.

Conforme foi citado anteriormente, a separação da base em um conjunto de treinamento e um de
teste proporcionou o cálculo correto das métricas, o qual não leva em conta as instâncias sintéticas.
Desta maneira, atesta-se que o algoritmo implementado obteve um AUC superior a 89.79, o melhor
resultado obtido originalmente com esta base em [1] .
3.3 – Forest Cover




Figura 3.3.1 – Comparativo de AUC entre os algoritmos J48 e SMOTE 500 + J48 para a base Forest Cover.




Figura 3.3.2 – Plotagem das instâncias antes e depois da aplicação do SMOTE 500 para a base Forest Cover.
J48                                           SMOTE 500 + J48

   Estatísticas                                Valor       Estatísticas                              Valor
   Total de instâncias                         38429       Total de instâncias                       52164
   Instâncias da classe 1                      35682       Instâncias da classe 1                    35682
   Instâncias da classe 2                       2747       Instâncias da classe 2                    16482
   % Classificações corretas                   98,30       % Classificações corretas                  98,78
   % Classificações incorretas                   1,70      % Classificações incorretas                 1,22
   AUC                                          92,67      AUC                                        98,52

  Matriz de confusão                                      Matriz de confusão
  Real/Prev. c1                       c2                  Real/Prev. c1                      c2
  c1           35412                  270                 c1           35406                 276
  c2           382                    2365                c2           359                   16123

Tabela 3.3.3 – Resultados e métricas obtidas com o J48 e SMOTE 500 + J48 para a base Forest Cover.

Na figura 3.3.1 pode-se avaliar a comparação das duas abordagens, sendo que o SMOTE 500 + J48,
quase chegou à classificação perfeita. Na plotagem de instâncias antes e depois do SMOTE (figura
3.3.2), pode-se avaliar que o SMOTE acentuou a separação entre classes.

Na matriz de confusão da tabela 3.3.3 pode-se verificar a diminuição de falsos negativos, isto é,
menos instâncias minoritárias (c2) foram classificadas incorretamente como majoritárias (c1), e um
pequeno aumento de falsos positivos contra a classe majoritária.
3.4 - Bankrupt




Figura 3.4.1 – Comparativo de AUC entre os algoritmos J48 e SMOTE 400 + J48 para a base Bankrupt.




Figura 3.4.2 – Plotagem das instâncias antes e depois da aplicação do SMOTE 400 para a base Bankrupt.
J48                                           SMOTE 400 + J48

   Estatísticas                                Valor      Estatísticas                            Valor
   Total de instâncias                           116      Total de instâncias                      224
   Instâncias da classe 1                         27      Instâncias da classe 1                    135
   Instâncias da classe 2                         89      Instâncias da classe 2                     89
   % Classificações corretas                   81,03      % Classificações corretas               91,07
   % Classificações incorretas                 18,97      % Classificações incorretas              8,93
   AUC                                         69,58      AUC                                     90,10

  Matriz de confusão                                     Matriz de confusão
  Real/Prev. c1                       c2                 Real/Prev. c1                       c2
  c1           13                     14                 c1           128                    7
  c2           8                      81                 c2           13                     76

Tabela 3.4.3 – Resultados e métricas obtidas com o J48 e SMOTE 400 + J48 para a base Bankrupt.

Analisando o gráfico da figura 3.4.1, verifica-se um desempenho superior do AUC (90,10) do
SMOTE com 400% de aumento sintético dos registros, em relação ao AUC do J48 (69,58) simples.
Avalia-se ainda a que o comportamento centrado , isto é, nem conservador nem agressivo do
classificador [6], também se mantém nas duas abordagens. Os gráficos de plotagem de instâncias
da figura 3.4.2 demonstram que a criação de instâncias sintéticas aumentou a separabilidade entre as
classes.

Na matriz de confusão da tabela 3.4.3, pode-se verificar uma diminuição de falsos positivos de 14
para 7, e a diminuição de acertos da classe majoritária (c2), em favor da classe minoritária (c1).

Esta base não faz parte dos experimentos efetuados em [1].
4.0 – Conclusão

   Conjunto Melhor             J48           100           200           300           400           500
   de Dados desempen                         SMOTE         SMOTE         SMOTE         SMOTE         SMOTE
            ho em [1]
   Pima     73,07              70,55         77,60         81,19         80,02                       81,43
                                                                                       82,51
   Satimage 89,79              82,22                       91,56         91,34         89,83         88,67
                                             93,26
   Forest   98,49              92,67         96,29         97,45         97,94         98,18         98,52
   Cover
   Bankrupt -                  69,58         75,27         80,68         80,89                       90,06
                                                                                       90,10
Tabela 4.1 – Comparação dos resultados obtidos anteriormente em [1], com os resultados obtidos com o J48 e os
resultados obtidos com diversos percentuais de SMOTE + J48.

Em todos os percentuais de SMOTE + J48, os valores de AUC obtidos no experimento
mantiveram-se superiores em relação ao J48 simples e aos melhores desempenhos obtidos em [1],
conforme pode ser visto na tabela 4.1.

Com exceção da base Satimage, que utilizou um conjunto de treinamento e outro de teste, as
métricas fornecidas pelo Weka, as quais foram replicadas no Matlab para a geração dos gráficos,
não levaram em consideração somente as instâncias originais, portanto, neste trabalho não podemos
atestar com precisão que o SMOTE obteve um resultado superior nas bases Pima, Forest Cover e
Bankrupt. Entretanto, nos experimentos ocorreu a diminuição de falsos negativos e falsos positivos,
mesmo com a adição de instâncias sintéticas, o que, juntamente com o bom resultado alcançado
com a base Satimage, fornecem indícios de bom desempenho do classificador implementado.


5.0 – Trabalhos futuros

Apesar de [1] não citar que as instâncias sintéticas deveriam ser removidas para se computar as
métricas de classificação, estamos assumindo esta condição, por ser a alternativa mais plausível, e
portanto, será efetuado um ajuste no algoritmo, para que a plataforma Weka possa calcular as
métricas de classificação levando em conta somente as instâncias originais.

Serão efetuados experimentos com outros conjuntos de dados utilizados em [1], os quais não estão
disponíveis para download público. Todavia, estes experimentos dependem da colaboração dos
responsáveis pelos respectivos conjuntos de dados.

6.0 – Referências
[1] Nitesh V. Chawla, Kevin W. Bowyer, Lawrence O. Hall, W. Philip Kegelmeyer -
SMOTE: Synthetic Minority Over-sampling Technique
Journal of Artificial Inteligence Research 16 - AI Access Foundation and Morgan Kaufmann - pp.
321-357 (2002).

[2] Chawla, N., Bowyer, K., Hall, L., & Kegelmeyer, P. – SMOTE: Synthetic Minority
Over-sampling TEchnique. In International Conference of Knowledge Based Computer
Systems, pp. 46–57 - National Center for Software Technology, Mumbai, India,
Allied Press (2000)

[3] Américo, Rui - Mineração de Dados para Melhor Avaliação de Risco de Crédito em Empresas
Brasileiras de Capital Aberto - COPPE - Universidade Federal do Rio de Janeiro (2007)
[4] Evsukoff, Alexandre - Toolbox Matlab – COPPE - Universidade Federal do Rio de Janeiro
(2007)

[5] Evsukoff, Alexandre – Material de aula – COC786 Aprendizado Estatístico Computacional –
COPPE - Universidade Federal do Rio de Janeiro (2007)

[6] Fawcett, Tom – ROC Graphs: Notes and Pratical Considerations for Ressearchers – HP
Laboratories (2004)

[7] Suman, Sanjeev; Laddhad , Kamlesh; Deshmukh,Unmesh - Methods for Handling Highly
Skewed Datasets - CSE, IIT Bombay, Mumbai (2005)

[8] Blake, C., & Merz, C. - UCI Repository of Machine Learning Databases -
http://www.ics.uci.edu/~mlearn/~MLRepository.html - Department of Information
and Computer Sciences, University of California, Irvine (1998)

[9] Hastie, Trevor; Tibshirani, Robert; Friedman, Jerome – The Elements of Statistical Learning,
Data Mining, Inference, and Prediction – Cap. 13 - Springer Series in Statistics (2001)

[10] Ian H. Witten and Eibe Frank (2005) quot;Data Mining: Practical machine learning tools and
techniquesquot;, 2nd Edition, Morgan Kaufmann, San Francisco, 2005.

[11] Java Standard Development Kit versão 1.5 – Sun Microsystems Inc. 2005 (c) – java.sun.com

[12] Matlab versão 7.10 – Mathworks Inc. 2005 (c) – www.mathworks.com
Apêndice A – Código fonte
package weka.filters.supervised.instance;

import java.util.*;

         weka.core.*;
import
         weka.core.Capabilities.Capability;
import
         weka.core.TechnicalInformation.Field;
import
         weka.core.TechnicalInformation.Type;
import
         weka.filters.SimpleBatchFilter;
import
         weka.filters.SupervisedFilter;
import

public class SMOTE extends SimpleBatchFilter implements SupervisedFilter,
               OptionHandler, TechnicalInformationHandler {

         /**
          *
          */
         private static final long serialVersionUID = -2703039882958523000L;

         /** Number of references */

         private int k = 2;

         private int N_amountOfSMOTE = 100;

         private int w_minorityClass = 0;

         private int U_percentToUndersample = 0;

         // inner class to hold a pair of doubles
         // (for maintaining a running list of nearest neighbors)
         class ClassDistance {
                double _class;

                double distance;

                int index;

         }

         public SMOTE() {

         }

         /**
          * Returns the description of the classifier.
          *
          * @return description of the KNN class.
          */
         public String globalInfo() {
                return quot;Implementation of SMOTE (Syntethic Minority Over-sampling Technique), quot;
                        + quot;aplied over a KNN algorithm, in order to improve the classification quot;
                               + quot;with imbalanced datasets.nnquot;
                               + quot;For more information see:nnquot;
                               + getTechnicalInformation().toString();

         }

         /**
          * sets k
          *
          * @param new_k
          *            new k value.
          */
         public void setK(int new_k) {
                k = new_k;
         }

         /**
          * gets k
          *
          * @return k
          */
         public int getK() {
                return k;
}

protected void processUnderSampling(Instances data) {

       // Obtain the samples from class w
       if (U_percentToUndersample == 0) {
              return;
       }

       Enumeration en = data.enumerateInstances();
       int T = data.numInstances();

       int totalToUndersample = T * U_percentToUndersample / 100;
       int count = 0;
       Random r = data.getRandomNumberGenerator(System.currentTimeMillis());

       while (count <= totalToUndersample) {
              // Sorts an instance to be eliminated
              int index = (int) (r.nextDouble() * (T - count));
              Instance instance = data.instance(index);
              if (instance.classIndex() != w_minorityClass) {
                      try {

                             data.delete(index);
                             count++;
                      } catch (NullPointerException e) {
                             e.printStackTrace();
                             data.delete(index);

                      }
              }
       }

}

protected Instances determineOutputFormat(Instances inputFormat)
               throws Exception {

       return inputFormat;
}

protected Instances process(Instances data) throws Exception {

       // Obtain the samples from class w
       Instances samples = new Instances(data, 0);
       Enumeration en = data.enumerateInstances();
       while (en.hasMoreElements()) {
              Instance instance = (Instance) en.nextElement();
              if (instance.classValue() == w_minorityClass) {
                      samples.add(instance);
              }
       }
       int T = samples.numInstances();

       /*
        * IF N is less than 100%, randomize the minority class samples as only
        * a random percent of them will be SMOTEd
        */
       if (N_amountOfSMOTE < 100) {
              T = (int) ((N_amountOfSMOTE / 100.0) * T);
              N_amountOfSMOTE = 100;
       }

       /* The amount of SMOTE is assumed to be in integral multiples of 100 */
       N_amountOfSMOTE = (int) (N_amountOfSMOTE / 100.0);

       // Keeps a count of number of synthetic samples generates, intialized to
       // 0
       int newindex = 0;

       // Instances for synthetic samples
       Instances synthetics = new Instances(data, 0);

       /*
        * Compute k nearest neighbors for i, and save the indices in the
        * nnarray
        */
       Random random = data.getRandomNumberGenerator(System.currentTimeMillis());
       random.setSeed(System.currentTimeMillis());
en = samples.enumerateInstances();
       while (en.hasMoreElements()) {
              Instance instance = (Instance) en.nextElement();
              // Compute k nearest neighbors for i
              List knnList = generateNnnList(instance, data);
              // List knnList = generateNnnList(instance, samples);
              populate(N_amountOfSMOTE, instance, knnList, synthetics, random,
                             data);
              newindex++;
       }

       if (U_percentToUndersample > 0) {
              processUnderSampling(data);

       }

       en = synthetics.enumerateInstances();
       while (en.hasMoreElements()) {
              Instance synthetic = (Instance) en.nextElement();
              data.add(synthetic);
       }

       return data;

}

/* Function to generate synthetic samples */
protected void populate(int N, Instance sample, List knnList,
               Instances synthetics, Random random, Instances data) {
       // Number of attributes
       int numattrs = synthetics.numAttributes();

       while (N != 0) {

              /*
               * Choose a random number between 1 and k, call it nn. This step
               * chooses one of the k nearest neighbors of i
               */
              int nn = (int) (Math.random() * knnList.size());
              Instance neighbor = data
                             .instance(((ClassDistance) knnList.get(nn)).index);
              Instance synthetic = (Instance) sample.copy(); // new
              // Instance(sample);

              for (int i = 0; i < numattrs - 1; ++i) {
                     // Proccess all the attributes, less the class attribute
                     if (sample.classIndex() != i) {
                             double dif = neighbor.value(i) - sample.value(i);
                             double gap = random.nextDouble();
                             synthetic.setValue(i, sample.value(i) + gap + dif);

                      }

              }

              synthetic.setClassValue(sample.classValue());
              synthetics.add(synthetic);

              N--;
       }

}

protected LinkedList generateNnnList(Instance instance, Instances data) {
       LinkedList knnList = new LinkedList();

       double subtotal;
       // DoublePair classDistance = new DoublePair(0, 0);
       // compute distances from the instance to all instances in training set
       for (int i = 0; i < data.numInstances(); i++) {
              subtotal = 0;
              for (int j = 0; j < instance.numAttributes(); j++) {
                      if (j != instance.classIndex()) {
                             // Euclidean
                             subtotal += Math.pow((data.instance(i).value(j) - instance
                                            .value(j)), 2.0);
                      }
              }
              subtotal = Math.sqrt(subtotal);
// manage the current k nearest neighbors
              for (int j = 0; j < k; j++) {
                     if (knnList.size() < k) {
                             if (j == knnList.size()) {
                                    ClassDistance classDistance = new ClassDistance();
                                    classDistance._class = data.instance(i).classValue();
                                    classDistance.distance = subtotal;
                                    classDistance.index = i;
                                    knnList.addLast(classDistance);
                                    break;
                             }
                     }
                     if (subtotal < ((ClassDistance) knnList.get(j)).distance) {
                             ClassDistance classDistance = new ClassDistance();
                             classDistance._class = data.instance(i).classValue();
                             classDistance.distance = subtotal;
                             classDistance.index = i;
                             knnList.add(j, classDistance);

                             if (knnList.size() > k) {
                                    knnList.remove(k);
                             }
                             break;
                        }
              }
       }
       return knnList;
}

// ----------------------------------------------------------------------------

public Capabilities getCapabilities() {
       Capabilities result = super.getCapabilities();

       // attributes
       result.enable(Capability.NOMINAL_ATTRIBUTES);
       result.enable(Capability.NUMERIC_ATTRIBUTES);
       result.enable(Capability.DATE_ATTRIBUTES);
       result.enable(Capability.RELATIONAL_ATTRIBUTES);
       // result.enable(Capability.MISSING_VALUES);

       // class
       result.enable(Capability.NOMINAL_CLASS);
       result.enable(Capability.MISSING_CLASS_VALUES);

       // other
       // result.enable(Capability.ONLY_MULTIINSTANCE);

       return result;
}


public TechnicalInformation getTechnicalInformation() {
       TechnicalInformation result;
       result = new TechnicalInformation(Type.INPROCEEDINGS);
       result.setValue(Field.AUTHOR,
       quot;Nitesh V. Chawla, Kevin W. Bowyer, Lawrence O. Hall, W. Philip Kegelmeyer.quot;
       + quot;nImplemented in Weka by Marcelo Beckmann quot; +
       quot;- Universidade Federal do Rio de Janeiro - COPPE/PECquot;);
       result.setValue(Field.TITLE,
                      quot;nSMOTE: Synthetic Minority Over-sampling TEchniquequot;);
       result.setValue(Field.BOOKTITLE,
                      quot;Journal of Artificial Inteligence Research 16quot;);
       result.setValue(Field.EDITOR,
                      quot;AI Access Foundation and Morgan Kaufmannquot;);
       result.setValue(Field.YEAR, quot;2002quot;);
       result.setValue(Field.PAGES, quot;321-357quot;);

       return result;
}

public String percentToUndersampleTipText() {

       return quot;Percent of instances to be undersampled.quot;;
}

public String kTipText() {
       return quot;Number of Nearest Neighbors.quot;;
}
public String amountOfSMOTETipText() {
              return quot;Amount of SMOTE N% to be created. Use multiples of 100.quot;;
       }

       public String minorityClassTipText() {
              return quot;Index of minority class, starting with 0.quot;;
       }

       public Enumeration listOptions() {
              Vector result = new Vector();

              result.addElement(new Option(
                             quot;tNumber of Nearest Neighbors (default 2).quot;, quot;Kquot;, 0,
                             quot;-K <number of references>quot;));

              result
                             .addElement(new Option(
                                            quot;tAmount of SMOTE N% to be created (default 100). Use
multiples of 100.quot;,
                                              quot;Nquot;, 0,
                                              quot;-N <percent of SMOTEd instances to be created>quot;));

              result.addElement(new Option(
                             quot;tIndex of minority class, starting with 0 (default 0).quot;, quot;wquot;,
                             0, quot;-w <Index of minority class>quot;));

              return result.elements();
       }

       public void setOptions(String[] options) throws Exception {
              // setDebug(Utils.getFlag('D', options));

              String option = Utils.getOption('k', options);
              if (option.length() != 0)
                     k = Integer.parseInt(option);
              else
                     k = 1;

              option = Utils.getOption('N', options);
              if (option.length() != 0)
                     N_amountOfSMOTE = Integer.parseInt(option);
              else
                     N_amountOfSMOTE = 10;

              option = Utils.getOption('w', options);
              if (option.length() != 0)
                     N_amountOfSMOTE = Integer.parseInt(option);
              else
                     N_amountOfSMOTE = 10;

              option = Utils.getOption('U', options);
              if (option.length() != 0)
                     U_percentToUndersample = Integer.parseInt(option);
              else
                     U_percentToUndersample = 10;

       }

       /**
        * Gets the current option settings for the OptionHandler.
        *
        * @return the list of current option settings as an array of strings
        */
       public String[] getOptions() {
              Vector result;

              result = new Vector();

              // if (getDebug())
              // result.add(quot;-Dquot;);

              result.add(quot;-Nquot;);
              result.add(quot;quot; + N_amountOfSMOTE);

              result.add(quot;-kquot;);
              result.add(quot;quot; + k);

              result.add(quot;-wquot;);
              result.add(quot;quot; + w_minorityClass);
result.add(quot;-Uquot;);
           result.add(quot;quot; + U_percentToUndersample);

           return (String[]) result.toArray(new String[result.size()]);
    }

    public int getAmountOfSMOTE() {
           return N_amountOfSMOTE;
    }

    public void setAmountOfSMOTE(int n) {
           N_amountOfSMOTE = n;
    }

    public int getMinorityClass() {
           return w_minorityClass;
    }

    public void setMinorityClass(int w) {
           this.w_minorityClass = w;
    }

    public int getPercentToUndersample() {
           return U_percentToUndersample;
    }

    public void setPercentToUndersample(int toUndersample) {
           U_percentToUndersample = toUndersample;
    }

    /**
     * Main method for testing this class.
     *
     * @param argv
     *            should contain arguments to the filter: use -h for help
     */
    public static void main(String[] argv) {
           runFilter(new SMOTE(), argv);
    }

}

Mais conteúdo relacionado

Semelhante a Implementation of Smote Algorithm for Imbalanced Classification Problems

Algoritmo 01 - Semana 01
Algoritmo 01 - Semana 01Algoritmo 01 - Semana 01
Algoritmo 01 - Semana 01Eder Samaniego
 
Trabalho 01-CEP-UFAM-AM ANO2024/030.docx
Trabalho 01-CEP-UFAM-AM ANO2024/030.docxTrabalho 01-CEP-UFAM-AM ANO2024/030.docx
Trabalho 01-CEP-UFAM-AM ANO2024/030.docxHelderEvangelista1
 
Planif novo espaco_a_12_ae_2019_20
Planif novo espaco_a_12_ae_2019_20Planif novo espaco_a_12_ae_2019_20
Planif novo espaco_a_12_ae_2019_20Paula Gomes
 
Evaluation of multi user system of voice interaction using grammars(slide share)
Evaluation of multi user system of voice interaction using grammars(slide share)Evaluation of multi user system of voice interaction using grammars(slide share)
Evaluation of multi user system of voice interaction using grammars(slide share)Elizabete Munzlinger
 
Teste de Software - Especialização Univem
Teste de Software - Especialização UnivemTeste de Software - Especialização Univem
Teste de Software - Especialização UnivemAndré Abe Vicente
 
Um framework para validação automática de modelos aplicado ao subsistema de e...
Um framework para validação automática de modelos aplicado ao subsistema de e...Um framework para validação automática de modelos aplicado ao subsistema de e...
Um framework para validação automática de modelos aplicado ao subsistema de e...Italo Pinto Rodrigues
 
Apresentacao dissertacao thiago defesa
Apresentacao dissertacao   thiago defesaApresentacao dissertacao   thiago defesa
Apresentacao dissertacao thiago defesathiaguth
 

Semelhante a Implementation of Smote Algorithm for Imbalanced Classification Problems (11)

Algoritmo 01 - Semana 01
Algoritmo 01 - Semana 01Algoritmo 01 - Semana 01
Algoritmo 01 - Semana 01
 
Metodos matematicos
Metodos matematicosMetodos matematicos
Metodos matematicos
 
Trabalho 01-CEP-UFAM-AM ANO2024/030.docx
Trabalho 01-CEP-UFAM-AM ANO2024/030.docxTrabalho 01-CEP-UFAM-AM ANO2024/030.docx
Trabalho 01-CEP-UFAM-AM ANO2024/030.docx
 
Planif novo espaco_a_12_ae_2019_20
Planif novo espaco_a_12_ae_2019_20Planif novo espaco_a_12_ae_2019_20
Planif novo espaco_a_12_ae_2019_20
 
Evaluation of multi user system of voice interaction using grammars(slide share)
Evaluation of multi user system of voice interaction using grammars(slide share)Evaluation of multi user system of voice interaction using grammars(slide share)
Evaluation of multi user system of voice interaction using grammars(slide share)
 
Pi raciocinio lógico
Pi   raciocinio lógicoPi   raciocinio lógico
Pi raciocinio lógico
 
Iniciação Científica - Pedro Victor Gomes
Iniciação Científica - Pedro Victor GomesIniciação Científica - Pedro Victor Gomes
Iniciação Científica - Pedro Victor Gomes
 
Teste de Software - Especialização Univem
Teste de Software - Especialização UnivemTeste de Software - Especialização Univem
Teste de Software - Especialização Univem
 
Um framework para validação automática de modelos aplicado ao subsistema de e...
Um framework para validação automática de modelos aplicado ao subsistema de e...Um framework para validação automática de modelos aplicado ao subsistema de e...
Um framework para validação automática de modelos aplicado ao subsistema de e...
 
Apresentacao dissertacao thiago defesa
Apresentacao dissertacao   thiago defesaApresentacao dissertacao   thiago defesa
Apresentacao dissertacao thiago defesa
 
Resolução Caso 3 - Grupo Fênix
Resolução Caso 3 - Grupo FênixResolução Caso 3 - Grupo Fênix
Resolução Caso 3 - Grupo Fênix
 

Mais de marcelobeckmann

Dissertation: Genetic Algorithms as a pre processing strategy for imbalanced ...
Dissertation: Genetic Algorithms as a pre processing strategy for imbalanced ...Dissertation: Genetic Algorithms as a pre processing strategy for imbalanced ...
Dissertation: Genetic Algorithms as a pre processing strategy for imbalanced ...marcelobeckmann
 
Java Micro Edition Applied
Java Micro Edition AppliedJava Micro Edition Applied
Java Micro Edition Appliedmarcelobeckmann
 
Hibernate With Visual Editor And Hibernate Tools
Hibernate With Visual Editor And Hibernate ToolsHibernate With Visual Editor And Hibernate Tools
Hibernate With Visual Editor And Hibernate Toolsmarcelobeckmann
 
Genetic Algorithm For Job Shop Problem
Genetic Algorithm For Job Shop ProblemGenetic Algorithm For Job Shop Problem
Genetic Algorithm For Job Shop Problemmarcelobeckmann
 
Genetic Algorithm Applied In Travel Salesman Problem
Genetic Algorithm Applied In Travel Salesman ProblemGenetic Algorithm Applied In Travel Salesman Problem
Genetic Algorithm Applied In Travel Salesman Problemmarcelobeckmann
 

Mais de marcelobeckmann (6)

Dissertation: Genetic Algorithms as a pre processing strategy for imbalanced ...
Dissertation: Genetic Algorithms as a pre processing strategy for imbalanced ...Dissertation: Genetic Algorithms as a pre processing strategy for imbalanced ...
Dissertation: Genetic Algorithms as a pre processing strategy for imbalanced ...
 
Java Micro Edition Applied
Java Micro Edition AppliedJava Micro Edition Applied
Java Micro Edition Applied
 
IT Carreer
IT CarreerIT Carreer
IT Carreer
 
Hibernate With Visual Editor And Hibernate Tools
Hibernate With Visual Editor And Hibernate ToolsHibernate With Visual Editor And Hibernate Tools
Hibernate With Visual Editor And Hibernate Tools
 
Genetic Algorithm For Job Shop Problem
Genetic Algorithm For Job Shop ProblemGenetic Algorithm For Job Shop Problem
Genetic Algorithm For Job Shop Problem
 
Genetic Algorithm Applied In Travel Salesman Problem
Genetic Algorithm Applied In Travel Salesman ProblemGenetic Algorithm Applied In Travel Salesman Problem
Genetic Algorithm Applied In Travel Salesman Problem
 

Implementation of Smote Algorithm for Imbalanced Classification Problems

  • 1. Implementation of SMOTE algorithm for imbalanced classification problems Marcelo Beckmann Universidade Federal do Rio de Janeiro – COPPE beckmann.marcelo@gmail.com
  • 2. 1.0 - Objetivos Este trabalho tem como objetivo reportar a implementação feita do algoritmo SMOTE proposto por [1] na plataforma de mineração de dados de código livre Weka, bem como demonstrar os resultados do algoritmo implementado, nas mesmas bases de dados avaliadas pelo autor no referido artigo. 1.0 - Introdução Em mineração de dados, um dos principais problemas da atividade de classificação reside no tratamento de conjuntos de dados onde uma das classes possui uma quantidade minoritária de instâncias, onde esse desbalanceamento leva o algoritmo a classificar incorretamente uma instância da classe minoritária como sendo da classe majoritária. Todavia, a classe minoritária, que representa a informação anormal em um conjunto de dados, costuma ser a informação interessante a qual se quer predizer. A abordagem proposta por [1] para o tratamento de problemas desse tipo visa a criação de instâncias sintéticas a partir de k vizinhos mais próximos de uma instância da classe desbalanceada. 2.0 - Implementação O algoritmo foi implementado em Java versão 5.0, como um plugin na plataforma Weka. Por ser basicamente o processo de preparação de dados, o SMOTE foi implementado como um plugin de Filtro, no pacote weka.filters.supervised.instance. Foi criada uma classe com o nome de SMOTE neste pacote. Esta classe estende weka.filters.SimpleBatchFilter e implementa as interfaces weka.core.OptionHandler, weka.core.TechnicalInformationHandler e weka.filters.SupervisedFilter. O algoritmo reside nos métodos process(Instances data), o qual recebe as instâncias da base a ser processada e retorna a base original mais as instâncias sintéticas, e populate(...) que é encarregado de gerar as instâncias sintéticas. Nestes métodos foi implementado o algoritmo propriamente dito, conforme demonstrado no pseudocódigo da página 329 de [1]. Também foram criados os métodos generateNnnList(...) que se encarregará de gerar uma lista de k vizinhos mais próximos (utilizando distância euclidiana), conforme especificado em [9], e processUnderSampling(Instances data), o qual opcionalmente irá retirar randomicamente um percentual de instâncias da classe majoritária. Para maiores detalhes da implementação, vide o código completo no anexo A. A parametrização do algoritmo, pode ser feita em uma caixa de diálogo, conforme demonstrado na figura 2.2, e na tabela 2.1 contém uma descrição detalhada dos parâmetros. O significado de cada parâmetro também pode consultado no botão More da caixa de diálogos da figura 2.2. Parâmetro Símbolo Descrição amountOfSMOTE N Percentual de instâncias sintéticas a serem criadas a partir da classe minoritária. Use múltiplos de 100. k k Número de vizinhos mais próximos minorityClass w Índice da classe minoritária, começando com 0. percentToUndersample U Percentual de instâncias a serem removidas da(s) classe(s) diferente(s) da classe minoritária. Tabela 2.1 – Descrição dos parâmetros utilizados no algoritmo SMOTE.
  • 3. Figura 2.2 – Caixa de diálogo com os parâmetros necessários para utilização do SMOTE a partir da aba Preprocess. 3.0 – Experimentos Para os experimentos foram utilizadas quatro bases avaliadas em [1], e disponibilizadas em [8] (Pima, Satimage, Forest Cover), e mais uma base de balanços e falências disponibilizada por [3]. Outras bases utilizadas em [1] não se encontram disponíveis para download imediato, e serão avaliadas em trabalhos futuros. Repetindo o que foi testado em [1], as bases em estudo possuem problemas de classificação binária, onde uma das classes é desbalanceada. Seguindo ainda o artigo, os experimentos de classificação foram executados com o algoritmo C4.5 e comparados com o SMOTE + C4.5. Para os nossos experimentos, foi utilizado o J48, uma versão mais nova do C4.5. Em todos os experimentos, os conjuntos de dados foram padronizados com o filtro Standarize, e não foi executado um pré-processamento de análise de correlação, outliers e componentes principais. O algoritmo J48 foi parametrizado com os valores padrões fornecidos pelo Weka (-C 0.25 –M 2) As subseções a seguir irão demonstrar os resultados obtidos em cada conjunto de dados com o algoritmo implementado. Pelo SMOTE ser um algoritmo probabilístico, os valores demonstrados neste relatório são os melhores obtidos em 3 execuções..
  • 4. 3.1 – Pima Figura 3.1.1 – Comparativo de AUC entre os algoritmos J48 e SMOTE 400 + J48 para a base Pima. Figura 3.1.2 – Plotagem das instâncias antes e depois da aplicação do SMOTE 400 para a base Pima.
  • 5. J48 SMOTE 400 + J48 Estatísticas Valor Estatísticas Valor Total de instâncias 768 Total de instâncias 1840 Instâncias da classe 1 500 Instâncias da classe 1 500 Instâncias da classe 2 268 Instâncias da classe 2 1340 % Classificações corretas 73,83 % Classificações corretas 86,30 % Classificações incorretas 26,17 % Classificações incorretas 13,70 AUC 70,55 AUC 82,51 Matriz de confusão Matriz de confusão Real/Prev. c1 c2 Real/Prev. c1 c2 c1 407 93 c1 371 129 c2 108 160 c2 123 1217 Tabela 3.1.3 – Resultados e métricas obtidas com o J48 e SMOTE 400 + J48 para a base Pima. Analisando o gráfico da figura 3.1.1, verifica-se um desempenho superior do AUC (82,51) do SMOTE com 400% de aumento sintético dos registros, em relação ao AUC do J48 simples (70,55). Avalia-se ainda a que o comportamento centrado , isto é, nem conservador nem agressivo do classificador [6], se mantém nas duas abordagens. Os gráficos de plotagem de instâncias da figura 3.1.2 demonstram que a criação de instâncias sintéticas aumentou a separabilidade entre classes. Na tabela 3.1.3 verifica-se um aumento de falsos positivos e falsos negativos, apesar do aumento de verdadeiros positivos na classe minoritária c2. Todavia, este aumento de desempenho trata-se de uma melhoria tão sintética quanto as instâncias criadas, pois pode-se concluir que o mecanismo de cálculo de métricas fornecido pelo Weka deveria computar somente as instâncias originais e não as originais + sintéticas. Apesar de não ser citado no artigo, estamos assumindo que para se efetuar uma comparação precisa com o melhor valor obtido para esta base em [1], que foi de 73.07, será necessário remover as instâncias sintéticas.
  • 6. 3.2 – Satimage Figura 3.2.1 – Comparativo de AUC entre os algoritmos J48 e SMOTE 100 + J48 para a base Satimage. Figura 3.2.2 – Plotagem das instâncias antes e depois da aplicação do SMOTE 100 para a base Satimage. Conforme orientação dos autores [8], não se deve utilizar a validação cruzada para a base Satimage, e sim utilizar uma base para treinamento e outra para teste no processo de classificação. Desta maneira, o mecanismo de cálculo do Weka computou corretamente as métricas de classificação. Analisando o gráfico da figura 3.2.1, verifica-se um desempenho superior do AUC (93,26) com SMOTE de 100% de aumento sintético dos registros, em relação ao AUC J48 sem preparação (82,22). Os gráficos de plotagem de instâncias da figura 3.2.2 demonstram a criação de instâncias sintéticas, as quais podem levar a classificações incorretas da classe majoritária, em favor da minoritária (falsos positivos).
  • 7. J48 SMOTE 100 + J48 Estatísticas Valor Estatísticas Valor Total de instâncias 2000 Total de instâncias 2000 Instâncias da classe 1 1789 Instâncias da classe 1 1789 Instâncias da classe 2 211 Instâncias da classe 2 211 % Classificações corretas 94,00 % Classificações corretas 95,80 % Classificações incorretas 6,00 % Classificações incorretas 4,20 AUC 82,22 AUC 93,26 Matriz de confusão Matriz de confusão Real/Prev. c1 c2 Real/Prev. c1 c2 c1 1738 51 c1 1726 63 c2 69 142 c2 21 190 Tabela 3.2.3 – Resultados e métricas obtidas com o J48 e SMOTE 400 + J48 para a base Satimage. Avaliando a tabela 3.2.3, pode-se notar um aumento de verdadeiros positivos na classe minoritária c2, de 142 no J48, para 190 com o SMOTE 100% + J48, bem como a diminuição dos falsos negativos de 69 para 21, o que atesta o bom desempenho do SMOTE. Conforme foi previsto na análise do gráfico 3.2.2, a criação das instâncias sintéticas diminuiu o número de verdadeiros negativos de 1738 para 1726 na classe majoritária c1. Conforme foi citado anteriormente, a separação da base em um conjunto de treinamento e um de teste proporcionou o cálculo correto das métricas, o qual não leva em conta as instâncias sintéticas. Desta maneira, atesta-se que o algoritmo implementado obteve um AUC superior a 89.79, o melhor resultado obtido originalmente com esta base em [1] .
  • 8. 3.3 – Forest Cover Figura 3.3.1 – Comparativo de AUC entre os algoritmos J48 e SMOTE 500 + J48 para a base Forest Cover. Figura 3.3.2 – Plotagem das instâncias antes e depois da aplicação do SMOTE 500 para a base Forest Cover.
  • 9. J48 SMOTE 500 + J48 Estatísticas Valor Estatísticas Valor Total de instâncias 38429 Total de instâncias 52164 Instâncias da classe 1 35682 Instâncias da classe 1 35682 Instâncias da classe 2 2747 Instâncias da classe 2 16482 % Classificações corretas 98,30 % Classificações corretas 98,78 % Classificações incorretas 1,70 % Classificações incorretas 1,22 AUC 92,67 AUC 98,52 Matriz de confusão Matriz de confusão Real/Prev. c1 c2 Real/Prev. c1 c2 c1 35412 270 c1 35406 276 c2 382 2365 c2 359 16123 Tabela 3.3.3 – Resultados e métricas obtidas com o J48 e SMOTE 500 + J48 para a base Forest Cover. Na figura 3.3.1 pode-se avaliar a comparação das duas abordagens, sendo que o SMOTE 500 + J48, quase chegou à classificação perfeita. Na plotagem de instâncias antes e depois do SMOTE (figura 3.3.2), pode-se avaliar que o SMOTE acentuou a separação entre classes. Na matriz de confusão da tabela 3.3.3 pode-se verificar a diminuição de falsos negativos, isto é, menos instâncias minoritárias (c2) foram classificadas incorretamente como majoritárias (c1), e um pequeno aumento de falsos positivos contra a classe majoritária.
  • 10. 3.4 - Bankrupt Figura 3.4.1 – Comparativo de AUC entre os algoritmos J48 e SMOTE 400 + J48 para a base Bankrupt. Figura 3.4.2 – Plotagem das instâncias antes e depois da aplicação do SMOTE 400 para a base Bankrupt.
  • 11. J48 SMOTE 400 + J48 Estatísticas Valor Estatísticas Valor Total de instâncias 116 Total de instâncias 224 Instâncias da classe 1 27 Instâncias da classe 1 135 Instâncias da classe 2 89 Instâncias da classe 2 89 % Classificações corretas 81,03 % Classificações corretas 91,07 % Classificações incorretas 18,97 % Classificações incorretas 8,93 AUC 69,58 AUC 90,10 Matriz de confusão Matriz de confusão Real/Prev. c1 c2 Real/Prev. c1 c2 c1 13 14 c1 128 7 c2 8 81 c2 13 76 Tabela 3.4.3 – Resultados e métricas obtidas com o J48 e SMOTE 400 + J48 para a base Bankrupt. Analisando o gráfico da figura 3.4.1, verifica-se um desempenho superior do AUC (90,10) do SMOTE com 400% de aumento sintético dos registros, em relação ao AUC do J48 (69,58) simples. Avalia-se ainda a que o comportamento centrado , isto é, nem conservador nem agressivo do classificador [6], também se mantém nas duas abordagens. Os gráficos de plotagem de instâncias da figura 3.4.2 demonstram que a criação de instâncias sintéticas aumentou a separabilidade entre as classes. Na matriz de confusão da tabela 3.4.3, pode-se verificar uma diminuição de falsos positivos de 14 para 7, e a diminuição de acertos da classe majoritária (c2), em favor da classe minoritária (c1). Esta base não faz parte dos experimentos efetuados em [1].
  • 12. 4.0 – Conclusão Conjunto Melhor J48 100 200 300 400 500 de Dados desempen SMOTE SMOTE SMOTE SMOTE SMOTE ho em [1] Pima 73,07 70,55 77,60 81,19 80,02 81,43 82,51 Satimage 89,79 82,22 91,56 91,34 89,83 88,67 93,26 Forest 98,49 92,67 96,29 97,45 97,94 98,18 98,52 Cover Bankrupt - 69,58 75,27 80,68 80,89 90,06 90,10 Tabela 4.1 – Comparação dos resultados obtidos anteriormente em [1], com os resultados obtidos com o J48 e os resultados obtidos com diversos percentuais de SMOTE + J48. Em todos os percentuais de SMOTE + J48, os valores de AUC obtidos no experimento mantiveram-se superiores em relação ao J48 simples e aos melhores desempenhos obtidos em [1], conforme pode ser visto na tabela 4.1. Com exceção da base Satimage, que utilizou um conjunto de treinamento e outro de teste, as métricas fornecidas pelo Weka, as quais foram replicadas no Matlab para a geração dos gráficos, não levaram em consideração somente as instâncias originais, portanto, neste trabalho não podemos atestar com precisão que o SMOTE obteve um resultado superior nas bases Pima, Forest Cover e Bankrupt. Entretanto, nos experimentos ocorreu a diminuição de falsos negativos e falsos positivos, mesmo com a adição de instâncias sintéticas, o que, juntamente com o bom resultado alcançado com a base Satimage, fornecem indícios de bom desempenho do classificador implementado. 5.0 – Trabalhos futuros Apesar de [1] não citar que as instâncias sintéticas deveriam ser removidas para se computar as métricas de classificação, estamos assumindo esta condição, por ser a alternativa mais plausível, e portanto, será efetuado um ajuste no algoritmo, para que a plataforma Weka possa calcular as métricas de classificação levando em conta somente as instâncias originais. Serão efetuados experimentos com outros conjuntos de dados utilizados em [1], os quais não estão disponíveis para download público. Todavia, estes experimentos dependem da colaboração dos responsáveis pelos respectivos conjuntos de dados. 6.0 – Referências [1] Nitesh V. Chawla, Kevin W. Bowyer, Lawrence O. Hall, W. Philip Kegelmeyer - SMOTE: Synthetic Minority Over-sampling Technique Journal of Artificial Inteligence Research 16 - AI Access Foundation and Morgan Kaufmann - pp. 321-357 (2002). [2] Chawla, N., Bowyer, K., Hall, L., & Kegelmeyer, P. – SMOTE: Synthetic Minority Over-sampling TEchnique. In International Conference of Knowledge Based Computer Systems, pp. 46–57 - National Center for Software Technology, Mumbai, India, Allied Press (2000) [3] Américo, Rui - Mineração de Dados para Melhor Avaliação de Risco de Crédito em Empresas Brasileiras de Capital Aberto - COPPE - Universidade Federal do Rio de Janeiro (2007)
  • 13. [4] Evsukoff, Alexandre - Toolbox Matlab – COPPE - Universidade Federal do Rio de Janeiro (2007) [5] Evsukoff, Alexandre – Material de aula – COC786 Aprendizado Estatístico Computacional – COPPE - Universidade Federal do Rio de Janeiro (2007) [6] Fawcett, Tom – ROC Graphs: Notes and Pratical Considerations for Ressearchers – HP Laboratories (2004) [7] Suman, Sanjeev; Laddhad , Kamlesh; Deshmukh,Unmesh - Methods for Handling Highly Skewed Datasets - CSE, IIT Bombay, Mumbai (2005) [8] Blake, C., & Merz, C. - UCI Repository of Machine Learning Databases - http://www.ics.uci.edu/~mlearn/~MLRepository.html - Department of Information and Computer Sciences, University of California, Irvine (1998) [9] Hastie, Trevor; Tibshirani, Robert; Friedman, Jerome – The Elements of Statistical Learning, Data Mining, Inference, and Prediction – Cap. 13 - Springer Series in Statistics (2001) [10] Ian H. Witten and Eibe Frank (2005) quot;Data Mining: Practical machine learning tools and techniquesquot;, 2nd Edition, Morgan Kaufmann, San Francisco, 2005. [11] Java Standard Development Kit versão 1.5 – Sun Microsystems Inc. 2005 (c) – java.sun.com [12] Matlab versão 7.10 – Mathworks Inc. 2005 (c) – www.mathworks.com
  • 14. Apêndice A – Código fonte package weka.filters.supervised.instance; import java.util.*; weka.core.*; import weka.core.Capabilities.Capability; import weka.core.TechnicalInformation.Field; import weka.core.TechnicalInformation.Type; import weka.filters.SimpleBatchFilter; import weka.filters.SupervisedFilter; import public class SMOTE extends SimpleBatchFilter implements SupervisedFilter, OptionHandler, TechnicalInformationHandler { /** * */ private static final long serialVersionUID = -2703039882958523000L; /** Number of references */ private int k = 2; private int N_amountOfSMOTE = 100; private int w_minorityClass = 0; private int U_percentToUndersample = 0; // inner class to hold a pair of doubles // (for maintaining a running list of nearest neighbors) class ClassDistance { double _class; double distance; int index; } public SMOTE() { } /** * Returns the description of the classifier. * * @return description of the KNN class. */ public String globalInfo() { return quot;Implementation of SMOTE (Syntethic Minority Over-sampling Technique), quot; + quot;aplied over a KNN algorithm, in order to improve the classification quot; + quot;with imbalanced datasets.nnquot; + quot;For more information see:nnquot; + getTechnicalInformation().toString(); } /** * sets k * * @param new_k * new k value. */ public void setK(int new_k) { k = new_k; } /** * gets k * * @return k */ public int getK() { return k;
  • 15. } protected void processUnderSampling(Instances data) { // Obtain the samples from class w if (U_percentToUndersample == 0) { return; } Enumeration en = data.enumerateInstances(); int T = data.numInstances(); int totalToUndersample = T * U_percentToUndersample / 100; int count = 0; Random r = data.getRandomNumberGenerator(System.currentTimeMillis()); while (count <= totalToUndersample) { // Sorts an instance to be eliminated int index = (int) (r.nextDouble() * (T - count)); Instance instance = data.instance(index); if (instance.classIndex() != w_minorityClass) { try { data.delete(index); count++; } catch (NullPointerException e) { e.printStackTrace(); data.delete(index); } } } } protected Instances determineOutputFormat(Instances inputFormat) throws Exception { return inputFormat; } protected Instances process(Instances data) throws Exception { // Obtain the samples from class w Instances samples = new Instances(data, 0); Enumeration en = data.enumerateInstances(); while (en.hasMoreElements()) { Instance instance = (Instance) en.nextElement(); if (instance.classValue() == w_minorityClass) { samples.add(instance); } } int T = samples.numInstances(); /* * IF N is less than 100%, randomize the minority class samples as only * a random percent of them will be SMOTEd */ if (N_amountOfSMOTE < 100) { T = (int) ((N_amountOfSMOTE / 100.0) * T); N_amountOfSMOTE = 100; } /* The amount of SMOTE is assumed to be in integral multiples of 100 */ N_amountOfSMOTE = (int) (N_amountOfSMOTE / 100.0); // Keeps a count of number of synthetic samples generates, intialized to // 0 int newindex = 0; // Instances for synthetic samples Instances synthetics = new Instances(data, 0); /* * Compute k nearest neighbors for i, and save the indices in the * nnarray */ Random random = data.getRandomNumberGenerator(System.currentTimeMillis()); random.setSeed(System.currentTimeMillis());
  • 16. en = samples.enumerateInstances(); while (en.hasMoreElements()) { Instance instance = (Instance) en.nextElement(); // Compute k nearest neighbors for i List knnList = generateNnnList(instance, data); // List knnList = generateNnnList(instance, samples); populate(N_amountOfSMOTE, instance, knnList, synthetics, random, data); newindex++; } if (U_percentToUndersample > 0) { processUnderSampling(data); } en = synthetics.enumerateInstances(); while (en.hasMoreElements()) { Instance synthetic = (Instance) en.nextElement(); data.add(synthetic); } return data; } /* Function to generate synthetic samples */ protected void populate(int N, Instance sample, List knnList, Instances synthetics, Random random, Instances data) { // Number of attributes int numattrs = synthetics.numAttributes(); while (N != 0) { /* * Choose a random number between 1 and k, call it nn. This step * chooses one of the k nearest neighbors of i */ int nn = (int) (Math.random() * knnList.size()); Instance neighbor = data .instance(((ClassDistance) knnList.get(nn)).index); Instance synthetic = (Instance) sample.copy(); // new // Instance(sample); for (int i = 0; i < numattrs - 1; ++i) { // Proccess all the attributes, less the class attribute if (sample.classIndex() != i) { double dif = neighbor.value(i) - sample.value(i); double gap = random.nextDouble(); synthetic.setValue(i, sample.value(i) + gap + dif); } } synthetic.setClassValue(sample.classValue()); synthetics.add(synthetic); N--; } } protected LinkedList generateNnnList(Instance instance, Instances data) { LinkedList knnList = new LinkedList(); double subtotal; // DoublePair classDistance = new DoublePair(0, 0); // compute distances from the instance to all instances in training set for (int i = 0; i < data.numInstances(); i++) { subtotal = 0; for (int j = 0; j < instance.numAttributes(); j++) { if (j != instance.classIndex()) { // Euclidean subtotal += Math.pow((data.instance(i).value(j) - instance .value(j)), 2.0); } } subtotal = Math.sqrt(subtotal);
  • 17. // manage the current k nearest neighbors for (int j = 0; j < k; j++) { if (knnList.size() < k) { if (j == knnList.size()) { ClassDistance classDistance = new ClassDistance(); classDistance._class = data.instance(i).classValue(); classDistance.distance = subtotal; classDistance.index = i; knnList.addLast(classDistance); break; } } if (subtotal < ((ClassDistance) knnList.get(j)).distance) { ClassDistance classDistance = new ClassDistance(); classDistance._class = data.instance(i).classValue(); classDistance.distance = subtotal; classDistance.index = i; knnList.add(j, classDistance); if (knnList.size() > k) { knnList.remove(k); } break; } } } return knnList; } // ---------------------------------------------------------------------------- public Capabilities getCapabilities() { Capabilities result = super.getCapabilities(); // attributes result.enable(Capability.NOMINAL_ATTRIBUTES); result.enable(Capability.NUMERIC_ATTRIBUTES); result.enable(Capability.DATE_ATTRIBUTES); result.enable(Capability.RELATIONAL_ATTRIBUTES); // result.enable(Capability.MISSING_VALUES); // class result.enable(Capability.NOMINAL_CLASS); result.enable(Capability.MISSING_CLASS_VALUES); // other // result.enable(Capability.ONLY_MULTIINSTANCE); return result; } public TechnicalInformation getTechnicalInformation() { TechnicalInformation result; result = new TechnicalInformation(Type.INPROCEEDINGS); result.setValue(Field.AUTHOR, quot;Nitesh V. Chawla, Kevin W. Bowyer, Lawrence O. Hall, W. Philip Kegelmeyer.quot; + quot;nImplemented in Weka by Marcelo Beckmann quot; + quot;- Universidade Federal do Rio de Janeiro - COPPE/PECquot;); result.setValue(Field.TITLE, quot;nSMOTE: Synthetic Minority Over-sampling TEchniquequot;); result.setValue(Field.BOOKTITLE, quot;Journal of Artificial Inteligence Research 16quot;); result.setValue(Field.EDITOR, quot;AI Access Foundation and Morgan Kaufmannquot;); result.setValue(Field.YEAR, quot;2002quot;); result.setValue(Field.PAGES, quot;321-357quot;); return result; } public String percentToUndersampleTipText() { return quot;Percent of instances to be undersampled.quot;; } public String kTipText() { return quot;Number of Nearest Neighbors.quot;; }
  • 18. public String amountOfSMOTETipText() { return quot;Amount of SMOTE N% to be created. Use multiples of 100.quot;; } public String minorityClassTipText() { return quot;Index of minority class, starting with 0.quot;; } public Enumeration listOptions() { Vector result = new Vector(); result.addElement(new Option( quot;tNumber of Nearest Neighbors (default 2).quot;, quot;Kquot;, 0, quot;-K <number of references>quot;)); result .addElement(new Option( quot;tAmount of SMOTE N% to be created (default 100). Use multiples of 100.quot;, quot;Nquot;, 0, quot;-N <percent of SMOTEd instances to be created>quot;)); result.addElement(new Option( quot;tIndex of minority class, starting with 0 (default 0).quot;, quot;wquot;, 0, quot;-w <Index of minority class>quot;)); return result.elements(); } public void setOptions(String[] options) throws Exception { // setDebug(Utils.getFlag('D', options)); String option = Utils.getOption('k', options); if (option.length() != 0) k = Integer.parseInt(option); else k = 1; option = Utils.getOption('N', options); if (option.length() != 0) N_amountOfSMOTE = Integer.parseInt(option); else N_amountOfSMOTE = 10; option = Utils.getOption('w', options); if (option.length() != 0) N_amountOfSMOTE = Integer.parseInt(option); else N_amountOfSMOTE = 10; option = Utils.getOption('U', options); if (option.length() != 0) U_percentToUndersample = Integer.parseInt(option); else U_percentToUndersample = 10; } /** * Gets the current option settings for the OptionHandler. * * @return the list of current option settings as an array of strings */ public String[] getOptions() { Vector result; result = new Vector(); // if (getDebug()) // result.add(quot;-Dquot;); result.add(quot;-Nquot;); result.add(quot;quot; + N_amountOfSMOTE); result.add(quot;-kquot;); result.add(quot;quot; + k); result.add(quot;-wquot;); result.add(quot;quot; + w_minorityClass);
  • 19. result.add(quot;-Uquot;); result.add(quot;quot; + U_percentToUndersample); return (String[]) result.toArray(new String[result.size()]); } public int getAmountOfSMOTE() { return N_amountOfSMOTE; } public void setAmountOfSMOTE(int n) { N_amountOfSMOTE = n; } public int getMinorityClass() { return w_minorityClass; } public void setMinorityClass(int w) { this.w_minorityClass = w; } public int getPercentToUndersample() { return U_percentToUndersample; } public void setPercentToUndersample(int toUndersample) { U_percentToUndersample = toUndersample; } /** * Main method for testing this class. * * @param argv * should contain arguments to the filter: use -h for help */ public static void main(String[] argv) { runFilter(new SMOTE(), argv); } }