lstm_cell.https.any.js (27280B)
1 // META: title=test WebNN API lstmCell operation 2 // META: global=window 3 // META: variant=?cpu 4 // META: variant=?gpu 5 // META: variant=?npu 6 // META: script=../resources/utils.js 7 // META: timeout=long 8 9 'use strict'; 10 11 // https://www.w3.org/TR/webnn/#api-mlgraphbuilder-lstmcell 12 // A single time step of the Long Short-Term Memory [LSTM] recurrent network 13 // using a cell state, an input, output, and forget gate to compute the cell 14 // state and the hidden state of the next time step that rolls into the output 15 // across the temporal sequence of the network. 16 // 17 // enum MLRecurrentNetworkActivation { 18 // "relu", 19 // "sigmoid", 20 // "tanh" 21 // }; 22 // 23 // enum MLLstmWeightLayout { 24 // "iofg", // input-output-forget-cell gate ordering 25 // "ifgo" // input-forget-cell-output gate ordering 26 // }; 27 // 28 // dictionary MLLstmCellOptions : MLOperatorOptions { 29 // MLOperand bias; 30 // MLOperand recurrentBias; 31 // MLOperand peepholeWeight; 32 // MLLstmWeightLayout layout = "iofg"; 33 // sequence<MLRecurrentNetworkActivation> activations; 34 // }; 35 // 36 // sequence<MLOperand> lstmCell(MLOperand input, 37 // MLOperand weight, 38 // MLOperand recurrentWeight, 39 // MLOperand hiddenState, 40 // MLOperand cellState, 41 // [EnforceRange] unsigned long hiddenSize, 42 // optional MLLstmCellOptions options = {}); 43 44 45 const getLstmCellPrecisionTolerance = (graphResources) => { 46 const toleranceValueDict = {float32: 1, float16: 1}; 47 const expectedDataType = 48 graphResources 49 .expectedOutputs[Object.keys(graphResources.expectedOutputs)[0]] 50 .descriptor.dataType; 51 return {metricType: 'ULP', value: toleranceValueDict[expectedDataType]}; 52 }; 53 54 const lstmCellTests = [ 55 { 56 'name': 57 "lstmCell float32 tensors with options.bias, options.recurrentBias and options.activations=['relu', 'relu', 'relu']", 58 'graph': { 59 'inputs': { 60 'lstmCellInput': { 61 'data': [1, 2, 2, 1], 62 'descriptor': {shape: [2, 2], dataType: 'float32'} 63 }, 64 'lstmCellWeight': { 65 'data': [1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2], 66 'descriptor': {shape: [8, 2], dataType: 'float32'}, 67 'constant': true 68 }, 69 'lstmCellRecurrentWeight': { 70 'data': [ 71 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 72 0.1, 0.1, 0.1 73 ], 74 'descriptor': {shape: [8, 2], dataType: 'float32'}, 75 'constant': true 76 }, 77 'lstmCellHiddenState': { 78 'data': [0, 0, 0, 0], 79 'descriptor': {shape: [2, 2], dataType: 'float32'} 80 }, 81 'lstmCellCellState': { 82 'data': [0, 0, 0, 0], 83 'descriptor': {shape: [2, 2], dataType: 'float32'} 84 }, 85 'lstmCellBias': { 86 'data': [1, 2, 1, 2, 1, 2, 1, 2], 87 'descriptor': {shape: [8], dataType: 'float32'}, 88 'constant': true 89 }, 90 'lstmCellRecurrentBias': { 91 'data': [1, 2, 1, 2, 1, 2, 1, 2], 92 'descriptor': {shape: [8], dataType: 'float32'}, 93 'constant': true 94 } 95 }, 96 'operators': [{ 97 'name': 'lstmCell', 98 'arguments': [ 99 {'input': 'lstmCellInput'}, {'weight': 'lstmCellWeight'}, 100 {'recurrentWeight': 'lstmCellRecurrentWeight'}, 101 {'hiddenState': 'lstmCellHiddenState'}, 102 {'cellState': 'lstmCellCellState'}, {'hiddenSize': 2}, { 103 'options': { 104 'bias': 'lstmCellBias', 105 'recurrentBias': 'lstmCellRecurrentBias', 106 'activations': ['relu', 'relu', 'relu'] 107 } 108 } 109 ], 110 'outputs': ['lstmCellOutput1', 'lstmCellOutput2'] 111 }], 112 'expectedOutputs': { 113 'lstmCellOutput1': { 114 'data': [1, 8, 27, 216], 115 'descriptor': {shape: [2, 2], dataType: 'float32'} 116 }, 117 'lstmCellOutput2': { 118 'data': [1, 4, 9, 36], 119 'descriptor': {shape: [2, 2], dataType: 'float32'} 120 } 121 } 122 } 123 }, 124 { 125 'name': 126 "lstmCell float32 tensors with options.bias, options.recurrentBias, options.activations=['relu', 'relu', 'relu'] and options.peepholeWeight", 127 'graph': { 128 'inputs': { 129 'lstmCellInput': { 130 'data': [1, 2, 2, 1], 131 'descriptor': {shape: [2, 2], dataType: 'float32'} 132 }, 133 'lstmCellWeight': { 134 'data': [1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2], 135 'descriptor': {shape: [8, 2], dataType: 'float32'}, 136 'constant': true 137 }, 138 'lstmCellRecurrentWeight': { 139 'data': [ 140 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 141 0.1, 0.1, 0.1 142 ], 143 'descriptor': {shape: [8, 2], dataType: 'float32'}, 144 'constant': true 145 }, 146 'lstmCellHiddenState': { 147 'data': [0, 0, 0, 0], 148 'descriptor': {shape: [2, 2], dataType: 'float32'} 149 }, 150 'lstmCellCellState': { 151 'data': [0, 0, 0, 0], 152 'descriptor': {shape: [2, 2], dataType: 'float32'} 153 }, 154 'lstmCellBias': { 155 'data': [1, 2, 1, 2, 1, 2, 1, 2], 156 'descriptor': {shape: [8], dataType: 'float32'}, 157 'constant': true 158 }, 159 'lstmCellRecurrentBias': { 160 'data': [1, 2, 1, 2, 1, 2, 1, 2], 161 'descriptor': {shape: [8], dataType: 'float32'}, 162 'constant': true 163 }, 164 'lstmCellPeepholeWeight': { 165 'data': [0, 0, 0, 0, 0, 0], 166 'descriptor': {shape: [6], dataType: 'float32'}, 167 'constant': true 168 } 169 }, 170 'operators': [{ 171 'name': 'lstmCell', 172 'arguments': [ 173 {'input': 'lstmCellInput'}, {'weight': 'lstmCellWeight'}, 174 {'recurrentWeight': 'lstmCellRecurrentWeight'}, 175 {'hiddenState': 'lstmCellHiddenState'}, 176 {'cellState': 'lstmCellCellState'}, {'hiddenSize': 2}, { 177 'options': { 178 'bias': 'lstmCellBias', 179 'recurrentBias': 'lstmCellRecurrentBias', 180 'peepholeWeight': 'lstmCellPeepholeWeight', 181 'activations': ['relu', 'relu', 'relu'] 182 } 183 } 184 ], 185 'outputs': ['lstmCellOutput1', 'lstmCellOutput2'] 186 }], 187 'expectedOutputs': { 188 'lstmCellOutput1': { 189 'data': [1, 8, 27, 216], 190 'descriptor': {shape: [2, 2], dataType: 'float32'} 191 }, 192 'lstmCellOutput2': { 193 'data': [1, 4, 9, 36], 194 'descriptor': {shape: [2, 2], dataType: 'float32'} 195 } 196 } 197 } 198 }, 199 { 200 'name': 201 "lstmCell float32 tensors with options.bias, options.recurrentBias, options.activations=['relu', 'relu', 'relu'] and explicit options.layout='iofg'", 202 'graph': { 203 'inputs': { 204 'lstmCellInput': { 205 'data': [1, 2, 2, 1], 206 'descriptor': {shape: [2, 2], dataType: 'float32'} 207 }, 208 'lstmCellWeight': { 209 'data': [1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2], 210 'descriptor': {shape: [8, 2], dataType: 'float32'}, 211 'constant': true 212 }, 213 'lstmCellRecurrentWeight': { 214 'data': [ 215 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 216 0.1, 0.1, 0.1 217 ], 218 'descriptor': {shape: [8, 2], dataType: 'float32'}, 219 'constant': true 220 }, 221 'lstmCellHiddenState': { 222 'data': [0, 0, 0, 0], 223 'descriptor': {shape: [2, 2], dataType: 'float32'} 224 }, 225 'lstmCellCellState': { 226 'data': [0, 0, 0, 0], 227 'descriptor': {shape: [2, 2], dataType: 'float32'} 228 }, 229 'lstmCellBias': { 230 'data': [1, 2, 1, 2, 1, 2, 1, 2], 231 'descriptor': {shape: [8], dataType: 'float32'}, 232 'constant': true 233 }, 234 'lstmCellRecurrentBias': { 235 'data': [1, 2, 1, 2, 1, 2, 1, 2], 236 'descriptor': {shape: [8], dataType: 'float32'}, 237 'constant': true 238 } 239 }, 240 'operators': [{ 241 'name': 'lstmCell', 242 'arguments': [ 243 {'input': 'lstmCellInput'}, {'weight': 'lstmCellWeight'}, 244 {'recurrentWeight': 'lstmCellRecurrentWeight'}, 245 {'hiddenState': 'lstmCellHiddenState'}, 246 {'cellState': 'lstmCellCellState'}, {'hiddenSize': 2}, { 247 'options': { 248 'bias': 'lstmCellBias', 249 'recurrentBias': 'lstmCellRecurrentBias', 250 'layout': 'iofg', 251 'activations': ['relu', 'relu', 'relu'] 252 } 253 } 254 ], 255 'outputs': ['lstmCellOutput1', 'lstmCellOutput2'] 256 }], 257 'expectedOutputs': { 258 'lstmCellOutput1': { 259 'data': [1, 8, 27, 216], 260 'descriptor': {shape: [2, 2], dataType: 'float32'} 261 }, 262 'lstmCellOutput2': { 263 'data': [1, 4, 9, 36], 264 'descriptor': {shape: [2, 2], dataType: 'float32'} 265 } 266 } 267 } 268 }, 269 { 270 'name': 271 "lstmCell float32 tensors with options.bias, options.recurrentBias, options.activations=['relu', 'relu', 'relu'] and options.layout='ifgo'", 272 'graph': { 273 'inputs': { 274 'lstmCellInput': { 275 'data': [1, 2, 2, 1], 276 'descriptor': {shape: [2, 2], dataType: 'float32'} 277 }, 278 'lstmCellWeight': { 279 'data': [1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2], 280 'descriptor': {shape: [8, 2], dataType: 'float32'}, 281 'constant': true 282 }, 283 'lstmCellRecurrentWeight': { 284 'data': [ 285 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 286 0.1, 0.1, 0.1 287 ], 288 'descriptor': {shape: [8, 2], dataType: 'float32'}, 289 'constant': true 290 }, 291 'lstmCellHiddenState': { 292 'data': [0, 0, 0, 0], 293 'descriptor': {shape: [2, 2], dataType: 'float32'} 294 }, 295 'lstmCellCellState': { 296 'data': [0, 0, 0, 0], 297 'descriptor': {shape: [2, 2], dataType: 'float32'} 298 }, 299 'lstmCellBias': { 300 'data': [1, 2, 1, 2, 1, 2, 1, 2], 301 'descriptor': {shape: [8], dataType: 'float32'}, 302 'constant': true 303 }, 304 'lstmCellRecurrentBias': { 305 'data': [1, 2, 1, 2, 1, 2, 1, 2], 306 'descriptor': {shape: [8], dataType: 'float32'}, 307 'constant': true 308 } 309 }, 310 'operators': [{ 311 'name': 'lstmCell', 312 'arguments': [ 313 {'input': 'lstmCellInput'}, {'weight': 'lstmCellWeight'}, 314 {'recurrentWeight': 'lstmCellRecurrentWeight'}, 315 {'hiddenState': 'lstmCellHiddenState'}, 316 {'cellState': 'lstmCellCellState'}, {'hiddenSize': 2}, { 317 'options': { 318 'bias': 'lstmCellBias', 319 'recurrentBias': 'lstmCellRecurrentBias', 320 'layout': 'ifgo', 321 'activations': ['relu', 'relu', 'relu'] 322 } 323 } 324 ], 325 'outputs': ['lstmCellOutput1', 'lstmCellOutput2'] 326 }], 327 'expectedOutputs': { 328 'lstmCellOutput1': { 329 'data': [1, 8, 27, 216], 330 'descriptor': {shape: [2, 2], dataType: 'float32'} 331 }, 332 'lstmCellOutput2': { 333 'data': [1, 4, 9, 36], 334 'descriptor': {shape: [2, 2], dataType: 'float32'} 335 } 336 } 337 } 338 }, 339 { 340 'name': 'lstmCell float32 tensors with all options', 341 'graph': { 342 'inputs': { 343 'lstmCellInput': { 344 'data': [1, 2, 2, 1], 345 'descriptor': {shape: [2, 2], dataType: 'float32'} 346 }, 347 'lstmCellWeight': { 348 'data': [1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2], 349 'descriptor': {shape: [8, 2], dataType: 'float32'}, 350 'constant': true 351 }, 352 'lstmCellRecurrentWeight': { 353 'data': [ 354 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 355 0.1, 0.1, 0.1 356 ], 357 'descriptor': {shape: [8, 2], dataType: 'float32'}, 358 'constant': true 359 }, 360 'lstmCellHiddenState': { 361 'data': [0, 0, 0, 0], 362 'descriptor': {shape: [2, 2], dataType: 'float32'} 363 }, 364 'lstmCellCellState': { 365 'data': [0, 0, 0, 0], 366 'descriptor': {shape: [2, 2], dataType: 'float32'} 367 }, 368 'lstmCellBias': { 369 'data': [1, 2, 1, 2, 1, 2, 1, 2], 370 'descriptor': {shape: [8], dataType: 'float32'}, 371 'constant': true 372 }, 373 'lstmCellRecurrentBias': { 374 'data': [1, 2, 1, 2, 1, 2, 1, 2], 375 'descriptor': {shape: [8], dataType: 'float32'}, 376 'constant': true 377 }, 378 'lstmCellPeepholeWeight': { 379 'data': [0, 0, 0, 0, 0, 0], 380 'descriptor': {shape: [6], dataType: 'float32'}, 381 'constant': true 382 } 383 }, 384 'operators': [{ 385 'name': 'lstmCell', 386 'arguments': [ 387 {'input': 'lstmCellInput'}, {'weight': 'lstmCellWeight'}, 388 {'recurrentWeight': 'lstmCellRecurrentWeight'}, 389 {'hiddenState': 'lstmCellHiddenState'}, 390 {'cellState': 'lstmCellCellState'}, {'hiddenSize': 2}, { 391 'options': { 392 'bias': 'lstmCellBias', 393 'recurrentBias': 'lstmCellRecurrentBias', 394 'peepholeWeight': 'lstmCellPeepholeWeight', 395 'layout': 'iofg', 396 'activations': ['relu', 'relu', 'relu'] 397 } 398 } 399 ], 400 'outputs': ['lstmCellOutput1', 'lstmCellOutput2'] 401 }], 402 'expectedOutputs': { 403 'lstmCellOutput1': { 404 'data': [1, 8, 27, 216], 405 'descriptor': {shape: [2, 2], dataType: 'float32'} 406 }, 407 'lstmCellOutput2': { 408 'data': [1, 4, 9, 36], 409 'descriptor': {shape: [2, 2], dataType: 'float32'} 410 } 411 } 412 } 413 }, 414 415 // float16 tests 416 { 417 'name': 418 "lstmCell float16 tensors with options.bias, options.recurrentBias and options.activations=['relu', 'relu', 'relu']", 419 'graph': { 420 'inputs': { 421 'lstmCellInput': { 422 'data': [1, 2, 2, 1], 423 'descriptor': {shape: [2, 2], dataType: 'float16'} 424 }, 425 'lstmCellWeight': { 426 'data': [1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2], 427 'descriptor': {shape: [8, 2], dataType: 'float16'}, 428 'constant': true 429 }, 430 'lstmCellRecurrentWeight': { 431 'data': [ 432 0.0999755859375, 0.0999755859375, 0.0999755859375, 0.0999755859375, 433 0.0999755859375, 0.0999755859375, 0.0999755859375, 0.0999755859375, 434 0.0999755859375, 0.0999755859375, 0.0999755859375, 0.0999755859375, 435 0.0999755859375, 0.0999755859375, 0.0999755859375, 0.0999755859375 436 ], 437 'descriptor': {shape: [8, 2], dataType: 'float16'}, 438 'constant': true 439 }, 440 'lstmCellHiddenState': { 441 'data': [0, 0, 0, 0], 442 'descriptor': {shape: [2, 2], dataType: 'float16'} 443 }, 444 'lstmCellCellState': { 445 'data': [0, 0, 0, 0], 446 'descriptor': {shape: [2, 2], dataType: 'float16'} 447 }, 448 'lstmCellBias': { 449 'data': [1, 2, 1, 2, 1, 2, 1, 2], 450 'descriptor': {shape: [8], dataType: 'float16'}, 451 'constant': true 452 }, 453 'lstmCellRecurrentBias': { 454 'data': [1, 2, 1, 2, 1, 2, 1, 2], 455 'descriptor': {shape: [8], dataType: 'float16'}, 456 'constant': true 457 } 458 }, 459 'operators': [{ 460 'name': 'lstmCell', 461 'arguments': [ 462 {'input': 'lstmCellInput'}, {'weight': 'lstmCellWeight'}, 463 {'recurrentWeight': 'lstmCellRecurrentWeight'}, 464 {'hiddenState': 'lstmCellHiddenState'}, 465 {'cellState': 'lstmCellCellState'}, {'hiddenSize': 2}, { 466 'options': { 467 'bias': 'lstmCellBias', 468 'recurrentBias': 'lstmCellRecurrentBias', 469 'activations': ['relu', 'relu', 'relu'] 470 } 471 } 472 ], 473 'outputs': ['lstmCellOutput1', 'lstmCellOutput2'] 474 }], 475 'expectedOutputs': { 476 'lstmCellOutput1': { 477 'data': [1, 8, 27, 216], 478 'descriptor': {shape: [2, 2], dataType: 'float16'} 479 }, 480 'lstmCellOutput2': { 481 'data': [1, 4, 9, 36], 482 'descriptor': {shape: [2, 2], dataType: 'float16'} 483 } 484 } 485 } 486 }, 487 { 488 'name': 489 "lstmCell float16 tensors with options.bias, options.recurrentBias, options.activations=['relu', 'relu', 'relu'] and options.peepholeWeight", 490 'graph': { 491 'inputs': { 492 'lstmCellInput': { 493 'data': [1, 2, 2, 1], 494 'descriptor': {shape: [2, 2], dataType: 'float16'} 495 }, 496 'lstmCellWeight': { 497 'data': [1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2], 498 'descriptor': {shape: [8, 2], dataType: 'float16'}, 499 'constant': true 500 }, 501 'lstmCellRecurrentWeight': { 502 'data': [ 503 0.0999755859375, 0.0999755859375, 0.0999755859375, 0.0999755859375, 504 0.0999755859375, 0.0999755859375, 0.0999755859375, 0.0999755859375, 505 0.0999755859375, 0.0999755859375, 0.0999755859375, 0.0999755859375, 506 0.0999755859375, 0.0999755859375, 0.0999755859375, 0.0999755859375 507 ], 508 'descriptor': {shape: [8, 2], dataType: 'float16'}, 509 'constant': true 510 }, 511 'lstmCellHiddenState': { 512 'data': [0, 0, 0, 0], 513 'descriptor': {shape: [2, 2], dataType: 'float16'} 514 }, 515 'lstmCellCellState': { 516 'data': [0, 0, 0, 0], 517 'descriptor': {shape: [2, 2], dataType: 'float16'} 518 }, 519 'lstmCellBias': { 520 'data': [1, 2, 1, 2, 1, 2, 1, 2], 521 'descriptor': {shape: [8], dataType: 'float16'}, 522 'constant': true 523 }, 524 'lstmCellRecurrentBias': { 525 'data': [1, 2, 1, 2, 1, 2, 1, 2], 526 'descriptor': {shape: [8], dataType: 'float16'}, 527 'constant': true 528 }, 529 'lstmCellPeepholeWeight': { 530 'data': [0, 0, 0, 0, 0, 0], 531 'descriptor': {shape: [6], dataType: 'float16'}, 532 'constant': true 533 } 534 }, 535 'operators': [{ 536 'name': 'lstmCell', 537 'arguments': [ 538 {'input': 'lstmCellInput'}, {'weight': 'lstmCellWeight'}, 539 {'recurrentWeight': 'lstmCellRecurrentWeight'}, 540 {'hiddenState': 'lstmCellHiddenState'}, 541 {'cellState': 'lstmCellCellState'}, {'hiddenSize': 2}, { 542 'options': { 543 'bias': 'lstmCellBias', 544 'recurrentBias': 'lstmCellRecurrentBias', 545 'peepholeWeight': 'lstmCellPeepholeWeight', 546 'activations': ['relu', 'relu', 'relu'] 547 } 548 } 549 ], 550 'outputs': ['lstmCellOutput1', 'lstmCellOutput2'] 551 }], 552 'expectedOutputs': { 553 'lstmCellOutput1': { 554 'data': [1, 8, 27, 216], 555 'descriptor': {shape: [2, 2], dataType: 'float16'} 556 }, 557 'lstmCellOutput2': { 558 'data': [1, 4, 9, 36], 559 'descriptor': {shape: [2, 2], dataType: 'float16'} 560 } 561 } 562 } 563 }, 564 { 565 'name': 566 "lstmCell float16 tensors with options.bias, options.recurrentBias, options.activations=['relu', 'relu', 'relu'] and explicit options.layout='iofg'", 567 'graph': { 568 'inputs': { 569 'lstmCellInput': { 570 'data': [1, 2, 2, 1], 571 'descriptor': {shape: [2, 2], dataType: 'float16'} 572 }, 573 'lstmCellWeight': { 574 'data': [1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2], 575 'descriptor': {shape: [8, 2], dataType: 'float16'}, 576 'constant': true 577 }, 578 'lstmCellRecurrentWeight': { 579 'data': [ 580 0.0999755859375, 0.0999755859375, 0.0999755859375, 0.0999755859375, 581 0.0999755859375, 0.0999755859375, 0.0999755859375, 0.0999755859375, 582 0.0999755859375, 0.0999755859375, 0.0999755859375, 0.0999755859375, 583 0.0999755859375, 0.0999755859375, 0.0999755859375, 0.0999755859375 584 ], 585 'descriptor': {shape: [8, 2], dataType: 'float16'}, 586 'constant': true 587 }, 588 'lstmCellHiddenState': { 589 'data': [0, 0, 0, 0], 590 'descriptor': {shape: [2, 2], dataType: 'float16'} 591 }, 592 'lstmCellCellState': { 593 'data': [0, 0, 0, 0], 594 'descriptor': {shape: [2, 2], dataType: 'float16'} 595 }, 596 'lstmCellBias': { 597 'data': [1, 2, 1, 2, 1, 2, 1, 2], 598 'descriptor': {shape: [8], dataType: 'float16'}, 599 'constant': true 600 }, 601 'lstmCellRecurrentBias': { 602 'data': [1, 2, 1, 2, 1, 2, 1, 2], 603 'descriptor': {shape: [8], dataType: 'float16'}, 604 'constant': true 605 } 606 }, 607 'operators': [{ 608 'name': 'lstmCell', 609 'arguments': [ 610 {'input': 'lstmCellInput'}, {'weight': 'lstmCellWeight'}, 611 {'recurrentWeight': 'lstmCellRecurrentWeight'}, 612 {'hiddenState': 'lstmCellHiddenState'}, 613 {'cellState': 'lstmCellCellState'}, {'hiddenSize': 2}, { 614 'options': { 615 'bias': 'lstmCellBias', 616 'recurrentBias': 'lstmCellRecurrentBias', 617 'layout': 'iofg', 618 'activations': ['relu', 'relu', 'relu'] 619 } 620 } 621 ], 622 'outputs': ['lstmCellOutput1', 'lstmCellOutput2'] 623 }], 624 'expectedOutputs': { 625 'lstmCellOutput1': { 626 'data': [1, 8, 27, 216], 627 'descriptor': {shape: [2, 2], dataType: 'float16'} 628 }, 629 'lstmCellOutput2': { 630 'data': [1, 4, 9, 36], 631 'descriptor': {shape: [2, 2], dataType: 'float16'} 632 } 633 } 634 } 635 }, 636 { 637 'name': 638 "lstmCell float16 tensors with options.bias, options.recurrentBias, options.activations=['relu', 'relu', 'relu'] and options.layout='ifgo'", 639 'graph': { 640 'inputs': { 641 'lstmCellInput': { 642 'data': [1, 2, 2, 1], 643 'descriptor': {shape: [2, 2], dataType: 'float16'} 644 }, 645 'lstmCellWeight': { 646 'data': [1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2], 647 'descriptor': {shape: [8, 2], dataType: 'float16'}, 648 'constant': true 649 }, 650 'lstmCellRecurrentWeight': { 651 'data': [ 652 0.0999755859375, 0.0999755859375, 0.0999755859375, 0.0999755859375, 653 0.0999755859375, 0.0999755859375, 0.0999755859375, 0.0999755859375, 654 0.0999755859375, 0.0999755859375, 0.0999755859375, 0.0999755859375, 655 0.0999755859375, 0.0999755859375, 0.0999755859375, 0.0999755859375 656 ], 657 'descriptor': {shape: [8, 2], dataType: 'float16'}, 658 'constant': true 659 }, 660 'lstmCellHiddenState': { 661 'data': [0, 0, 0, 0], 662 'descriptor': {shape: [2, 2], dataType: 'float16'} 663 }, 664 'lstmCellCellState': { 665 'data': [0, 0, 0, 0], 666 'descriptor': {shape: [2, 2], dataType: 'float16'} 667 }, 668 'lstmCellBias': { 669 'data': [1, 2, 1, 2, 1, 2, 1, 2], 670 'descriptor': {shape: [8], dataType: 'float16'}, 671 'constant': true 672 }, 673 'lstmCellRecurrentBias': { 674 'data': [1, 2, 1, 2, 1, 2, 1, 2], 675 'descriptor': {shape: [8], dataType: 'float16'}, 676 'constant': true 677 } 678 }, 679 'operators': [{ 680 'name': 'lstmCell', 681 'arguments': [ 682 {'input': 'lstmCellInput'}, {'weight': 'lstmCellWeight'}, 683 {'recurrentWeight': 'lstmCellRecurrentWeight'}, 684 {'hiddenState': 'lstmCellHiddenState'}, 685 {'cellState': 'lstmCellCellState'}, {'hiddenSize': 2}, { 686 'options': { 687 'bias': 'lstmCellBias', 688 'recurrentBias': 'lstmCellRecurrentBias', 689 'layout': 'ifgo', 690 'activations': ['relu', 'relu', 'relu'] 691 } 692 } 693 ], 694 'outputs': ['lstmCellOutput1', 'lstmCellOutput2'] 695 }], 696 'expectedOutputs': { 697 'lstmCellOutput1': { 698 'data': [1, 8, 27, 216], 699 'descriptor': {shape: [2, 2], dataType: 'float16'} 700 }, 701 'lstmCellOutput2': { 702 'data': [1, 4, 9, 36], 703 'descriptor': {shape: [2, 2], dataType: 'float16'} 704 } 705 } 706 } 707 }, 708 { 709 'name': 'lstmCell float16 tensors with all options', 710 'graph': { 711 'inputs': { 712 'lstmCellInput': { 713 'data': [1, 2, 2, 1], 714 'descriptor': {shape: [2, 2], dataType: 'float16'} 715 }, 716 'lstmCellWeight': { 717 'data': [1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2, 1, -1, 2, -2], 718 'descriptor': {shape: [8, 2], dataType: 'float16'}, 719 'constant': true 720 }, 721 'lstmCellRecurrentWeight': { 722 'data': [ 723 0.0999755859375, 0.0999755859375, 0.0999755859375, 0.0999755859375, 724 0.0999755859375, 0.0999755859375, 0.0999755859375, 0.0999755859375, 725 0.0999755859375, 0.0999755859375, 0.0999755859375, 0.0999755859375, 726 0.0999755859375, 0.0999755859375, 0.0999755859375, 0.0999755859375 727 ], 728 'descriptor': {shape: [8, 2], dataType: 'float16'}, 729 'constant': true 730 }, 731 'lstmCellHiddenState': { 732 'data': [0, 0, 0, 0], 733 'descriptor': {shape: [2, 2], dataType: 'float16'} 734 }, 735 'lstmCellCellState': { 736 'data': [0, 0, 0, 0], 737 'descriptor': {shape: [2, 2], dataType: 'float16'} 738 }, 739 'lstmCellBias': { 740 'data': [1, 2, 1, 2, 1, 2, 1, 2], 741 'descriptor': {shape: [8], dataType: 'float16'}, 742 'constant': true 743 }, 744 'lstmCellRecurrentBias': { 745 'data': [1, 2, 1, 2, 1, 2, 1, 2], 746 'descriptor': {shape: [8], dataType: 'float16'}, 747 'constant': true 748 }, 749 'lstmCellPeepholeWeight': { 750 'data': [0, 0, 0, 0, 0, 0], 751 'descriptor': {shape: [6], dataType: 'float16'}, 752 'constant': true 753 } 754 }, 755 'operators': [{ 756 'name': 'lstmCell', 757 'arguments': [ 758 {'input': 'lstmCellInput'}, {'weight': 'lstmCellWeight'}, 759 {'recurrentWeight': 'lstmCellRecurrentWeight'}, 760 {'hiddenState': 'lstmCellHiddenState'}, 761 {'cellState': 'lstmCellCellState'}, {'hiddenSize': 2}, { 762 'options': { 763 'bias': 'lstmCellBias', 764 'recurrentBias': 'lstmCellRecurrentBias', 765 'peepholeWeight': 'lstmCellPeepholeWeight', 766 'layout': 'iofg', 767 'activations': ['relu', 'relu', 'relu'] 768 } 769 } 770 ], 771 'outputs': ['lstmCellOutput1', 'lstmCellOutput2'] 772 }], 773 'expectedOutputs': { 774 'lstmCellOutput1': { 775 'data': [1, 8, 27, 216], 776 'descriptor': {shape: [2, 2], dataType: 'float16'} 777 }, 778 'lstmCellOutput2': { 779 'data': [1, 4, 9, 36], 780 'descriptor': {shape: [2, 2], dataType: 'float16'} 781 } 782 } 783 } 784 } 785 ]; 786 787 webnn_conformance_test( 788 lstmCellTests, buildAndExecuteGraph, getLstmCellPrecisionTolerance);