OnehotAndIndex.cpp 5.1 KB
Newer Older
linye committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
/* NiuTrans.Tensor - an open-source tensor library
 * Copyright (C) 2017, Natural Language Processing Lab, Northestern University.
 * All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * $Created by: Xu Chen (email: hello_master1954@163.com) 2018-12-17
 */

#include "OnehotAndIndex.h"
#include "OnehotAndIndex.cuh"

namespace nts{ // namespace nts(NiuTrans.Tensor)

/* 
convert onehot tensor to index tensor 

>> onehot - onehot tensor, which value is 0 or 1
>> index - index tensor, which value is an integer num
>> size - the last dimension size of the onehot tensor
*/
34
void _OnehotToIndex(XTensor * onehot, XTensor * index, int size)
linye committed
35
{
36
    CheckNTErrors(onehot->GetDim(-1) == size, "Illegal tensor dimension!");
linye committed
37 38 39 40
    CheckNTErrors(onehot->order == index->order + 1, "Illegal tensor order!");
    CheckNTErrors(onehot->dataType == X_INT, "The onehot tensor must be in X_INT!")
    CheckNTErrors(index->dataType == X_INT, "The index tensor must be in X_INT!")

41 42
    for (int i = 0; i < index->order; i++)
        CheckNTErrors(index->GetDim(i) == onehot->GetDim(i), "Illegal tensor order!");
linye committed
43 44 45

#ifdef USE_CUDA
    if(onehot->devID >= 0 && index->devID >= 0) {
46
        _CudaOnehotToIndex(onehot, index, size);
linye committed
47 48 49 50
        return;
    }
#endif

51 52
    int blockNum = index->unitNum;
    int stride = size;
linye committed
53 54 55 56 57

    int * onehotData = (int *)onehot->data;
    int * indexData = (int *)index->data;

    for (int i = 0; i < blockNum; i++) {
58 59
        int * od = onehotData + i * stride;
        int record = -1;
linye committed
60
        for (int j = 0; j < stride; j++) {
61 62 63 64 65
            if (od[j] != 0) {
                if (record == -1)
                    record = j;
                else
                    ShowNTErrors("The value of onehot tensor is illegal!");
linye committed
66 67
            }
        }
68
        indexData[i] = record;
linye committed
69
    }
70

linye committed
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
}

/* 
convert onehot tensor to index tensor (return an XTensor structure)
make a new tensor to keep the result and return it 

>> onehot - onehot tensor, which value is 0 or 1
>> size - the last dimension size of the onehot tensor
<< return - the index tensor
*/
XTensor OnehotToIndex(XTensor & onehot, int size)
{
    CheckNTErrors(onehot.GetDim(-1) == size, "Illegal tensor dimension!");
    CheckNTErrors(onehot.dataType == X_INT, "The onehot tensor must be in X_INT!")

    XTensor index;
    InitTensor(&index, onehot.order - 1, onehot.dimSize, X_INT, 1.0F, onehot.devID, onehot.mem);
    index.SetTMPFlag();

    _OnehotToIndex(&onehot, &index, size);

    return index;
}

/* 
convert index tensor to onehot tensor 

>> index - index tensor, which value is an integer num
>> onehot - onehot tensor, which value is 0 or 1
>> size - the last dimension size of the onehot tensor
*/
102
void _IndexToOnehot(XTensor * index, XTensor * onehot, int size, float labelSmoothingP)
linye committed
103 104 105 106 107 108 109 110 111 112 113
{
    CheckNTErrors(onehot->GetDim(-1) == size, "Illegal tensor dimension!");
    CheckNTErrors(onehot->order == index->order + 1, "Illegal tensor order!");
    //CheckNTErrors(onehot->dataType == X_INT, "The onehot tensor must be in X_INT!")
    CheckNTErrors(index->dataType == X_INT, "The index tensor must be in X_INT!")

    for (int i = 0; i < index->order; i++)
        CheckNTErrors(index->GetDim(i) == onehot->GetDim(i), "Illegal tensor order!");

    onehot->SetZeroAll();

114
#ifdef USE_CUDA
linye committed
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
    float confidence = 1 - labelSmoothingP;
    float lowconfidence = labelSmoothingP / size;
    if(onehot->devID >= 0 && index->devID >= 0) {
        _CudaIndexToOnehot(index, onehot, size, confidence, lowconfidence);
        return;
    }
#endif

    int blockNum = index->unitNum;
    int stride = size;

    int * indexData = (int *)index->data;
    DTYPE * onehotData = (DTYPE *)onehot->data;

    for (int i = 0; i < blockNum; i++) {
        int id = indexData[i];
        DTYPE * od = onehotData + i * stride;
132
        od[id] = 1;
linye committed
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
    }

}

/* 
convert onehot tensor to index tensor (return an XTensor structure)
make a new tensor to keep the result and return it 

>> index - index tensor, which value is an integer num
>> size - the last dimension size of the onehot tensor
>> confidence - labelsmoothing
<< return - the onehot tensor
*/
XTensor IndexToOnehot(XTensor & index, int size, float labelSmoothingP)
{
    CheckNTErrors(index.dataType == X_INT, "The onehot tensor must be in X_INT!")

    XTensor onehot;
    onehot.SetTMPFlag();
    
    int order = index.order;
    int * dim = new int[order + 1];
    memcpy(dim, index.dimSize, order * sizeof(int));
    dim[order] = size;
    InitTensor(&onehot, index.order + 1, dim, X_FLOAT, 1.0F, index.devID, index.mem);

    _IndexToOnehot(&index, &onehot, size, labelSmoothingP);

    delete[] dim;

    return onehot;
}

166
} // namespace nts(NiuTrans.Tensor)