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); }
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); }
//[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); }