自学习算法 [英] Self Training Algorithm

查看:150
本文介绍了自学习算法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想建立一个自我训练算法针对特定问题。 。为了简单起见,我会敲定下来到简单的例子

I'd like to develop a self training algorithm for a specific problem. To keep things simple i'll nail it down to simple example.

更新:我添加了一个可行的解决方案作为回答下面这个问题

让我们说我有一个庞大的数据库来实体的名单。每个实体是同类型的,具有类型字节的4个属性。

Let's say i have a huge list of entities coming from a database. Each entity is of the same type and has 4 properties of type byte.

public class Entity
{
    public byte Prop1 { get; set; }
    public byte Prop2 { get; set; }
    public byte Prop3 { get; set; }
    public byte Prop4 { get; set; }
}

现在我想测试动态的一个或每个实体的多个属性对一个简单的条件。这基本上意味着,我要测试的此条件的所有属性的所有可能的组合。

Now I'd like to dynamically test one or more property of each entity against a simple condition. Which basically means that i want to test all possible combinations of all properties against this condition.

要完成这件事我已经创建了属性的位掩码。

To get this done I have created a bit mask for the properties.

[Flags]
public enum EEntityValues
{
    Undefined = 0,
    Prop1 = 1,
    Prop2 = 2,
    Prop3 = 4,
    Prop4 = 8,
}

和添加了一个方法来获得位掩码的最大值。 。返回15(1 + 2 + 4 + 8)这个例子

And added an method to get the max value of the bit mask. Which returns 15 (1 + 2 + 4 + 8) for this example.

public static int GetMaxValue<T>() where T : struct
{
    return Enum.GetValues( typeof(T) ).Cast<int>().Sum();
}

目前这个阶段,我能够全部财产组合遍历一个简单的循环。在实施例中第一次迭代的属性为prop1测试中,在第二次迭代Prop2被测试,在第三次迭代为prop1和Prop2进行测试等。

At this stage I'm able to iterate over all property combinations with a simple loop. In example within the first iteration the property Prop1 is tested, on the second iteration Prop2 is tested, on the third iteration Prop1 and Prop2 are tested and so on.

for(int i = 1; i <= GetMaxValue<EEntityValues>(); i++)
{
     EEntityValues flags = (EEntityValues)i;

     if(flags.HasSet(EEntityValues.Prop1))
     {
         ....
     }
}

现在,让我们的实体进入游戏。

Now let's get the entities into the game.

List<Entity> entities = GetEntitiesFromDb();

for(int i = 1; i <= GetMaxValue<EEntityValues>(); i++)
{
     EEntityValues flags = (EEntityValues)i;
     byte minProp1Value = 10, minProp2Value = 20, minProp3Value = 30, minProp4Value = 40;

     foreach(Entitiy entity in entities)
     {
         if(flags.HasSet(EEntityValues.Prop1) && entitiy.Prop1 >= minProp1Value)
         {
              ....
         } else { continue; }

         if(flags.HasSet(EEntityValues.Prop2) && entitiy.Prop2 >= minProp2Value)
         {
              ....
         } else { continue; }
     }
}



那么,这个伟大的工程,如果我的最低值静态的。

Well, this works great if my minimum values are static.

现在,让我们变得更加复杂。当我们还记得,在第一次迭代,我们只是在测试性能为prop1,因为位掩码为1,取值范围为prop1为0..255。我还此属性,其具有1..25​​5的有效范围限定的最小值。此最低值只是跳过foreach循环实体的过滤器。

Now let's get more complicated. As we remember, on the first iteration we are testing property Prop1 only, because the bit mask is 1. The value range for Prop1 is 0..255. I also defined a minimum value for this property which has a valid range of 1..255. This minimum value is just a filter to skip entities in the foreach loop.

现在我想测试的财产为prop1而我升起的最低水平。这些测试都没有问题,所以我不包括他们进入我的样本的一部分

Now i'd like to test the property Prop1 while i'm rising the minimum level. These tests are not part of the problem so i don't include them into my samples.

     byte minProp1Value = 1;

     while(minProp1Value <= 255)
     {
         foreach(Entitiy entity in entities)
         {
              if(flags.HasSet(EEntityValues.Prop1) && entitiy.Prop1 >= minProp1Value)
              {
                  .... // Testing the matching entity and storing the result
              } else { continue; }
         }

         minProp1Value++;
     }

这是简单的一个属性。在第三次迭代我不得不面对2个属性,为prop1和Prop2,因为位掩码为3。

This is simple for a single property. On the third iteration i have to deal with 2 properties, Prop1 and Prop2, because the bit mask is 3.

     byte minProp1Value = 1, minProp2Value = 1;

     while(minProp1Value <= 255)
     {
         while(minProp2Value <= 255)
         {
              foreach(Entitiy entity in entities)
              {
                   ....
              }

              minProp2Value++;
         }

         minProp1Value++;
         minProp2Value = 1;
     }



正如你所看到的,在这个阶段我测试的为prop1和Prop2针对上升的最低水平每一个实体。

As you can see, at this stage i'm testing Prop1 and Prop2 of each entity against a rising minimum level.

对于我处理多个属性我不能硬编码,而循环进入我的代码动态生成套的原因。这就是为什么我在找一个更聪明的解决方案,以测试给定属性集(位掩码)最低值的所有可能的组合。

For the reason that i'm dealing with dynamically generated sets of multiple properties i can't hardcode the while loops into my code. That's why i'm looking for a smarter solution to test all possible combinations of minimum values for the given property-set (bit mask).

推荐答案

休息一会儿,我想出了,似乎适合我的需求的解决方案后。该限制是,所有被测试的属性应该是同一类型具有相同的数值范围,这是好的,我在我的情况,因为所有属性都是抽象的百分比值。

After having a rest i came up with a solution that seems to fit my requirements. The limitation is that all tested properties should be of the same type with the same value range, which is fine for me in my case because all properties are abstract percentage values.

顺便说一句,我不知道如果主题自我学习算法是有点误导这里。有几个方式可以实现这样的解决方案,但如果你不知道你的数据的行为和效果的数值都有,最简单的办法就是暴力破解所有可能的组合,以确定最佳的拟合结果。这就是我在这里展示。

By the way, i'm not sure if the topic "self training algorithm" is a little bit misleading here. There are a couple of ways to implement such a solution, but if you have no idea how your data behave and which effects the values have, the most simple solution is to brute force all possible combinations to identify the best fitting result. That's what i'm showing here.

不管怎么说,用于测试目的,我增加了一个随机数发生器,我的实体类。

Anyways, for testing purpose i added a random number generator to my entity class.

public class Entity
{
    public byte Prop1 { get; set; }
    public byte Prop2 { get; set; }
    public byte Prop3 { get; set; }
    public byte Prop4 { get; set; }

    public Entity()
    {
        Random random = new Random( Guid.NewGuid().GetHashCode() );
        byte[] bytes = new byte[ 4 ];

        random.NextBytes( bytes );

        this.Prop1 = bytes[0];
        this.Prop2 = bytes[1];
        this.Prop3 = bytes[2];
        this.Prop4 = bytes[3];
    }
}



我的掩码保持不变。

My bitmask stays untouched.

[Flags]
public enum EProperty
{
    Undefined = 0,
    Prop1 = 1,
    Prop2 = 1 << 1,
    Prop3 = 1 << 2,
    Prop4 = 1 << 3
}



比我增加了一些新的扩展methodes对付我的位掩码。

Than i added some new extension methodes to deal with my bitmask.

public static class BitMask
{
    public static int GetMaxValue<T>() where T : struct
    {
        return Enum.GetValues(typeof (T)).Cast<int>().Sum();
    }

    public static int GetTotalCount<T>() where T : struct
    {
        return Enum.GetValues(typeof (T)).Cast<int>().Count(e => e > 0);
    }

    public static int GetFlagCount<T>(this T mask) where T : struct
    {
        int result = 0, value = (int) (object) mask;

        while (value != 0)
        {
            value = value & (value - 1);
            result++;
        }

        return result;
    }

    public static IEnumerable<T> Split<T>(this T mask)
    {
        int maskValue = (int) (object) mask;

        foreach (T flag in Enum.GetValues(typeof (T)))
        {
            int flagValue = (int) (object) flag;

            if (0 != (flagValue & maskValue))
            {
                yield return flag;
            }
        }
    }
}



比我写了一个查询生成器

Than i wrote a query builder

public static class QueryBuilder
{
    public static IEnumerable<Entity> Where(this IEnumerable<Entity> entities, EProperty[] properties, int[] values)
    {
        IEnumerable<Entity> result = entities.Select(e => e);

        for (int index = 0; index <= properties.Length - 1; index++)
        {
            EProperty property = properties[index];
            int value = values[index];

            switch (property)
            {
                case EProperty.Prop1:
                    result = result.Where(e => Math.Abs(e.Prop1) >= value);
                    break;
                case EProperty.Prop2:
                    result = result.Where(e => Math.Abs(e.Prop2) >= value);
                    break;
                case EProperty.Prop3:
                    result = result.Where(e => Math.Abs(e.Prop3) >= value);
                    break;              
                case EProperty.Prop4:
                    result = result.Where(e => Math.Abs(e.Prop4) >= value);
                    break;   
            }
        }

        return result;
    }
}



最后我已经准备好运行了培训。

And finally i'm ready to run the training.

    private const int maxThreads = 10;

    private const int minValue = 0;
    private const int maxValue = 100;

    private static IEnumerable<Entity> entities;

    public static void Main(string[] args)
    {
        Console.WriteLine(DateTime.Now.ToLongTimeString());

        entities = Enumerable.Repeat(new Entity(), 10).ToList();

        Action<EProperty[], int[]> testCase = RunTestCase;
        RunSelfTraining( testCase );

        Console.WriteLine(DateTime.Now.ToLongTimeString());
        Console.WriteLine("Done.");

        Console.Read();
    }

    private static void RunTestCase( EProperty[] properties, int[] values ) 
    {         
        foreach( Entity entity in entities.Where( properties, values ) )
        {

        }
    }

    private static void RunSelfTraining<T>( Action<T[], int[]> testCase ) where T : struct
    {
        ParallelOptions parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = maxThreads };

        for (int maskValue = 1; maskValue <= BitMask.GetMaxValue<T>(); maskValue++)
        {
            T mask = ( T ) (object)maskValue;
            T[] properties = mask.Split().ToArray();         

            int variations = (int) Math.Pow(maxValue - minValue + 1, properties.Length);

            Parallel.For(1, variations, parallelOptions, variation =>
            {
                int[] values = GetVariation(variation, minValue, maxValue, properties.Length).ToArray();   
                testCase.Invoke(properties, values);        
            } );
        }
    }

    public static IEnumerable<int> GetVariation( int index, int minValue, int maxValue, int count )
    {
        index = index - 1; 
        int range = maxValue - minValue + 1;

        for( int j = 0; j < count; j++ )
        {
            yield return index % range + minValue;
            index = index / range;
        }
    }
}

这篇关于自学习算法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆