• Save
Implementation of Smote Algorithm for Imbalanced Classification Problems
Upcoming SlideShare
Loading in...5
×
 

Implementation of Smote Algorithm for Imbalanced Classification Problems

on

  • 1,467 views

 

Statistics

Views

Total Views
1,467
Views on SlideShare
1,464
Embed Views
3

Actions

Likes
0
Downloads
0
Comments
0

2 Embeds 3

https://www.facebook.com 2
http://www.lmodules.com 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Implementation of Smote Algorithm for Imbalanced Classification Problems Implementation of Smote Algorithm for Imbalanced Classification Problems Document Transcript

  • 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); } }