Esempio n. 1
0
        /// <summary>
        /// Method to convert a given categorical domain into a sepecific <see cref="CategoricalEncodingBase"/>.
        /// See: http://www.kdnuggets.com/2015/12/beyond-one-hot-exploration-categorical-variables.html.
        /// </summary>
        /// <typeparam name="T">
        /// Domain value type.
        /// </typeparam>
        /// <param name="parameterName">
        /// Name of the parameter that uses <paramref name="domain"/>.
        /// </param>
        /// <param name="domain">
        /// The <see cref="DomainBase{T}"/>.
        /// </param>
        /// <returns>
        /// The <see cref="ConvertedCategory{T}"/>.
        /// </returns>
        public ConvertedCategory <T> Encode <T>(string parameterName, CategoricalDomain <T> domain)
        {
            if (string.IsNullOrWhiteSpace(parameterName))
            {
                throw new ArgumentException("String \"parameterName\" must not be null, empty, or whitespace.", nameof(parameterName));
            }

            if (ReferenceEquals(domain, null))
            {
                throw new ArgumentNullException(nameof(domain));
            }

            this.ValidateDomain(domain);
            var categoryValues = domain.PossibleValues.ToArray();
            var categoryToDoubleRepresentation = new Dictionary <T, double[]>();
            var domainRepresentationLength     = this.NumberOfGeneratedColumns(domain);

            for (var index = 0; index < categoryValues.Length; index++)
            {
                var currentCategoricalValue = categoryValues[index];
                var singleValueEncoding     = this.EncodeNextValue(index, domainRepresentationLength);
                categoryToDoubleRepresentation.Add(currentCategoricalValue, singleValueEncoding);
            }

            var categoryEncoding = new ConvertedCategory <T>(parameterName, categoryToDoubleRepresentation, domain);

            return(categoryEncoding);
        }
Esempio n. 2
0
        /// <summary>
        /// Creates a <see cref="CategoricalDomain{T}"/> consisting of <paramref name="members"/> strings of the form
        /// "CategoricalValue_{number}". Iteration starts at 1.
        /// </summary>
        /// <param name="members">Number of categories.</param>
        /// <returns>The created <see cref="CategoricalDomain{T}"/>.</returns>
        private CategoricalDomain <string> GetTestDomain(int members)
        {
            var domainMembers = Enumerable.Range(1, members).Select(m => $"CategoricalValue_{m}").ToList();
            var domain        = new CategoricalDomain <string>(domainMembers);

            return(domain);
        }
Esempio n. 3
0
        /// <summary>
        /// Converts this node to an <see cref="OrNode{T}"/>.
        /// </summary>
        /// <typeparam name="T">The type of values the represented parameter can take.</typeparam>
        /// <returns>The converted <see cref="OrNode{T}"/>.</returns>
        /// <exception cref="XmlException">Thrown if the object was read from XML in such a way that it
        /// does not represent a valid <see cref="IParameterTreeNode"/> object.</exception>
        protected override IParameterTreeNode ConvertToParameterTreeNode<T>()
        {
            // Cast domain to correct type.
            CategoricalDomain<T> categoricalDomain =
                this.domain.ConvertToParameterTreeDomain() as CategoricalDomain<T>;
            if (categoricalDomain == null)
            {
                throw new XmlException(
                    $"Domain of OR node '{this.id}' was not of type {typeof(CategoricalDomain<T>)} as expected.");
            }

            // Create OR node.
            var node = new OrNode<T>(this.id, categoricalDomain);

            // Add children:
            foreach (var choice in this.choice)
            {
                // Check activator is of correct type.
                if (!(choice.Item is T))
                {
                    throw new XmlException(
                        $"OR node '{this.id}' had a choice of type {choice.Item.GetType()} instead of {typeof(T)}.");
                }

                // Add child.
                node.AddChild((T)choice.Item, choice.child.ConvertToParameterTreeNode());
            }

            return node;
        }
Esempio n. 4
0
        /// <summary>
        /// Creates a <see cref="ParameterTree"/> consisting of a single node with categorical domain.
        /// </summary>
        /// <typeparam name="T">Type of the categorical domain.</typeparam>
        /// <param name="domain">The categorical domain.</param>
        /// <returns>The created <see cref="ParameterTree"/>.</returns>
        private ParameterTree SingleCategoryTree <T>(CategoricalDomain <T> domain)
        {
            var root = new ValueNode <T>("CategoricalFeature", domain);

            var tree = new ParameterTree(root);

            return(tree);
        }
        public override void MutateGeneValueThrowsExceptionForWrongType()
        {
            IDomain domain = new CategoricalDomain <int>(new List <int> {
                1
            });

            Assert.Throws <ArgumentOutOfRangeException>(() => domain.MutateGeneValue(new Allele <double>(1.0), CategoricalDomainTest.dummyVariancePercentage));
        }
Esempio n. 6
0
        public override void ContainsGeneValueReturnsFalseForWrongType()
        {
            IDomain domain = new CategoricalDomain <int>(new List <int> {
                1
            });

            Assert.False(
                domain.ContainsGeneValue(new Allele <double>(1.0)),
                $"Wrong type is categorized as legal gene value.");
        }
Esempio n. 7
0
        public void ToStringShowsAllCategories()
        {
            IDomain domain = new CategoricalDomain <int>(new List <int> {
                1, -4, 17
            });

            Assert.Equal(
                "{1, -4, 17}",
                domain.ToString());
        }
Esempio n. 8
0
        public void ContainsGeneValueReturnsTrueForSubtype()
        {
            DomainBase <object> objectDomain = new CategoricalDomain <object>(new List <object> {
                "a1"
            });

            var stringAllele = new Allele <string>("a1");

            Assert.True(
                objectDomain.ContainsGeneValue(stringAllele),
                $"{stringAllele} was not identified as legal value of domain {objectDomain}.");
        }
Esempio n. 9
0
        /// <summary>
        /// Initializes a new instance of the <see cref="GenomeTransformationTest"/> class.
        /// Serves as test initialize method.
        /// </summary>
        public GenomeTransformationTest()
        {
            this._categoricalDomain = new CategoricalDomain <int>(Enumerable.Range(0, 10).ToList());

            var root            = new AndNode();
            var contNode        = new ValueNode <double>("continuous", new ContinuousDomain());
            var categoricalNode = new ValueNode <int>("test", this._categoricalDomain);

            root.AddChild(contNode);
            root.AddChild(categoricalNode);
            this._tree = new ParameterTree(root);
        }
Esempio n. 10
0
        /// <summary>
        /// Initializes a new instance of the <see cref="OrNode{T}" /> class.
        /// </summary>
        /// <param name="identifier">The parameter's identifier. Must be unique.</param>
        /// <param name="domain">The parameter's domain. It must either contain value types or strings.</param>
        /// <exception cref="ArgumentException">Thrown if the type contained in the domain is a reference type
        /// which is not a string.</exception>
        public OrNode(string identifier, CategoricalDomain <T> domain)
            : base(identifier)
        {
            // Check the type of the OR node. We cannot handle arbitrary reference types because the internal
            // dictionary would fail on serialization then. Another option would have been to provide an
            // IEqualityComparer independent of the reference, but it is assumed that the demand for reference
            // type OR nodes is not that high anyway.
            if (!typeof(T).IsValueType && !typeof(T).Equals(typeof(string)))
            {
                throw new ArgumentException(
                          "OrNodes may only be built for value types and strings.",
                          "domain");
            }

            this._domain = domain;
        }
Esempio n. 11
0
        /// <summary>
        /// Tries to retrieve the cached encoding for the given <paramref name="category"/>, or encodes + stores it in <see cref="EncodedCategories"/>.
        /// </summary>
        /// <typeparam name="T">
        /// The type of <paramref name="category"/> domain.
        /// </typeparam>
        /// <param name="identifier">
        /// The identifier.
        /// </param>
        /// <param name="category">
        /// The encoding.
        /// </param>
        /// <returns>
        /// The <see cref="ConvertedCategory{T}"/>.
        /// </returns>
        protected IConvertedCategory EncodeNodeCategory <T>(string identifier, CategoricalDomain <T> category)
        {
            // only lock on the affected dictionary. this is the only block form which dictionary is accessed.
            lock (this._transformationAndEncodingLock)
            {
                if (this.EncodedCategories.ContainsKey(identifier))
                {
                    return(this.EncodedCategories[identifier] as IConvertedCategory);
                }

                // only local variables/reading access in CategoricalEncoding. No need to lock in there.
                var encoding = this.CategoricalEncoding.Encode(identifier, category);
                this.EncodedCategories.Add(identifier, encoding);
                return(encoding);
            }
        }
Esempio n. 12
0
        public void PossibleValuesAreIndependentFromProvidedList()
        {
            // Create CategoricalDomain
            var provided = new List <int>(CategoricalDomainTest.categories);

            this._categoricalDomain = new CategoricalDomain <int>(provided);

            // Check that values are correctly set.
            Assert.True(TestUtils.SetsAreEquivalent(this._categoricalDomain.PossibleValues, provided));

            // Change the list that was used for initialization.
            provided.Add(4);

            // It should now be different from the possible values.
            Assert.False(
                TestUtils.SetsAreEquivalent(this._categoricalDomain.PossibleValues, provided),
                $"Values of categorical domain have been changed externally.");
        }
Esempio n. 13
0
        /// <summary>
        /// Builds a <see cref="ParameterTree"/> which consists of integer value nodes "1intDom" and "2intDom" and a
        /// categorical domain which is dependent on "1intDom".
        /// </summary>
        /// <returns>The created <see cref="ParameterTree"/>.</returns>
        private ParameterTree BuildCategoricalDomainParameterTree()
        {
            // Create the nodes.
            IntegerDomain allIntegers = new IntegerDomain();
            var           catDomain   = new CategoricalDomain <int>(new List <int> {
                1, 2, 3, 4, 5, 6
            });
            ValueNode <int> a    = new ValueNode <int>("1intDom", allIntegers);
            ValueNode <int> b    = new ValueNode <int>("2intDom", allIntegers);
            ValueNode <int> c    = new ValueNode <int>("3catDom", catDomain);
            AndNode         root = new AndNode();

            // Create connections.
            a.SetChild(c);
            root.AddChild(a);
            root.AddChild(b);

            // Return instantiated tree.
            return(new ParameterTree(root));
        }
Esempio n. 14
0
        public void MutateDoesNotDepartFromUniformDistribution()
        {
            // Set up categorical domain with integer values 0 - 3.
            var possibleValues = new List <int> {
                0, 1, 2, 3
            };
            CategoricalDomain <int> domain = new CategoricalDomain <int>(possibleValues);

            // Remember which values were generated for a lot of iterations.
            double[]     observations = new double[CategoricalDomainTest.triesForRandomTests];
            Allele <int> geneValue    = new Allele <int>(1);

            for (int i = 0; i < CategoricalDomainTest.triesForRandomTests; i++)
            {
                observations[i] = (int)domain.MutateGeneValue(geneValue, CategoricalDomainTest.dummyVariancePercentage).GetValue();
            }

            // Apply the Chi-Squared test.
            ChiSquareTest uniformTest = new ChiSquareTest(observations, new UniformDiscreteDistribution(0, 3));

            Assert.False(
                uniformTest.Significant,
                $"Mutation was found to not produce a uniform distribution by the Chi-Squared test with significance level {uniformTest.Size}.");
        }
Esempio n. 15
0
 /// <summary>
 /// Constructs a node of the subclass of <see cref="ParameterNodeBase{T}"/> that one wants to test.
 /// </summary>
 /// <typeparam name="T">The parameter's type.</typeparam>
 /// <param name="identifier">The parameter's identifier.</param>
 /// <param name="domain">The parameter's domain.</param>
 /// <returns>The constructed node.</returns>
 protected abstract ParameterNodeBase <T> ConstructNode <T>(string identifier, CategoricalDomain <T> domain);
Esempio n. 16
0
 /// <summary>
 /// Constructs an <see cref="OrNode{T}"/>.
 /// </summary>
 /// <typeparam name="T">The parameter's type.</typeparam>
 /// <param name="identifier">The identifier.</param>
 /// <param name="domain">The parameter's domain.</param>
 /// <returns>The constructed node.</returns>
 protected override ParameterNodeBase <T> ConstructNode <T>(string identifier, CategoricalDomain <T> domain)
 {
     return(new OrNode <T>(identifier, domain));
 }
Esempio n. 17
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ConvertedCategory{T}"/> class.
        /// </summary>
        /// <param name="parameterName">
        /// The name of the represented parameter.
        /// </param>
        /// <param name="categoryValues">
        /// The column representation for each <typeparamref name="T"/> in <see cref="CategoricalDomain{T}.PossibleValues"/>.
        /// </param>
        /// <param name="underlyingDomain">
        /// The underlying <see cref="CategoricalDomain{T}"/>.
        /// </param>
        public ConvertedCategory(string parameterName, Dictionary <T, double[]> categoryValues, CategoricalDomain <T> underlyingDomain)
        {
            if (string.IsNullOrWhiteSpace(parameterName))
            {
                throw new ArgumentException("String \"parameterName\" must not be null, empty, or whitespace.", nameof(parameterName));
            }

            if (categoryValues is null)
            {
                throw new ArgumentNullException(nameof(categoryValues));
            }

            var prevLength = -1;

            foreach (var mappingValuePair in categoryValues)
            {
                if (mappingValuePair.Key == null || (prevLength >= 0 && prevLength != mappingValuePair.Value.Length))
                {
                    throw new ArgumentException("All category values need to be initialized and of the same length.", nameof(categoryValues));
                }

                prevLength = mappingValuePair.Value.Length;
            }

            var distinctRepresentations = categoryValues.Select(cv => cv.Value).Distinct(new DoubleArrayEqualityComparer()).Count();

            if (categoryValues.Count != distinctRepresentations)
            {
                throw new ArgumentException("Double Representations of features need to be distinct.");
            }

            this.ParameterName = parameterName;
            this.UnderlyingCategoricalDomain = underlyingDomain ?? throw new ArgumentException("Domain musn't be null.", nameof(underlyingDomain));
            this.CategoryValues = categoryValues;
            this.ColumnCount    = this.CategoryValues.Any() ? this.CategoryValues.First().Value.Length : -1;

            ((IConvertedCategory)this).Initialize();
        }
Esempio n. 18
0
 /// <summary>
 /// Initializes a new instance of the <see cref="CategoricalDomainTest"/> class.
 /// </summary>
 public CategoricalDomainTest()
 {
     this._categoricalDomain = new CategoricalDomain <int>(CategoricalDomainTest.categories);
 }