/// <summary> /// Copy the data stored in 'this' Value object to the buffers representing a sequence in CSC sparse format. /// The sequence buffer will be resized if necessary. /// The Value should have the same tensor shape as outputVariable. /// On return, the sequenceLength is set to the length of the sequence stored in 'this' Value, /// and the colStarts, rowIndices and nonZeroValues contain the data of column indexes, row indexes and non-zero values, /// and the numNonZeroValues is set to number of non-zero values contained in 'this' Value. /// </summary> /// <typeparam name="T">dat type</typeparam> /// <param name="outputVariable">source variable</param> /// <param name="sequenceLength">legnth of the sequence</param> /// <param name="colStarts">column start indices</param> /// <param name="rowIndices">row indices</param> /// <param name="nonZeroValues">sparse values</param> /// <param name="numNonZeroValues">number of sparse values</param> public void GetSparseData <T>(Variable outputVariable, out int sequenceLength, out IList <int> colStarts, out IList <int> rowIndices, out IList <T> nonZeroValues, out int numNonZeroValues) { var colStartVec = new IntVector(); var rowIndicesVec = new IntVector(); int[] n1 = new int[1]; int[] n2 = new int[1]; if (typeof(T).Equals(typeof(float))) { if (_GetDataType() != DataType.Float) { throw new ArgumentException("The value type does not match the list type."); } var nonZeroValuesVec = new FloatVector(); _CopyVariableValueToFloat(outputVariable, n1, colStartVec, rowIndicesVec, nonZeroValuesVec, n2); nonZeroValues = nonZeroValuesVec as IList <T>; } else if (typeof(T).Equals(typeof(double))) { if (_GetDataType() != DataType.Double) { throw new ArgumentException("The value type does not match the list type."); } var nonZeroValuesVec = new DoubleVector(); _CopyVariableValueToDouble(outputVariable, n1, colStartVec, rowIndicesVec, nonZeroValuesVec, n2); nonZeroValues = nonZeroValuesVec as IList <T>; } else { throw new ArgumentException("The value type does not match the list type."); } sequenceLength = n1[0]; numNonZeroValues = n2[0]; colStarts = colStartVec; rowIndices = rowIndicesVec; }
/// <summary> /// Helper function to create a FloatVector from IEnumerable. /// </summary> /// <typeparam name="T">The input data type.</typeparam> /// <param name="input">Elements to be stored in the FloatVector.</param> /// <returns>A FloatVector containing all elements from the IEnumerable input.</returns> internal static FloatVector AsFloatVector <T>(IEnumerable <T> input) { if (typeof(T).Equals(typeof(float))) { var inputVector = new FloatVector(); IEnumerable <float> inputInType = input as IEnumerable <float>; if (inputInType == null) { throw new ArgumentNullException("The parameter cannot be cast as IEnumerable<float>."); } foreach (var element in inputInType) { inputVector.Add(element); } return(inputVector); } else { throw new ArgumentException("The data type " + typeof(T).ToString() + " is not supported. Only float or double is supported by CNTK."); } }
// Create Value based on dense input // Todo: could this be a extension to Value class?? // Todo: use Variable instead of varName. VarName as extension method // Todo: List can have maximal 2^31-1, enough? Otherwise need to go to array which supports 64bit size public Value CreateValue <T>(string varName, List <List <T> > sequences, DeviceDescriptor computeDevice) { var variable = getVariableByName(varName); var dim = variable.Shape.TotalSize; if (typeof(T).Equals(typeof(float))) { var inputSeqVector = new FloatVectorVector(); foreach (var seq in sequences) { if (seq.Count() % dim != 0) { throw new InvalidDataException("the number of data in sequences does not match the input dimension"); } var samples = new FloatVector(seq); inputSeqVector.Add(samples); } var inputValue = Value.CreateDenseFloat(variable.Shape, inputSeqVector, computeDevice); return(inputValue); } else if (typeof(T).Equals(typeof(double))) { var inputSeqVector = new DoubleVectorVector(); foreach (var seq in sequences) { if (seq.Count() % dim != 0) { throw new InvalidDataException("the number of data in sequences does not match the input dimension"); } var samples = new DoubleVector(seq); inputSeqVector.Add(samples); } var inputValue = Value.CreateDenseDouble(variable.Shape, inputSeqVector, computeDevice); return(inputValue); } else { throw new InvalidDataException("The data type " + typeof(T).ToString() + " is not supported. Only float or double is supported by CNTK."); } }