【问题标题】:Dataset splitting as train/test/valid at C#在 C# 中将数据集拆分为训练/测试/有效
【发布时间】:2022-01-18 18:46:24
【问题描述】:

我有一个Dictionary<string,List<string>> 的数据。字典的Key 包括class_name,字典的Values 包括图像。毕竟,我在本地 pc 中生成了这个字典作为数据集。但是,我必须在 C# 代码中拆分 train(%80)/test(%10)/valid(%10) 中的所有数据。例如,我选择了 90 张图片,我有 3 个班级,每个班级有 30 张图片。拆分后,Train set class 必须有 24 张图片,test 和 val 分别设置 3 张图片。我该怎么做,有人帮忙吗?我分享一个png来帮助理解。enter image description here

【问题讨论】:

    标签: c# split dataset artificial-intelligence


    【解决方案1】:

    我没有完全掌握你的结构,但假设你的字典有 90 个条目

    var train = new List<KeyValuePair<string,List<string>>>();
    var test = new List<KeyValuePair<string,List<string>>>();
    var valid = new List<KeyValuePair<string,List<string>>>();
    
    int i = 0;
    foreach(var kvp in dictionary90){
      var x = i++ % 10;
      if(x<8)
        train.Add(kvp);
      else if(x<9)
        test.Add(kvp);
      else
        valid.Add(kvp);
    }
    

    它会将您的字典条目以 8:1:1 的比例分布在列表中

    【讨论】:

      【解决方案2】:

      此功能会将您的字典分成 3 个。您可以通过更改循环条件来修改它。如果 List 的计数大于 1(因为使用 Math.Ceiling 函数),它将起作用

      (Dictionary<string, List<string>> trainData, Dictionary<string, List<string>> testData, Dictionary<string, List<string>> validData) SplitData(Dictionary<string, List<string>> data)
      {
          var random = new Random();
      
          var train = new Dictionary<string, List<string>>();
          var test = new Dictionary<string, List<string>>();
          var valid = new Dictionary<string, List<string>>();
      
          foreach (KeyValuePair<string, List<string>> dataClass in data)
          {
              train[dataClass.Key] = dataClass.Value.ToList();
              test[dataClass.Key] = new List<string>();
              valid[dataClass.Key] = new List<string>();
      
              for (int i = 0; i < Math.Ceiling(0.1 * dataClass.Value.Count); i++)
              {
                  int idx = random.Next(train[dataClass.Key].Count);
                  test[dataClass.Key].Add(train[dataClass.Key][idx]);
                  train[dataClass.Key].RemoveAt(idx);
              }
      
              for (int i = 0; i < Math.Ceiling(0.1 * dataClass.Value.Count); i++)
              {
                  int idx = random.Next(train[dataClass.Key].Count);
                  valid[dataClass.Key].Add(train[dataClass.Key][idx]);
                  train[dataClass.Key].RemoveAt(idx);
              }
          }
      
          return (train, test, valid);
      }
      

      【讨论】:

      • 随机使用数据洗牌吗?
      • 是的。如果不想打乱数据,可以使用i变量代替idx
      • 好的,非常感谢。我也对你的解决方案有更多评论。如果我想要那本字典,我该怎么做。例如,我将 %0 到 %80 作为训练数据,将 %80 到 %90 作为验证数据,其余为测试数据。你有什么想法吗?
      • 你想要一个只返回 1 个字典的函数吗?我认为调用SplitDatavar splittedData = SplitData(data);)并使用元组元素之一(var trainData = splittedData.trainData;)更容易
      • 我用 counter 和 break 来处理它。谢谢你的帮助!
      猜你喜欢
      • 2010-11-25
      • 2021-05-09
      • 2019-05-01
      • 2019-12-15
      • 2020-03-17
      • 2018-10-13
      • 1970-01-01
      • 1970-01-01
      • 2021-12-08
      相关资源
      最近更新 更多