/// <summary> /// Cálcula o valor da entropia (atributo valoresClasseMeta.Atributo) /// </summary> /// <param name="valoresClasseMeta">Classe meta a ser calculada entropia</param> /// <returns>Retorna a entropia do atributo</returns> private double CalcularEntropia(Atributo valoresClasseMeta) { //Encontrar todas as variações de valores dentro dos exemplos para o atributo var valoresDistintos = valoresClasseMeta.RetornaValoresDistintos(); //Total de informações (j) da fórmula float totalInformacoes = valoresClasseMeta.valores.Count; double entropia = 0; //Proporção de casos foreach (var valorDistinto in valoresDistintos) { float divisaoCasosTotal = valoresClasseMeta.RetornaProporcaoCasos(valorDistinto.ToString()) / totalInformacoes; entropia += (divisaoCasosTotal) * (Math.Log(divisaoCasosTotal, 2)); } if (entropia < 0) { entropia *= -1; } return(entropia); }
/// <summary> /// Calcular a informação de ganho /// </summary> /// <returns></returns> private double CalcularGanho(double entropia, Atributo valoresClasseMeta, Atributo valoresAtributoCalculo) { double ganho = 0; //Lista com a soma dos (D) List <double> listaCalculoD = new List <double>(); if (valoresAtributoCalculo.TipoAtributo == Tipo.Categorico) { #region Tipo diferente de número //Retorna os valores distintos dentro da coluna var valoresDistAtrCalculo = valoresAtributoCalculo.RetornaValoresDistintos(); //Sobre cada atributo fazer cada possibilidade foreach (var valor in valoresDistAtrCalculo) { //Total de casos deste valor dentro da coluna float totalCasos = valoresAtributoCalculo.RetornaProporcaoCasos(valor.ToString()); //Retorna os diferentes valores contidos dentro da classeMeta para esse valor var casosClasseMeta = valoresAtributoCalculo.RetornaCasosOutroExemplo(valor.ToString(), valoresClasseMeta.valores); double casosSomados = 0; foreach (var caso in casosClasseMeta) { double divisao = caso.Value / totalCasos; casosSomados += divisao * (Math.Log(divisao, 2)); } double calculoD = (totalCasos / valoresAtributoCalculo.valores.Count) * casosSomados; listaCalculoD.Add(calculoD < 0 ? calculoD *= -1 : calculoD); } #endregion } else if (valoresAtributoCalculo.TipoAtributo == Tipo.Contínuo) { #region Ganho para números, realiza discretização double valorDiscretizado = Math.Round(valoresAtributoCalculo.Discretizar(), 2, MidpointRounding.AwayFromZero); //Conjunto maior float totalMaior = valoresAtributoCalculo.RetornaCasosConjunto(valorDiscretizado, true); var casosClasseMeta = valoresAtributoCalculo.RetornaCasosOutroExemplo(valorDiscretizado, true, valoresClasseMeta.valores); double casosSomados = 0; foreach (var caso in casosClasseMeta) { float divisao = caso.Value / totalMaior; casosSomados += divisao * (Math.Log(divisao, 2)); } double calculoD = (totalMaior / valoresAtributoCalculo.valores.Count) * casosSomados; listaCalculoD.Add(calculoD < 0 ? calculoD *= -1 : calculoD); //Conjunto menor igual float totalMenorIgual = valoresAtributoCalculo.RetornaCasosConjunto(valorDiscretizado, false); casosClasseMeta = valoresAtributoCalculo.RetornaCasosOutroExemplo(valorDiscretizado, false, valoresClasseMeta.valores); casosSomados = 0; foreach (var caso in casosClasseMeta) { float divisao = caso.Value / totalMenorIgual; casosSomados += divisao * (Math.Log(divisao, 2)); } calculoD = (totalMenorIgual / valoresAtributoCalculo.valores.Count) * casosSomados; listaCalculoD.Add(calculoD < 0 ? calculoD *= -1 : calculoD); #endregion } else { #region Ganho para textos List <string> palavrasTop = new List <string>(); foreach (var valor in valoresAtributoCalculo.RetornaValoresDistintos()) { if (!string.IsNullOrEmpty(valor.ToString())) { foreach (var palavra in valor.ToString().Split(',')) { if (!string.IsNullOrEmpty(palavra) && palavrasTop.Count(p => p.Equals(palavra)) <= 0) { palavrasTop.Add(palavra); } } } } palavrasTop.Add(string.Empty); //Sobre cada atributo fazer cada possibilidade foreach (var valor in palavrasTop) { //Total de casos deste valor dentro da coluna float totalCasos = valoresAtributoCalculo.RetornaProporcaoCasos(valor.ToString()); //Retorna os diferentes valores contidos dentro da classeMeta para esse valor var casosClasseMeta = valoresAtributoCalculo.RetornaCasosOutroExemplo(valor.ToString(), valoresClasseMeta.valores); double casosSomados = 0; foreach (var caso in casosClasseMeta) { double divisao = caso.Value / totalCasos; casosSomados += divisao * (Math.Log(divisao, 2)); } double calculoD = (totalCasos / valoresAtributoCalculo.valores.Count) * casosSomados; listaCalculoD.Add(calculoD < 0 ? calculoD *= -1 : calculoD); } #endregion } //Entropia - (Soma da lista do cálculo do D) ganho = entropia - (listaCalculoD.Sum()); return(ganho); }