Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

completed lstm_cell #70

Merged
merged 2 commits into from
Apr 16, 2024
Merged

Conversation

mei1127
Copy link
Contributor

@mei1127 mei1127 commented Feb 28, 2024

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

Copy link
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
Contributor Author

Choose a reason for hiding this comment

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

OK

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
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};

import * as utils from './utils.js';

describe('test lstmCell', function() {
it.only('lstmCell lstmCell activations=[relu, relu, relu]', function() {
Copy link
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.

const hiddenSize = 2;
const input = new Tensor([batchSize, inputSize], [1, 2, 2, 1]);
const weight = new Tensor([4 * hiddenSize, inputSize],
new Float32Array([
Copy link
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

@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
Contributor

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

Copy link

@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 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

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};

const hiddenSize = 2;
const input = new Tensor([batchSize, inputSize], [1, 2, 2, 1]);
const weight = new Tensor([4 * hiddenSize, inputSize],
new Float32Array([
Copy link

@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});

// output hidden state (ht)
const ht = mul(o, activation2(ct));

return [ht, ct];
Copy link

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

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?

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

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.

@huningxin huningxin merged commit 9a7e0a4 into webmachinelearning:main Apr 16, 2024
3 checks passed
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