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