/// <summary> /// Construit un classificateur de test en cherchant la meilleure /// valeur du seuil. /// FeatureIndex est le numero d'index de la caractéristique. /// </summary> public static TestWeakClassifier Train(TestImage[] Tests, double ValidWeight, FeatureValues Feature) { if (Feature.Values == null) // Uncached values Feature.Values = FeatureValue.ComputeAllValuesSorted(Tests, Feature.Feature); // With the default values, the positive classifier says always // no. So it scores wrong for all valid tests. var positiveError = ValidWeight; // Iterate all feature's values, ascending var best = new TestWeakClassifier(Feature, Feature.Values[0].Value, 1, positiveError); // Select the threshold with the lowest error weight for (var iTest = 0; iTest < Feature.Values.Length; iTest++) { if (Tests[Feature.Values[iTest].TestIndex].Valid) { positiveError -= Tests[Feature.Values[iTest].TestIndex].Weight; if (positiveError < best.Errors) { best = new TestWeakClassifier(Feature, Feature.Values[iTest].Value + 1, 1, positiveError); } } else { positiveError += Tests[Feature.Values[iTest].TestIndex].Weight; var negativeError = 1.0 - positiveError; if (negativeError < best.Errors) { best = new TestWeakClassifier(Feature, Feature.Values[iTest].Value - 1, -1, negativeError); } } } return best; }
/// <summary> /// Charge un ensemble d'images de test d'apprentissage, initialise /// les poids des tests et calcule les valeurs de chaque caractéristique. /// </summary> private static Tuple<TestImage[], FeatureValues[]> LoadTestsSet(string TestsDir) { var goodDir = Path.Combine(TestsDir, "good"); var badDir = Path.Combine(TestsDir, "bad"); var good = LoadImages(goodDir); var bad = LoadImages(badDir); // Init default weights values var goodWeight = 1.0 / (2 * good.Length); var badWeight = 1.0 / (2 * bad.Length); var tests = new TestImage[good.Length + bad.Length]; // Save default weights and status (valid/invalid) and // fusion good & bad sets for (var i = 0; i < good.Length; i++) { tests[i] = new TestImage(good[i], goodWeight, true); } for (var i = good.Length; i < good.Length + bad.Length; i++) { tests[i] = new TestImage(bad[i - good.Length], badWeight, false); } // Compute features's values var featuresValues = ComputeFeaturesValues(tests); return Tuple.Create(tests, featuresValues); }
/// <summary> /// Retourne un tableau a deux dimensions contenenant les valeurs /// calculées de toutes les caractéristiques pour tous les tests. /// int[feature,test]. /// </summary> private static FeatureValues[] ComputeFeaturesValues(TestImage[] Tests) { // TODO: Windows compatibility if (Environment.OSVersion.Platform != PlatformID.Unix) throw new NotImplementedException(); Func<int> AvailableMemory = () => { return File.ReadAllLines("/proc/meminfo") .Where(elem => elem.StartsWith("MemFree") || elem.StartsWith("Buffers") || elem.StartsWith("Cached")) .Select(elem => elem.Split(' ')) .Aggregate(0, (acc, values) => acc + int.Parse(values[values.Length - 2])); }; // List all features of a standard 24x24 window var features = Window.ListFeatures().ToArray(); var featuresValues = new FeatureValues[features.Length]; Parallel.For(0, features.Length, (iFeature) => { //for (var iFeature = 0; iFeature < FeaturesList.Length; iFeature++) { if (AvailableMemory() > Config.MinFreeMemory) { var values = FeatureValue.ComputeAllValuesSorted(Tests, features[iFeature]); featuresValues[iFeature] = new FeatureValues(features[iFeature], values); } else featuresValues[iFeature] = new FeatureValues(features[iFeature], null); }); //} return featuresValues; }