TLogSoftmax.cpp 9.33 KB
Newer Older
liyinqiao committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/* 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-07-02
*/

#include "../XUtility.h"
23
#include "../core/utilities/CheckData.h"
liyinqiao committed
24 25 26
#include "TLogSoftmax.h"

namespace nts { // namespace nts(NiuTrans.Tensor)
liyinqiao committed
27 28 29 30

/* 
case 1: test LogSoftmax function.
LogSoftmax function: y = log(e^x / \sum_{i} e^{x_i})
liyinqiao committed
31 32 33
*/
bool TestLogSoftmax1()
{
34 35 36 37 38
    /* a tensor of size (2, 3) */
    int order = 2;
    int * dimSize = new int[order];
    dimSize[0] = 2;
    dimSize[1] = 3;
liyinqiao committed
39

40 41 42
    int unitNum = 1;
    for (int i = 0; i < order; i++)
        unitNum *= dimSize[i];
liyinqiao committed
43

liyinqiao committed
44 45 46 47
    DTYPE xData[2][3] = { {0.0F, 1.0F, 2.0F}, 
                          {0.5F, 0.7F, 1.4F} };
    DTYPE answer[2][3] = { {-2.4076F, -1.4076F, -0.4076F}, 
                           {-1.5435F, -1.3435F, -0.6435F} };
liyinqiao committed
48 49 50 51 52

    /* CPU test */
    bool cpuTest = true;

    /* create tensors */
53 54
    XTensor * x = NewTensorV2(order, dimSize);
    XTensor * y = NewTensorV2(order, dimSize);
55
    XTensor yUser;
liyinqiao committed
56 57

    /* initialize variables */
58
    x->SetData(xData, unitNum);
liyinqiao committed
59 60 61
    y->SetZeroAll();

    /* call LogSoftmax function */
62
    _LogSoftmax(x, y, 1);
63
    yUser = LogSoftmax(*x, 1);
liyinqiao committed
64 65
    
    /* check result */
66
    cpuTest = _CheckData(y, answer, unitNum, 1e-4F) && _CheckData(&yUser, answer, unitNum, 1e-4F);
liyinqiao committed
67 68 69 70 71 72

#ifdef USE_CUDA
    /* GPU test */
    bool gpuTest = true;

    /* create tensors */
73 74
    XTensor * xGPU = NewTensorV2(order, dimSize, X_FLOAT, 1.0F, 0);
    XTensor * yGPU = NewTensorV2(order, dimSize, X_FLOAT, 1.0F, 0);
75
    XTensor yUserGPU;
liyinqiao committed
76 77

    /* initialize variables */
78
    xGPU->SetData(xData, unitNum);
liyinqiao committed
79 80 81
    yGPU->SetZeroAll();

    /* call LogSoftmax function */
82
    _LogSoftmax(xGPU, yGPU, 1);
83
    yUserGPU = LogSoftmax(*xGPU, 1);
liyinqiao committed
84 85
    
    /* check result */
86
    gpuTest = _CheckData(yGPU, answer, unitNum, 1e-4F) && _CheckData(&yUserGPU, answer, unitNum, 1e-4F);
liyinqiao committed
87 88 89 90 91 92

    /* destroy variables */
    delete x;
    delete y;
    delete xGPU;
    delete yGPU;
93
    delete[] dimSize;
liyinqiao committed
94 95 96 97 98 99

    return cpuTest && gpuTest;
#else
    /* destroy variables */
    delete x;
    delete y;
100
    delete[] dimSize;
liyinqiao committed
101 102 103 104 105

    return cpuTest;
#endif // USE_CUDA
}

liyinqiao committed
106 107 108 109
/* 
case 2: test LogSoftmaxBackward function.
dE/dx = dE/dy * dy/dx
log softmax: y_i = log(e^{x_i} / \sum_{k} e^{x_k})
110
In this case, LossName=CROSSENTROPY.
liyinqiao committed
111 112 113
*/
bool TestLogSoftmax2()
{
114 115 116 117 118
    /* a tensor of size (1, 3) */
    int order = 2;
    int * dimSize = new int[order];
    dimSize[0] = 1;
    dimSize[1] = 3;
liyinqiao committed
119

120 121 122
    int unitNum = 1;
    for (int i = 0; i < order; i++)
        unitNum *= dimSize[i];
liyinqiao committed
123

124
    DTYPE xData[1][3] = {0.0F, 1.0F, 2.0F};
125 126
    DTYPE gData[1][3] = {0.5F, 0.8F, 1.5F};
    DTYPE yAnswer[1][3] = {-2.4076F, -1.4076F, -0.4076F};
127
    DTYPE dedxAnswer[1][3] = {-0.4100F, -0.5553F, -0.8348F};
liyinqiao committed
128 129 130 131 132

    /* CPU test */
    bool cpuTest = true;

    /* create tensors */
133 134 135 136 137
    XTensor * x = NewTensorV2(order, dimSize);
    XTensor * y = NewTensorV2(order, dimSize);
    XTensor * g = NewTensorV2(order, dimSize);
    XTensor * dedy = NewTensorV2(order, dimSize);
    XTensor * dedx = NewTensorV2(order, dimSize);
liyinqiao committed
138 139

    /* initialize variables */
140 141
    x->SetData(xData, unitNum);
    g->SetData(gData, unitNum);
liyinqiao committed
142 143 144 145 146
    y->SetZeroAll();
    dedx->SetZeroAll();
    dedy->SetZeroAll();

    /* call LogSoftmax function */
147
    _LogSoftmax(x, y, 1);
liyinqiao committed
148 149
    
    /* call LogSoftmaxBackward function */
150
    _LogSoftmaxBackward(g, y, x, dedy, dedx, NULL, 1, CROSSENTROPY);
liyinqiao committed
151 152
    
    /* check result */
153 154
    cpuTest = _CheckData(y, yAnswer, unitNum, 1e-4F)
              && _CheckData(dedx, dedxAnswer, unitNum, 1e-4F);
liyinqiao committed
155 156 157 158 159 160

#ifdef USE_CUDA
    /* GPU test */
    bool gpuTest = true;

    /* create tensors */
161 162 163 164 165
    XTensor * xGPU = NewTensorV2(order, dimSize, X_FLOAT, 1.0F, 0);
    XTensor * yGPU = NewTensorV2(order, dimSize, X_FLOAT, 1.0F, 0);
    XTensor * gGPU = NewTensorV2(order, dimSize, X_FLOAT, 1.0F, 0);
    XTensor * dedyGPU = NewTensorV2(order, dimSize, X_FLOAT, 1.0F, 0);
    XTensor * dedxGPU = NewTensorV2(order, dimSize, X_FLOAT, 1.0F, 0);
liyinqiao committed
166 167

    /* initialize variables */
168 169
    xGPU->SetData(xData, unitNum);
    gGPU->SetData(gData, unitNum);
liyinqiao committed
170 171 172 173 174
    yGPU->SetZeroAll();
    dedxGPU->SetZeroAll();
    dedyGPU->SetZeroAll();

    /* call LogSoftmax function */
175
    _LogSoftmax(xGPU, yGPU, 1);
liyinqiao committed
176 177

    /* call LogSoftmaxBackward function */
178
    _LogSoftmaxBackward(gGPU, yGPU, xGPU, dedyGPU, dedxGPU, NULL, 1, CROSSENTROPY);
liyinqiao committed
179 180
    
    /* check result */
181
    gpuTest = _CheckData(yGPU, yAnswer, unitNum, 1e-4F) && _CheckData(dedxGPU, dedxAnswer, unitNum, 1e-4F);
liyinqiao committed
182 183 184 185 186 187 188 189 190 191 192 193

    /* destroy variables */
    delete x;
    delete y;
    delete g;
    delete dedx;
    delete dedy;
    delete xGPU;
    delete yGPU;
    delete gGPU;
    delete dedxGPU;
    delete dedyGPU;
194
    delete[] dimSize;
liyinqiao committed
195 196 197 198 199 200 201 202 203

    return cpuTest && gpuTest;
#else
    /* destroy variables */
    delete x;
    delete y;
    delete g;
    delete dedx;
    delete dedy;
204
    delete[] dimSize;
liyinqiao committed
205 206 207 208 209

    return cpuTest;
#endif // USE_CUDA
}

liyinqiao committed
210 211 212 213
/* 
case 3: test LogSoftmaxBackward function.
dE/dx = dE/dy * dy/dx
log softmax: y_i = log(e^{x_i} / \sum_{k} e^{x_k})
214
In this case, LossName=SQUAREDERROR
liyinqiao committed
215 216 217 218
*/
bool TestLogSoftmax3()
{
    /* a tensor of size (1, 3) */
219 220 221 222
    int order = 2;
    int * dimSize = new int[order];
    dimSize[0] = 1;
    dimSize[1] = 3;
liyinqiao committed
223

224 225 226
    int unitNum = 1;
    for (int i = 0; i < order; i++)
        unitNum *= dimSize[i];
liyinqiao committed
227

228 229
    DTYPE xData[1][3] = {0.0F, 1.0F, 2.0F};
    DTYPE gData[1][3] = {0.5F, 0.8F, 1.5F};
liyinqiao committed
230
    DTYPE yAnswer[1][3] = {-2.4076F, -1.4076F, -0.4076F};
231
    DTYPE dedxAnswer[1][3] = {-0.4100F, -0.5553F, -0.8348F};
liyinqiao committed
232 233 234 235 236

    /* CPU test */
    bool cpuTest = true;

    /* create tensors */
237 238 239 240 241
    XTensor * x = NewTensorV2(order, dimSize);
    XTensor * y = NewTensorV2(order, dimSize);
    XTensor * g = NewTensorV2(order, dimSize);
    XTensor * dedy = NewTensorV2(order, dimSize);
    XTensor * dedx = NewTensorV2(order, dimSize);
liyinqiao committed
242 243

    /* initialize variables */
244 245
    x->SetData(xData, unitNum);
    g->SetData(gData, unitNum);
liyinqiao committed
246 247 248 249 250
    y->SetZeroAll();
    dedx->SetZeroAll();
    dedy->SetZeroAll();

    /* call LogSoftmax function */
251
    _LogSoftmax(x, y, 1);
liyinqiao committed
252 253
    
    /* call LogSoftmaxBackward function */
254
    _LogSoftmaxBackward(g, y, x, dedy, dedx, NULL, 1, SQUAREDERROR);
liyinqiao committed
255 256
    
    /* check result */
257 258
    cpuTest = _CheckData(y, yAnswer, unitNum, 1e-4F)
              && _CheckData(dedx, dedxAnswer, unitNum, 1e-4F);
liyinqiao committed
259 260 261 262 263 264

#ifdef USE_CUDA
    /* GPU test */
    bool gpuTest = true;

    /* create tensors */
265 266 267 268 269
    XTensor * xGPU = NewTensorV2(order, dimSize, X_FLOAT, 1.0F, 0);
    XTensor * yGPU = NewTensorV2(order, dimSize, X_FLOAT, 1.0F, 0);
    XTensor * gGPU = NewTensorV2(order, dimSize, X_FLOAT, 1.0F, 0);
    XTensor * dedyGPU = NewTensorV2(order, dimSize, X_FLOAT, 1.0F, 0);
    XTensor * dedxGPU = NewTensorV2(order, dimSize, X_FLOAT, 1.0F, 0);
liyinqiao committed
270 271

    /* initialize variables */
272 273
    xGPU->SetData(xData, unitNum);
    gGPU->SetData(gData, unitNum);
liyinqiao committed
274 275 276 277 278
    yGPU->SetZeroAll();
    dedxGPU->SetZeroAll();
    dedyGPU->SetZeroAll();

    /* call LogSoftmax function */
279
    _LogSoftmax(xGPU, yGPU, 1);
liyinqiao committed
280 281

    /* call LogSoftmaxBackward function */
282
    _LogSoftmaxBackward(gGPU, yGPU, xGPU, dedyGPU, dedxGPU, NULL, 1, SQUAREDERROR);
liyinqiao committed
283 284
    
    /* check result */
285 286
    gpuTest = _CheckData(yGPU, yAnswer, unitNum, 1e-4F)
              && _CheckData(dedxGPU, dedxAnswer, unitNum, 1e-3F);
liyinqiao committed
287 288 289 290 291 292 293 294 295 296 297 298

    /* destroy variables */
    delete x;
    delete y;
    delete g;
    delete dedx;
    delete dedy;
    delete xGPU;
    delete yGPU;
    delete gGPU;
    delete dedxGPU;
    delete dedyGPU;
299
    delete[] dimSize;
liyinqiao committed
300 301 302 303 304 305 306 307 308

    return cpuTest && gpuTest;
#else
    /* destroy variables */
    delete x;
    delete y;
    delete g;
    delete dedx;
    delete dedy;
309
    delete[] dimSize;
liyinqiao committed
310 311 312 313 314 315 316 317 318 319 320 321 322

    return cpuTest;
#endif // USE_CUDA
}

/* other cases */
/*
    TODO!!
*/

/* test for LogSoftmax Function */
bool TestLogSoftmax()
{
323
    XPRINT(0, stdout, "[TEST LogSoftmax] logsoftmax function and its backward computation \n");
liyinqiao committed
324 325 326 327 328 329 330 331 332 333 334 335
    bool returnFlag = true, caseFlag = true;

    /* case 1 test */
    caseFlag = TestLogSoftmax1();

    if (!caseFlag) {
        returnFlag = false;
        XPRINT(0, stdout, ">> case 1 failed!\n");
    }
    else
        XPRINT(0, stdout, ">> case 1 passed!\n");

liyinqiao committed
336 337
    /* case 2 test */
    caseFlag = TestLogSoftmax2();
liyinqiao committed
338

liyinqiao committed
339 340 341 342 343 344
    if (!caseFlag) {
        returnFlag = false;
        XPRINT(0, stdout, ">> case 2 failed!\n");
    }
    else
        XPRINT(0, stdout, ">> case 2 passed!\n");
liyinqiao committed
345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372

    /* case 3 test */
    caseFlag = TestLogSoftmax3();

    if (!caseFlag) {
        returnFlag = false;
        XPRINT(0, stdout, ">> case 3 failed!\n");
    }
    else
        XPRINT(0, stdout, ">> case 3 passed!\n");

    /* other cases test */
    /*
    TODO!!
    */

    if (returnFlag) {
        XPRINT(0, stdout, ">> All Passed!\n");
    }
    else
        XPRINT(0, stdout, ">> Failed!\n");

    XPRINT(0, stdout, "\n");

    return returnFlag;
}

} // namespace nts(NiuTrans.Tensor)