Ejemplo n.º 1
0
        /// <summary>
        /// Pack the data in an ordering expected by the RNN layer used.  This method is only called when using Data/Clip inputs.
        /// </summary>
        /// <param name="sender">Specifies the sender of the event, which is the MemoryDataLayer.</param>
        /// <param name="e">Specifies the event parameters.</param>
        /// <remarks>
        /// This method is responsible for packing the datum received into the data blob within the event arguments and do so in the
        /// expected LSTM ordering.
        /// </remarks>
        private void memData_OnDataPack(object sender, MemoryDataLayerPackDataArgs<T> e)
        {
            List<int> rgDataShape = e.Data.shape();
            List<int> rgClipShape = e.Clip.shape();
            List<int> rgLabelShape = e.Label.shape();
            int nBatch = e.DataItems.Count;
            int nSeqLen = rgDataShape[0];

            e.Data.Log.CHECK_GT(nSeqLen, 0, "The sequence lenth must be greater than zero!");
            e.Data.Log.CHECK_EQ(nBatch, e.ClipItems.Count, "The data and clip should have the same number of items.");
            e.Data.Log.CHECK_EQ(nSeqLen, rgClipShape[0], "The data and clip should have the same sequence count.");

            rgDataShape[1] = nBatch;  // LSTM uses sizing: seq, batch, data1, data2
            rgClipShape[1] = nBatch;
            rgLabelShape[1] = nBatch;

            e.Data.Reshape(rgDataShape);
            e.Clip.Reshape(rgClipShape);
            e.Label.Reshape(rgLabelShape);

            T[] rgRawData = new T[e.Data.count()];
            T[] rgRawClip = new T[e.Clip.count()];
            T[] rgRawLabel = new T[e.Label.count()];

            int nDataSize = e.Data.count(2);
            T[] rgDataItem = new T[nDataSize];
            T dfClip;
            int nIdx;

            for (int i = 0; i < nBatch; i++)
            {
                Datum data = e.DataItems[i];
                Datum clip = e.ClipItems[i];

                T[] rgLabel = unpackLabel(data);

                for (int j = 0; j < nSeqLen; j++)
                {
                    dfClip = clip.GetDataAt<T>(j);

                    for (int k = 0; k < nDataSize; k++)
                    {
                        rgDataItem[k] = data.GetDataAt<T>(j * nDataSize + k);
                    }

                    // LSTM: Create input data, the data must be in the order
                    // seq1_val1, seq2_val1, ..., seqBatch_Size_val1, seq1_val2, seq2_val2, ..., seqBatch_Size_valSequence_Length
                    if (e.LstmType == LayerParameter.LayerType.LSTM)
                        nIdx = nBatch * j + i;

                    // LSTM_SIMPLE: Create input data, the data must be in the order
                    // seq1_val1, seq1_val2, ..., seq1_valBatchSize, seq2_val1, seq2_val2, ..., seqSequenceLength_valBatchSize
                    else
                        nIdx = i * nBatch + j;

                    Array.Copy(rgDataItem, 0, rgRawData, nIdx * nDataSize, nDataSize);
                    rgRawClip[nIdx] = dfClip;

                    if (rgLabel != null)
                    {
                        if (rgLabel.Length == nSeqLen)
                            rgRawLabel[nIdx] = rgLabel[j];
                        else if (rgLabel.Length == 1)
                        {
                            if (j == nSeqLen - 1)
                                rgRawLabel[0] = rgLabel[0];
                        }
                        else
                        {
                            throw new Exception("The Solver SequenceLength parameter does not match the actual sequence length!  The label length '" + rgLabel.Length.ToString() + "' must be either '1' for SINGLE labels, or the sequence length of '" + nSeqLen.ToString() + "' for MULTI labels.  Stopping training.");
                        }
                    }
                }
            }

            e.Data.mutable_cpu_data = rgRawData;
            e.Clip.mutable_cpu_data = rgRawClip;
            e.Label.mutable_cpu_data = rgRawLabel;
            m_nRecurrentSequenceLength = nSeqLen;
        }