/// <summary> /// Создает массив атрибутов, на основе которых и будем строить дерево решений /// </summary> /// <param name="samples">Таблица c измерениями</param> /// <param name="counOfParameter">ключ первого параметра</param> /// <param name="parametersCount">Количество параметров учавствующих в анализе</param> /// <param name="curveCount">Количество дуг,задаваемые пользователем</param> /// <returns>Массив атрибутов</returns> private Attribute[] CreateAttribute(List <OneRow> samples, int parametersCount, Dictionary <int, string> parameterNames, int curveCount, int defectParameter) { Attribute[] attributes = new Attribute[parametersCount]; int i = 0; foreach (KeyValuePair <int, string> parameterName in parameterNames) { TupleList <decimal, decimal> bordersValue = Borders.AddBordersValue(parameterName.Key, samples, parametersCount, curveCount, defectParameter); attributes[i] = new Attribute(parameterName.Key, bordersValue); i++; } return(attributes); }
/// <summary> /// Создает массив атрибутов, на основе которых и будем строить дерево решений /// </summary> /// <param name="samples">Таблица c измерениями</param> /// <param name="counOfParameter">ключ первого параметра</param> /// <param name="parametersCount">Количество параметров учавствующих в анализе</param> /// <param name="curveCount">Количество дуг,задаваемые пользователем</param> /// <returns>Массив атрибутов</returns> private Attribute[] CreateAttribute(List <OneRow> samples, int parametersCount, int curveCount, int defectParameter) { Attribute[] attributes = new Attribute[samples[0].Input.Count]; int i = 0; foreach (var item in samples[0].Input) { TupleList <decimal, decimal> bordersValue = Borders.AddBordersValue(item.Key, samples, parametersCount, curveCount, defectParameter); attributes[i] = new Attribute(item.Key, bordersValue); i++; } return(attributes); }
/// <summary> /// Упрощает массив пороговых значений /// </summary> /// /// <param name="border">Весь список пороговых значений</param> /// /// <returns>массив пороговых значений </returns> private static TupleList <decimal, decimal> ChangeBorder(List <decimal> border, int parameterNumber) { double accurateStep = SearchStep(border.Count, parameterNumber); var borderValues = new TupleList <decimal, decimal>(); double sumOfValue = 0; for (int i = 0; i < parameterNumber - 1; i++) { if (i == parameterNumber - 2) { borderValues.Add(border[(int)sumOfValue], border[border.Count - 1]); sumOfValue += accurateStep; } else { borderValues.Add(border[(int)sumOfValue], border[(int)(sumOfValue + accurateStep)]); sumOfValue += accurateStep; } } return(borderValues); }
/// <summary> /// Этот метод является основным в построении дерева решений /// </summary> /// <param name="samples">Строит дерево решений на основе предоставленных измерений</param> /// <param Name="attributes"> Список атрибутов на основе которых мы строим дерево</param> /// <returns>Узел дерева </returns></returns?> private TreeNode IMountTree(List <OneRow> samples, Attribute[] attributes, Dictionary <int, string> parameterName, int defectParameterID, int curveCount, int depth) { if (AllSamplesPositives(samples, defectParameterID)) { return(new TreeNode(new Attribute(true), parameterName, samples.Count, 0, depth)); } if (AllSamplesNegatives(samples, defectParameterID)) { return(new TreeNode(new Attribute(false), parameterName, 0, samples.Count, depth)); } mTotal = samples.Count; mTotalPositives = CountTotalPositives(samples, defectParameterID); mEntropySet = Entropy.Calculate(mTotalPositives, mTotal - mTotalPositives); Entropy entropy = new Entropy(samples, attributes, mTotal, mEntropySet, defectParameterID); Attribute bestAttribute = entropy.GetBestAttribute(); //Attribute bestAttribute = GetBestAttribute(samples, attributes); if (bestAttribute == null) { double percent = (double)mTotalPositives / (double)mTotal; if (percent > 0.5) { return(new TreeNode(new Attribute(true), parameterName, mTotalPositives, mTotal - mTotalPositives, depth)); } return(new TreeNode(new Attribute(false), parameterName, mTotalPositives, mTotal - mTotalPositives, depth)); } TreeNode root = new TreeNode(bestAttribute, parameterName, mTotalPositives, mTotal - mTotalPositives, depth); for (int i = 0; i < bestAttribute.values.Count; i++) { int newDepth = depth + 1; List <OneRow> aSample = new List <OneRow>(); //Выбирает все элементы с отрезком значений этого атрибута var query = samples.Where(measurement => (measurement.Input[bestAttribute.AttributeName] >= bestAttribute.values[i].Item1 && measurement.Input[bestAttribute.AttributeName] <= bestAttribute.values[i].Item2)); foreach (var item in query) { aSample.Add(item); } //Выбирает все элементы с отрезком значений этого атрибута //Создает новый список атрибутов, убирая из этого списка лучший атрибут List <Attribute> aAttributes = new List <Attribute>(attributes.Length - 1); for (int j = 0; j < attributes.Length; j++) { if (attributes[j].AttributeName != bestAttribute.AttributeName) { //редактирует пороговые значения атрибута TupleList <decimal, decimal> bordersValue = Borders.AddBordersValue(attributes[j].AttributeName, aSample, aAttributes.Capacity, curveCount, defectParameterID); Attribute att = new Attribute(attributes[j].AttributeName, bordersValue); aAttributes.Add(att); //редактирует пороговые значения атрибута } } //Создает новый список атрибутов, убирая из этого списка лучший атрибут RandomForest c45 = new RandomForest(); TreeNode ChildNode = c45.IMountTree(aSample, (Attribute[])aAttributes.ToArray(), parameterName, defectParameterID, curveCount, newDepth); root.AddTreeNode(ChildNode, bestAttribute.values[i]); } return(root); }
public void ChangeValue(TupleList <decimal, decimal> value) { mValues = value; }
/// <summary> /// Инициализация нового класса атрибут /// </summary> /// <param name="label"> может принимать два значения true или false</param> public Attribute(object Label) { mLabel = Label; mName = -1; mValues = null; }
/// <summary> /// Инициализация нового класса атрибут /// </summary> /// <param name="name">Указывает имя атрибута</param> /// <param name="values">Указывает пороговые значения этого атрибута</param> public Attribute(int name, TupleList <decimal, decimal> values) { mName = name; mValues = values; mValues.Sort(); }
public Attribute(SerializationInfo sInfo, StreamingContext contextArg) { this.mLabel = (object)sInfo.GetValue("mLabel", typeof(object)); this.mName = (int)sInfo.GetValue("mName", typeof(int)); this.mValues = (TupleList <decimal, decimal>)sInfo.GetValue("MValues", typeof(TupleList <decimal, decimal>)); }
/// <summary> /// Создает массив пороговых значений /// </summary> /// <param name="key">ключ атрибута у которого строятся пороговые значения</param> /// <param name="samples">Таблица с измерениями</param> /// <returns>Массив пороговых значений </returns> public static TupleList <decimal, decimal> AddBordersValue(int key, List <OneRow> samples, int parametersCount, int curveCount, int keyOutput) { //TODO: переделать критерий разбиений. Разбиение должно быть более осмысленное. TupleList <decimal, decimal> groceryList = new TupleList <decimal, decimal>(); Dictionary <decimal, int> borderValuesTrue = new Dictionary <decimal, int>(); Dictionary <decimal, int> borderValuesFalse = new Dictionary <decimal, int>(); //Создается множество уникальных значений Dictionary <decimal, int> borderValues = new Dictionary <decimal, int>(); for (int i = 0; i < samples.Count; i++) { decimal valueParameter = samples[i].Input.First(paramater => paramater.Key == key).Value; if (samples[i].OutputBool[keyOutput]) { if (borderValuesTrue.ContainsKey(valueParameter)) { borderValuesTrue[valueParameter] += 1; } else { borderValuesTrue.Add(valueParameter, 1); } } if (!samples[i].OutputBool[keyOutput]) { if (borderValuesFalse.ContainsKey(valueParameter)) { borderValuesFalse[valueParameter] += 1; } else { borderValuesFalse.Add(valueParameter, 1); } } if (borderValues.ContainsKey(valueParameter)) { borderValues[valueParameter] += 1; } else { borderValues.Add(valueParameter, 1); } } List <decimal> bordersValuesTrueList = borderValuesTrue.Keys.ToList(); List <decimal> bordersValuesFalseList = borderValuesFalse.Keys.ToList(); bordersValuesTrueList.Sort(); bordersValuesFalseList.Sort(); List <decimal> newWaveBorderValues = new List <decimal>(); //создается множество уникальных значений int indexTrue = 0; int indexFalse = 0; int automation = 0; indexTrue = ReworkBorderValues(bordersValuesTrueList, indexTrue, bordersValuesFalseList, newWaveBorderValues, ref indexFalse, ref automation); bool end = true; while (end) { if ((indexTrue == bordersValuesTrueList.Count) && (indexFalse == bordersValuesFalseList.Count)) { break; } if (indexTrue == bordersValuesTrueList.Count) { if (indexFalse == bordersValuesFalseList.Count - 1) { newWaveBorderValues.Add(bordersValuesFalseList[bordersValuesFalseList.Count - 1]); break; } newWaveBorderValues.Add(bordersValuesFalseList[indexFalse]); newWaveBorderValues.Add(bordersValuesFalseList[bordersValuesFalseList.Count - 1]); break; } if (indexFalse == bordersValuesFalseList.Count) { if (indexTrue == bordersValuesTrueList.Count - 1) { newWaveBorderValues.Add(bordersValuesTrueList[bordersValuesTrueList.Count - 1]); break; } newWaveBorderValues.Add(bordersValuesTrueList[indexTrue]); newWaveBorderValues.Add(bordersValuesTrueList[bordersValuesTrueList.Count - 1]); break; } decimal trueNumber = bordersValuesTrueList[indexTrue]; decimal falseNumber = bordersValuesFalseList[indexFalse]; switch (automation) { case 0: //Case когда на прошлом этапе мы выбрали False элемент if (falseNumber < trueNumber) { indexFalse++; } else if (falseNumber > trueNumber) { newWaveBorderValues.Add(trueNumber); indexTrue++; automation = 1; } else if (falseNumber == trueNumber) { newWaveBorderValues.Add(falseNumber); indexTrue++; indexFalse++; automation = 2; } break; case 1: if (falseNumber > trueNumber) { indexTrue++; } else if (falseNumber < trueNumber) { newWaveBorderValues.Add(falseNumber); indexFalse++; automation = 0; } else if (falseNumber == trueNumber) { newWaveBorderValues.Add(falseNumber); indexTrue++; indexFalse++; automation = 2; } break; case 2: if (falseNumber > trueNumber) { newWaveBorderValues.Add(trueNumber); indexTrue++; automation = 1; } else if (falseNumber < trueNumber) { newWaveBorderValues.Add(falseNumber); indexFalse++; automation = 0; } else if (falseNumber == trueNumber) { newWaveBorderValues.Add(trueNumber); indexTrue++; indexFalse++; automation = 2; } break; } } newWaveBorderValues = newWaveBorderValues.Distinct().ToList(); Dictionary <decimal, int> borderValuesWithPartipition = new Dictionary <decimal, int>(); int countTrue = 0; int countFalse = 0; if (borderValuesTrue.ContainsKey(newWaveBorderValues[0])) { countTrue = borderValuesTrue[newWaveBorderValues[0]]; } if (borderValuesFalse.ContainsKey(newWaveBorderValues[0])) { countFalse = borderValuesFalse[newWaveBorderValues[0]]; } borderValuesWithPartipition.Add(newWaveBorderValues[0], countTrue + countFalse); for (int index = 1; index < newWaveBorderValues.Count; index++) { borderValuesWithPartipition.Add(newWaveBorderValues[index], 0); foreach (KeyValuePair <decimal, int> pair in borderValuesTrue) { if ((pair.Key > newWaveBorderValues[index - 1]) && (pair.Key <= newWaveBorderValues[index])) { borderValuesWithPartipition[newWaveBorderValues[index]] += pair.Value; } } foreach (KeyValuePair <decimal, int> pair in borderValuesFalse) { if ((pair.Key > newWaveBorderValues[index - 1]) && (pair.Key <= newWaveBorderValues[index])) { borderValuesWithPartipition[newWaveBorderValues[index]] += pair.Value; } } } //List<decimal> bordersValues = borderValues.Keys.ToList(); List <decimal> bordersValues = borderValuesWithPartipition.Keys.ToList(); bordersValues.Sort(); if ((bordersValues.Count > parametersCount) || (bordersValues.Count > curveCount)) { if (parametersCount >= curveCount) { bordersValues = ThresHoldValue(borderValues, curveCount, samples.Count); } else { bordersValues = ThresHoldValue(borderValues, parametersCount, samples.Count); } } else if (bordersValues.Count == 1) { } //int numberBorders = NumberBorders(bordersValues.Count); // TODO: Если количество разветлений будет больше 3 то надо будет переписать весь последующий кусок кода в более адекватном формате if ((bordersValues.Count > parametersCount) || (bordersValues.Count > curveCount)) { if (parametersCount >= curveCount) { groceryList = ChangeBorder(bordersValues, curveCount); } else { groceryList = ChangeBorder(bordersValues, parametersCount); } } else if (bordersValues.Count == 1) { groceryList.Add(bordersValues[0], bordersValues[0]); } else { for (int i = 0; i < bordersValues.Count - 1; i++) { if (i != bordersValues.Count - 2) { groceryList.Add(bordersValues[i], bordersValues[i + 1] - 0.001M); } else { groceryList.Add(bordersValues[i], bordersValues[i + 1]); } } } return(groceryList); }