Skip to content

completed lstm_cell#70

Merged
huningxin merged 2 commits intowebmachinelearning:mainfrom
mei1127:add_lstmCell
Apr 16, 2024
Merged

completed lstm_cell#70
huningxin merged 2 commits intowebmachinelearning:mainfrom
mei1127:add_lstmCell

Conversation

@mei1127
Copy link
Copy Markdown
Contributor

@mei1127 mei1127 commented Feb 28, 2024

Comment thread src/lstm_cell.js Outdated
* @param {MLLstmCellOptions} options
* return {Tensor}
*/

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove this blank line.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK

Comment thread src/lstm_cell.js Outdated
validateLstmCellParams(...arguments);
const zero = new Scalar(0);
const inputSize = input.shape[1];
const starts = layout === 'iofg' ? {i: 0, o: hiddenSize, f: 2* hiddenSize, g: 3*hiddenSize} :
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const starts = layout === 'iofg' ? {i: 0, o: hiddenSize, f: 2* hiddenSize, g: 3*hiddenSize} :
const starts = layout === 'iofg' ? {i: 0, o: hiddenSize, f: 2 * hiddenSize, g: 3 * hiddenSize} :
{i: 0, f: hiddenSize, g: 2 * hiddenSize, o: 3 * hiddenSize};

Comment thread test/lstm_cell_test.js Outdated
import * as utils from './utils.js';

describe('test lstmCell', function() {
it.only('lstmCell lstmCell activations=[relu, relu, relu]', function() {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use it() method.

Comment thread test/lstm_cell_test.js
const hiddenSize = 2;
const input = new Tensor([batchSize, inputSize], [1, 2, 2, 1]);
const weight = new Tensor([4 * hiddenSize, inputSize],
new Float32Array([
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer keep 2 space indentations.

Copy link
Copy Markdown

@fdwr fdwr Mar 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer keep 2 space indentations.

👍 Yeah, although I much prefer 4-space indents over 2-space indents to more clearly/accurately/quickly see the overall hierarchy of blocks, even more important is consistency within a codebase, and since the rest of the files are 2-space, then I'd do so here too (a mix of both 4-space and 2-space makes it harder to follow the levels too :'-( ).

There are lots of possible ways to do it, but picking one and sticking with it is better than switching between 3 different kinds of indentation. e.g.

Linear flow (uses more vertical space, but it's highly scannable for the eye to quickly locate code, efficient to glean overall block structure, consistently symmetric in constructs, and easily diffable)
    const hiddenState = new Tensor(                          // ->
      [batchSize, hiddenSize],                               //  0
      new Float32Array(batchSize * hiddenSize).fill(0),      //  1
    );                                                       // <-
    const cellState = new Tensor(                            // ->
      [batchSize, hiddenSize],                               //  0
      new Float32Array(batchSize * hiddenSize).fill(0),      //  1
    );                                                       // <-
    const activations = [                                    // ->
      relu,                                                  //  0
      relu,                                                  //  1
      relu,                                                  //  2
    ];                                                       // <-
    const outputs = lstmCell(
      input,
      weight,
      recurrentWeight,
      hiddenState,
      cellState,
      hiddenSize,
      {bias, recurrentBias, peepholeWeight, activations}
    );
Compact zig-zag ragged wrap with variable indent for nested lines (slower to scan and spot identifiers, and terrible for diffing, but shaves vertical space):
    const hiddenState = new Tensor([batchSize, hiddenSize],
                                   new Float32Array(batchSize * hiddenSize).fill(0));
    const cellState = new Tensor([batchSize, hiddenSize],
                                 new Float32Array(batchSize * hiddenSize).fill(0));
    const activations = [relu, relu, relu];
    const outputs = lstmCell(input, weight, recurrentWeight, hiddenState, cellState, hiddenSize,
                             {bias, recurrentBias, peepholeWeight, activations});
Compact zig-zag ragged wrap with uniform indentation for nested lines (slower to scan, bad for diffing albeit it a little less than #‌1, and shaves less vertical space):
    const hiddenState = new Tensor(
      [batchSize, hiddenSize],
      new Float32Array(batchSize * hiddenSize).fill(0));
    const cellState = new Tensor(
      [batchSize, hiddenSize],
      new Float32Array(batchSize * hiddenSize).fill(0));
    const activations = [
      relu, relu, relu];
    const outputs = lstmCell(
      input, weight, recurrentWeight, hiddenState, cellState, hiddenSize,
      {bias, recurrentBias, peepholeWeight, activations});

@BruceDai
Copy link
Copy Markdown
Contributor

Thanks @mei1127.
LGTM with some nits, please do some modifications.

Copy link
Copy Markdown

@fdwr fdwr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor comments. Thanks Mei.

Comment thread src/lstm_cell.js
Comment on lines +32 to +33
const starts = layout === 'iofg' ? {i: 0, o: hiddenSize, f: 2 * hiddenSize, g: 3 *hiddenSize} :
{i: 0, f: hiddenSize, g: 2 * hiddenSize, o: 3 * hiddenSize};
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be easier for future readers to read if indentation was aligned consistently:

Suggested change
const starts = layout === 'iofg' ? {i: 0, o: hiddenSize, f: 2 * hiddenSize, g: 3 *hiddenSize} :
{i: 0, f: hiddenSize, g: 2 * hiddenSize, o: 3 * hiddenSize};
const starts = layout === 'iofg' ? {i: 0, o: hiddenSize, f: 2 * hiddenSize, g: 3 *hiddenSize} :
{i: 0, f: hiddenSize, g: 2 * hiddenSize, o: 3 * hiddenSize};

Comment thread test/lstm_cell_test.js
const hiddenSize = 2;
const input = new Tensor([batchSize, inputSize], [1, 2, 2, 1]);
const weight = new Tensor([4 * hiddenSize, inputSize],
new Float32Array([
Copy link
Copy Markdown

@fdwr fdwr Mar 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer keep 2 space indentations.

👍 Yeah, although I much prefer 4-space indents over 2-space indents to more clearly/accurately/quickly see the overall hierarchy of blocks, even more important is consistency within a codebase, and since the rest of the files are 2-space, then I'd do so here too (a mix of both 4-space and 2-space makes it harder to follow the levels too :'-( ).

There are lots of possible ways to do it, but picking one and sticking with it is better than switching between 3 different kinds of indentation. e.g.

Linear flow (uses more vertical space, but it's highly scannable for the eye to quickly locate code, efficient to glean overall block structure, consistently symmetric in constructs, and easily diffable)
    const hiddenState = new Tensor(                          // ->
      [batchSize, hiddenSize],                               //  0
      new Float32Array(batchSize * hiddenSize).fill(0),      //  1
    );                                                       // <-
    const cellState = new Tensor(                            // ->
      [batchSize, hiddenSize],                               //  0
      new Float32Array(batchSize * hiddenSize).fill(0),      //  1
    );                                                       // <-
    const activations = [                                    // ->
      relu,                                                  //  0
      relu,                                                  //  1
      relu,                                                  //  2
    ];                                                       // <-
    const outputs = lstmCell(
      input,
      weight,
      recurrentWeight,
      hiddenState,
      cellState,
      hiddenSize,
      {bias, recurrentBias, peepholeWeight, activations}
    );
Compact zig-zag ragged wrap with variable indent for nested lines (slower to scan and spot identifiers, and terrible for diffing, but shaves vertical space):
    const hiddenState = new Tensor([batchSize, hiddenSize],
                                   new Float32Array(batchSize * hiddenSize).fill(0));
    const cellState = new Tensor([batchSize, hiddenSize],
                                 new Float32Array(batchSize * hiddenSize).fill(0));
    const activations = [relu, relu, relu];
    const outputs = lstmCell(input, weight, recurrentWeight, hiddenState, cellState, hiddenSize,
                             {bias, recurrentBias, peepholeWeight, activations});
Compact zig-zag ragged wrap with uniform indentation for nested lines (slower to scan, bad for diffing albeit it a little less than #‌1, and shaves less vertical space):
    const hiddenState = new Tensor(
      [batchSize, hiddenSize],
      new Float32Array(batchSize * hiddenSize).fill(0));
    const cellState = new Tensor(
      [batchSize, hiddenSize],
      new Float32Array(batchSize * hiddenSize).fill(0));
    const activations = [
      relu, relu, relu];
    const outputs = lstmCell(
      input, weight, recurrentWeight, hiddenState, cellState, hiddenSize,
      {bias, recurrentBias, peepholeWeight, activations});

Comment thread src/lstm_cell.js
// output hidden state (ht)
const ht = mul(o, activation2(ct));

return [ht, ct];
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Full names are nice, like return [hiddenState, cellState]. Plus you already spell these names hiddenState and cellStates elsewhere below, which would be more consistent.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe hiddenStateNew could be better for understand and differentiate from the previous state?

Comment thread src/lib/validate-input.js
throw new Error(`The hiddenState (rank ${hiddenState.rank}) is not a 2-D tensor.`);
}
if (hiddenState.shape[0] !== batchSize || hiddenState.shape[1] !== hiddenSize) {
throw new Error(`The shape of hiddenState
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message is split.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants