2017-01-27 9 views
0

Я новичок на эту тему. То, что я пытаюсь сделать, - собрать много SVM для одного и того же набора данных с разными параметрами (в будущем я надеюсь, что это будет другая сигнатура изображений), затем предсказать каждый SVM и принять в основном найденный класс.Не могу заставить SVM работать так, как я ожидал

Я попытался прочитать код многих людей о тренировке изображений SVM, но не мог понять, что я делаю неправильно в своем коде. Что я пытаюсь, svm.Predict всегда возвращает 0.

Любая помощь или подсказка очень оценена.

internal class SVMClassifier 
    { 
     Dictionary<int, string> classIndex_name; 
     List<SVM> svms; 

     internal void Train(string trainFolder) 
     { 
      this.classIndex_name = new Dictionary<int, string>(); 
      Dictionary<int, List<Mat>> class_mats = getMats(trainFolder, this.classIndex_name); 
      this.svms = new List<SVM>(); 


      Mat samples; Mat responses; 
      getTrainingData(class_mats, out samples, out responses); 
      svms.Add(trainSVM(samples, responses)); 
      svms.Add(trainSVM(samples, responses, SVM.SvmType.CSvc, SVM.SvmKernelType.Linear, 0d, 0d, 10d, TermCritType.Iter | TermCritType.Eps, 1000, 0.000001d, 0d, 0d)); 
      svms.Add(trainSVM(samples, responses, SVM.SvmType.CSvc, SVM.SvmKernelType.Rbf, 100d, 100d, 1d, TermCritType.Iter | TermCritType.Eps, 1000, 0.000001d, 0.1d, 0.5d)); 

      samples.Dispose(); responses.Dispose(); 

      foreach (Mat mat in class_mats.Values.SelectMany((a) => a)) 
       mat.Dispose(); 
     } 
     private static Dictionary<int, List<Mat>> getMats(string trainFolder, Dictionary<int, string> classIndex_name) 
     { 
      Dictionary<int, List<Mat>> class_mats = new Dictionary<int, List<Mat>>(); 
      DirectoryInfo diTrain = new DirectoryInfo(trainFolder); 
      int i = 0; 
      foreach (var di in diTrain.GetDirectories())//classes are according to the directories 
      { 
       var dirName = di.Name; 
       classIndex_name[i] = dirName; 
       var fileNames = di.GetFiles().Select((a) => a.FullName).ToList(); 
       fileNames.Sort(new Dece.Misc.NumericSuffixFileFullNameComparer()); 
       class_mats[i] = fileNames.Select((a) => getMat(a, true)).ToList(); 
       i++; 
      } 
      return class_mats; 
     } 

     private static SVM trainSVM(Mat samples, Mat responses, 
      SVM.SvmType? svm_Type = null, SVM.SvmKernelType? svm_KernelType = null, double? gamma = null, double? degree = null, double? c = null, 
      TermCritType? criteriaType = null, int? criteriaMaxCount = null, double? criteriaEps = null, double? p = null, double? nu=null) 
     { 
      SVM svm = new SVM(); 
      if (svm_Type != null) svm.Type = (SVM.SvmType)svm_Type; 
      if (svm_KernelType != null) svm.SetKernel((SVM.SvmKernelType)svm_KernelType); 
      if (gamma != null) svm.Gamma = (double)gamma; 
      if (degree != null) svm.Degree = (double)degree; 
      if (c != null) svm.C = (double)c; 

      if ((criteriaType != null) || (criteriaMaxCount != null) || (criteriaEps != null)) 
      { 
       var t = new MCvTermCriteria((int)criteriaMaxCount, (double)criteriaEps); 
       if (criteriaType != null) t.Type = (TermCritType)criteriaType; 
       svm.TermCriteria = t; 
      } 


      if (p != null) svm.P = (double)p; 
      if (nu != null) svm.Nu = (double)nu; 

      if (!svm.Train(samples, DataLayoutType.RowSample, responses)) 
       throw new Exception(); 
      return svm; 
     } 

     private static void getTrainingData(Dictionary<int, List<Mat>> class_mats, out Mat samples, out Mat responses) 
     { 
      samples = null; 
      List<int> lstResp = new List<int>(); 
      foreach (int cls in class_mats.Keys) 
      { 
       int count = 0; 
       foreach (Mat mat in class_mats[cls]) 
        using (var desc = mat.Reshape(0, 1)) 
        { 
         if (samples == null) 
          samples = new Mat(desc.Cols, 0, desc.Depth, 1); 
         samples.PushBack(desc); 
         count += desc.Rows; 
        } 
       for (int i = 0; i < count; i++) 
        lstResp.Add(cls); 
      } 

      //responses = new Mat(new Size(lstResp.Count, 1), DepthType.Cv32S, 1); 
      //for (int i = 0; i < lstResp.Count; i++) 
      // responses.SetValue(0, i, lstResp[i]); 

      responses = new Mat(new Size(1, lstResp.Count), DepthType.Cv32S, 1); 
      for (int i = 0; i < lstResp.Count; i++) 
       responses.SetValue(i, 0, lstResp[i]); 

      if (samples.Depth != DepthType.Cv32F) 
       samples.ConvertTo(samples, DepthType.Cv32F); 

      CvInvoke.Normalize(samples, samples, -1, 1, NormType.MinMax); 
     } 

     internal void Detect(IEnumerable<string> fileNames, Action<ShapeInfo> detected) 
     { 
      foreach (var fn in fileNames) 
       using (Mat mat = getMat(fn, false)) 
       { 
        { 
         using (var samples = mat.Reshape(0, 1)) 
         { 
          if (samples.Depth != DepthType.Cv32F) 
           samples.ConvertTo(samples, DepthType.Cv32F); 
          CvInvoke.Normalize(samples, samples, -1, 1, NormType.MinMax); 
          foreach (var svm in this.svms) 
          { 
           Mat res = new Mat(); 
           float p0 = svm.Predict(samples, res, 0); 
           float p1 = svm.Predict(samples, res, 1); 
           float p2 = svm.Predict(samples, res, 2); 
           float p3 = svm.Predict(samples, res, 3); 
           float p4 = svm.Predict(samples, res, 4); 
           float p = svm.Predict(samples, res); 

           foreach (var val in toIEnumerable(p0, p1, p2, p3, p4, p)) 
            if (val != 0f) 
            { 
             System.Windows.Forms.MessageBox.Show("never enters here :("); 
            } 
          } 
         } 
        } 
       } 
     } 

     private static Mat getMat(string fn, bool train) 
     { 
      var mat = new Mat(fn, ImreadModes.Grayscale); 
      mat.Resize(new Size(128, 128)); 
      return mat; 
     } 
     private static IEnumerable<T> toIEnumerable<T>(params T[] items) 
     { 
      if (items != null) 
       foreach (var item in items) 
        yield return item; 
     } 

    } 

расширение Mat.SetValue берется из here.

Я надеюсь, что такой вопрос подходит для формата этого сайта. Если не этот вопрос может быть закрыт-стертый, не проблема. Я пытаюсь понять, как мы должны тренировать SVM с изображениями.

ответ

0

Да, я глуп. Проблема заключалась в отправке пустой функции Mat to Predict. Когда я попробовал null вместо этого, я начал получать предсказания класса. (Я все еще не понимаю почему.)

Проблема классификации заставляет меня чувствовать себя глупым. Любые комментарии о том, как я использую svm, что можно сделать, - это хорошо.

 internal void Detect(IEnumerable<string> fileNames, Action<ShapeInfo> detected) 
     { 
      foreach (var fn in fileNames) 
       using (Mat mat = getMat(fn, false)) 
       { 
        { 
         using (var samples = mat.Reshape(0, 1)) 
         { 
          if (samples.Depth != DepthType.Cv32F) 
           samples.ConvertTo(samples, DepthType.Cv32F); 
          CvInvoke.Normalize(samples, samples, -1, 1, NormType.MinMax); 
          foreach (var svm in this.svms) 
          { 
           float p = svm.Predict(samples, null); 

          } 
         } 
        } 
       } 
     }