Beispiel #1
0
        public static string MakeWeights(
            [ExcelArgument(Description = "Name of the weights object to create.")] string name,
            [ExcelArgument(Description = "Array of array objects created using =nnMakeArray().")] object[] weightArrays)
        {
            if (weightArrays == null || weightArrays.Length == 0)
            {
                throw new NNXException("Argument WeightArrays cannot be null or empty.");
            }

            var weightArrayNames = weightArrays.Select(o => o.ToString()).ToArray();

            var results = new double[weightArrayNames.Length][];

            for (var i = 0; i < weightArrayNames.Length; i++)
            {
                var arrayName = weightArrayNames[i];

                double[] array;

                if (!ObjectStore.TryGet(arrayName, out array))
                {
                    throw new NNXException($"Element at index {i + 1} ('{arrayName}') does not " +
                                           "point to a valid array of numbers.");
                }

                results[i] = array;
            }

            ObjectStore.Add(name, results);

            return(name);
        }
Beispiel #2
0
        public static string MakeMultilayerPerceptron(
            [ExcelArgument(Description = "Name of perceptron object to create.")] string name,
            [ExcelArgument(Description = "Number of input nodes, not including input bias.")] int numInputs,
            [ExcelArgument(Description = "Number of output nodes.")] int numOutputs,
            [ExcelArgument(Description = "Number of nodes in each hidden layer, not including biases. " +
                                         "Must be an array of integers.")] double[] hiddenLayerSizes,
            [ExcelArgument(Description = "Weights object created using =nnMakeWeights().")] string weights)
        {
            var nn = new MultilayerPerceptron(numInputs, numOutputs, hiddenLayerSizes.ToIntArray());

            double[][] weightValues;

            if (!ObjectStore.TryGet(weights, out weightValues))
            {
                throw new NNXException("Argument Weights should be a weights object created using nnMakeWeights().");
            }

            if (weightValues.Length != nn.Weights.Length)
            {
                throw new NNXException($"Argument Weights was expected to have {nn.Weights.Length} " +
                                       $"layers; had: {weightValues.Length}.");
            }

            for (var layer = 0; layer < weightValues.Length; layer++)
            {
                if (weightValues[layer].Length != nn.Weights[layer].Length)
                {
                    throw new NNXException($"Argument Weights was expected to have {nn.Weights[layer].Length} " +
                                           $"values in layer {layer + 1}; had: {weightValues[layer].Length}.");
                }
            }

            weightValues.DeepCopyTo(nn.Weights);

            ObjectStore.Add(name, nn);
            return(name);
        }
Beispiel #3
0
        //[ExcelFunction(Name = "nnMakeObject")]
        public static string MakeObject(string name, string typeName, object[,] properties)
        {
            if (string.IsNullOrEmpty(typeName))
            {
                throw new NNXException("Argument TypeName should not be null or empty.");
            }

            Type objectType;

            if (!SupportedObjects.TryGetValue(typeName, out objectType))
            {
                throw new NNXException($"Unrecognized object type: '{typeName}'.");
            }

            var obj = Activator.CreateInstance(objectType);

            if (properties == null || properties.GetLength(0) == 0)
            {
                // No properties to set, we're done here.
                ObjectStore.Add(name, obj);
                return(name);
            }

            if (properties.GetLength(1) != 2)
            {
                throw new NNXException($"Argument Properties must have width 2; was: {properties.GetLength(1)}.");
            }

            var numProperties    = properties.GetLength(0);
            var objectProperties = objectType.GetProperties(BindingFlags.Instance | BindingFlags.Public)
                                   .Where(p => p.CanWrite).ToList();

            for (var i = 0; i < numProperties; i++)
            {
                var propertyName = properties[i, 0].ToString();
                var value        = properties[i, 1];

                if (string.IsNullOrEmpty(propertyName))
                {
                    throw new NNXException($"Property at position {i + 1} was empty.");
                }

                var targetProperty = objectProperties.FirstOrDefault(p => p.Name == propertyName);

                if (targetProperty == null)
                {
                    throw new NNXException($"Object type {typeName} does not have property {propertyName}.");
                }

                var propertyType = targetProperty.PropertyType;

                // Special case: assigning an integer double to int.
                if (propertyType == typeof(int) &&
                    value is double &&
                    (((double)value) % 1 == 0.0))
                {
                    targetProperty.SetValue(obj, (int)((double)value));
                    continue;
                }

                // Special case: assigning int to double.
                if (propertyType == typeof(double) && value is int)
                {
                    targetProperty.SetValue(obj, (double)((int)value));
                    continue;
                }

                // Special case: string.
                if (propertyType == typeof(string))
                {
                    var stringValue = value?.ToString() ?? "";
                    targetProperty.SetValue(obj, stringValue);
                    continue;
                }

                // General case.
                if (propertyType.IsInstanceOfType(value))
                {
                    targetProperty.SetValue(obj, value);
                    continue;
                }

                // If this was a simple type, then the user provided a value
                // of the wrong type.
                if (propertyType.IsAssignableFrom(typeof(int)) ||
                    propertyType.IsAssignableFrom(typeof(double)) ||
                    propertyType.IsAssignableFrom(typeof(string)))
                {
                    var propertyTypeName = MapPropertyType(propertyType);
                    var aOrAn            = AOrAn(propertyTypeName);

                    throw new NNXException($"Property {propertyName} of object type {typeName} " +
                                           $"must be {aOrAn} {propertyTypeName}; was {value}.");
                }

                // If we get here, then the target property is an array or array of arrays.
                var referencedName = properties[i, 1].ToString();

                // Special case: weights.
                if (propertyType.IsAssignableFrom(typeof(double[][])))
                {
                    double[][] weights;

                    if (!ObjectStore.TryGet(referencedName, out weights))
                    {
                        throw new NNXException($"Property {propertyName} of type {typeName} must be of type " +
                                               "Weights created using nnMakeWeights() function.");
                    }

                    targetProperty.SetValue(obj, weights);
                    continue;
                }

                // Special case: enumerables.
                if (propertyType.IsAssignableFrom(typeof(string[])))
                {
                    string[] array;

                    if (!ObjectStore.TryGet(referencedName, out array))
                    {
                        throw new NNXException($"Property {propertyName} of type {typeName} must refer " +
                                               $"to array containing elements of type string.");
                    }

                    targetProperty.SetValue(obj, array);
                    continue;
                }

                if (propertyType.IsAssignableFrom(typeof(double[])))
                {
                    double[] array;

                    if (!ObjectStore.TryGet(referencedName, out array))
                    {
                        throw new NNXException($"Property {propertyName} of type {typeName} must refer " +
                                               $"to array containing elements of type number.");
                    }

                    targetProperty.SetValue(obj, array);
                    continue;
                }

                if (propertyType.IsAssignableFrom(typeof(int[])))
                {
                    int[] intArray;

                    if (ObjectStore.TryGet(referencedName, out intArray))
                    {
                        targetProperty.SetValue(obj, intArray);
                        continue;
                    }

                    double[] doubleArray;

                    if (ObjectStore.TryGet(referencedName, out doubleArray))
                    {
                        var convertedArray = new int[doubleArray.Length];

                        for (var j = 0; j < doubleArray.Length; j++)
                        {
                            var doubleValue = doubleArray[j];

                            if (doubleValue % 1 != 0)
                            {
                                throw new NNXException($"Property {propertyName} of type {typeName} must refer " +
                                                       $"to array containing elements of type integer.");
                            }

                            convertedArray[j] = (int)doubleValue;
                        }

                        targetProperty.SetValue(obj, convertedArray);
                        continue;
                    }


                    throw new NNXException($"Property {propertyName} of type {typeName} must refer " +
                                           $"to array containing elements of type integer.");
                }

                throw new Exception("Reached unreacheable code.");
            }

            ObjectStore.Add(name, obj);
            return(name);
        }