//classifies the dataset with ID = id public ActionResult Index(int id) { //remove any data from the trees and nodes tables foreach(var t in db.Trees.ToList()) { db.Trees.Remove(t); } foreach(var n in db.Nodes.ToList()) { db.Nodes.Remove(n); } db.SaveChanges(); Models.DataSet dataset = db.DataSets.Single(i => i.ID == id); List<Instance> instances = db.Instances.Where(i => i.DataSetID == dataset.ID).ToList(); List<Tree> decisionTrees = new List<Tree>(); List<double> successRates = new List<double>(); List<string> correctlyClassifiedInstances = new List<string>(); Tree decisionTree; //stringwriter for exporting to CSV results = new StringWriter(); results.WriteLine("\"Test No.\",\"Predicted Class\",\"Actual Class\""); DataTable dataTable = new DataTable(); dataTable.Columns.Add(new DataColumn("ID")); //performs the following sequence 10 times, as specified for (int j = 0; j < 10; j++) { decisionTree = new Tree { Name = dataset.Name + " Tree" }; db.Trees.Add(decisionTree); db.SaveChanges(); decisionTrees.Add(decisionTree); //generates testing and training lists from the datasets instances: 1/3 testing and 2/3 training int noOfTestingDataInstances = instances.Count / 3; List<Instance> testingInstances = new List<Instance>(); List<Instance> trainingInstances = new List<Instance>(); for (int i = 0; i < noOfTestingDataInstances; i++) { var x = rnd.Next(instances.Count); testingInstances.Add(instances.ElementAt(rnd.Next(instances.Count))); } trainingInstances = instances.Where(i => testingInstances.Contains(i) == false).ToList(); //generates a decision tree based on the training instances attributesUsedSoFar = new List<string>(); CreateDecisionTree(trainingInstances, new Node { EdgeValue = null }, decisionTree.ID, String.Empty, null); //classifies each test instance based on the current decision tree, and computes a list of success rates double successes = 0; double failures = 0; foreach (var i in testingInstances) { string result = classifyInstance(i, decisionTree); results.WriteLine("\"{0}\",\"{1}\",\"{2}\"", j+1, result, i.Class); if (result == i.Class) successes++; else failures++; } results.WriteLine(); double successRate = successes / testingInstances.Count; successRate = Math.Round(successRate, 6); successRates.Add(successRate * 100); Math.Round(successes, 0); correctlyClassifiedInstances.Add(successes.ToString()+"/"+(testingInstances.Count.ToString())); } //outputs the success rates and the decision trees nodes to the view ViewBag.SuccessRates = successRates; ViewBag.CorrectlyClassifiedInstances = correctlyClassifiedInstances; ViewBag.TestInstances = (instances.Count / 3).ToString(); ViewBag.TrainingInstances = (instances.Count - (instances.Count / 3)).ToString(); ViewBag.TotalInstances = instances.Count.ToString(); ViewBag.AverageSuccessRate = Math.Round(successRates.Average(),2); int decisionTreeId = decisionTrees.ElementAt(successRates.IndexOf(successRates.Max())).ID; List<Node> decisionTreeNodes = db.Nodes.Where(i => i.TreeID == decisionTreeId).OrderBy(i=>i.ID).ThenBy(i=>i.ParentID).ToList(); return View(decisionTreeNodes); }
//classifies an instance - returns "" if the instance cannot be classified private string classifyInstance(Instance instance, Tree tree) { Node selectedNode = db.Nodes.Single(i => i.ParentID < 1 && i.TreeID == tree.ID); while (db.Nodes.Where(i => i.ParentID == selectedNode.ID).Count() > 0) { Boolean result = false; List<Node> childNodes = db.Nodes.Where(i => i.ParentID == selectedNode.ID).ToList(); int j = 0; while (result != true) { if (j >= childNodes.Count) return ""; // this is the case where the instance cannot be classified, this can happen occasionally with nominal data Node childNode = childNodes.ElementAt(j); result = checkBranch(instance, selectedNode, childNode); if (result == true) { selectedNode = childNodes.ElementAt(j); } j++; } } return selectedNode.Attribute; }