npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ts-torch/nn

v0.1.2

Published

Neural network modules for ts-torch

Downloads

10

Readme

@ts-torch/nn

Neural network modules with advanced TypeScript type safety and compile-time shape checking.

Features

  • Type-Safe Shape Inference: Catch shape mismatches at compile time
  • Composable .pipe() Chaining: Build models with fluent, type-checked composition
  • Advanced Weight Initialization: Kaiming (He) and Xavier (Glorot) initialization
  • Functional API: Stateless operations for custom forward passes
  • Parameter Management: Automatic tracking of trainable parameters
  • Training/Eval Modes: Built-in support for different model behaviors

Installation

npm install @ts-torch/nn @ts-torch/core

Quick Start

Type-Safe .pipe() Chaining

import { Linear, ReLU, Softmax } from '@ts-torch/nn';

// Build a classifier with type-safe chaining
const model = new Linear(784, 128)
  .pipe(new ReLU())
  .pipe(new Linear(128, 64))
  .pipe(new ReLU())
  .pipe(new Linear(64, 10))
  .pipe(new Softmax(-1));

// Type: PipedModule<readonly [number, 784], readonly [number, 10]>

// Forward pass with compile-time type checking
const input: Tensor<readonly [32, 784]> = ...;
const output = model.forward(input);
// Type: Tensor<readonly [32, 10]> ✓

Compile-Time Shape Errors

TypeScript catches shape mismatches at compile time:

const layer1 = new Linear(128, 64)
const layer2 = new Linear(256, 10) // Expects 256 inputs

// This will fail to compile!
const invalid = layer1.pipe(layer2)
// Error: Type 'readonly [number, 64]' is not assignable to 'readonly [number, 256]'

Sequential Container

import { Sequential } from '@ts-torch/nn'

// Using Sequential with explicit types
const model = new Sequential<readonly [number, 784], readonly [number, 10]>(
  new Linear(784, 256),
  new ReLU(),
  new Linear(256, 128),
  new ReLU(),
  new Linear(128, 10),
  new Softmax(-1),
)

Sequential Builder (Best Type Inference)

import { sequential } from '@ts-torch/nn'

// Builder pattern with full shape tracking
const model = sequential<readonly [number, 784]>()
  .add(new Linear(784, 256))
  .add(new ReLU())
  .add(new Linear(256, 128))
  .add(new ReLU())
  .add(new Linear(128, 10))
  .add(new Softmax(-1))
  .build()

// Type: Sequential<readonly [number, 784], readonly [number, 10]>

Available Modules

Linear Layers

import { Linear } from '@ts-torch/nn'

// Basic usage
const fc = new Linear(784, 128)

// With options
const fc = new Linear(784, 128, {
  bias: true, // Include bias term (default: true)
  init: 'kaiming_uniform', // Weight initialization strategy
  dtype: DType.float32, // Data type
})

// Initialization strategies:
// - 'kaiming_uniform': He uniform for ReLU networks
// - 'kaiming_normal': He normal for ReLU networks
// - 'xavier_uniform': Glorot uniform for tanh/sigmoid
// - 'xavier_normal': Glorot normal for tanh/sigmoid
// - 'zeros': Zero initialization (testing)

Activation Functions

All activation functions preserve input shape and are type-safe:

import { ReLU, Sigmoid, Tanh, Softmax, LeakyReLU, GELU } from '@ts-torch/nn'

// ReLU: max(0, x)
const relu = new ReLU()

// Sigmoid: 1 / (1 + e^(-x))
const sigmoid = new Sigmoid()

// Tanh: (e^x - e^(-x)) / (e^x + e^(-x))
const tanh = new Tanh()

// Softmax: normalize to probability distribution
const softmax = new Softmax(-1) // dim = -1 (last dimension)

// Leaky ReLU: max(αx, x)
const leaky = new LeakyReLU(0.01) // negative_slope = 0.01

// GELU: Gaussian Error Linear Unit (for transformers)
const gelu = new GELU()

Functional API

Stateless operations for custom forward passes:

import { F } from '@ts-torch/nn'

class CustomModule extends Module {
  forward(x: Tensor) {
    x = F.linear(x, this.weight, this.bias)
    x = F.relu(x)
    x = F.dropout(x, 0.5, this.training)
    x = F.softmax(x, -1)
    return x
  }
}

// Available functions:
// - F.relu, F.sigmoid, F.tanh, F.gelu, F.leakyRelu
// - F.softmax, F.logSoftmax
// - F.dropout
// - F.linear
// - F.normalize, F.clamp

Advanced Examples

Autoencoder

// Encoder: 784 -> 512 -> 256 -> 128
const encoder = new Linear(784, 512)
  .pipe(new ReLU())
  .pipe(new Linear(512, 256))
  .pipe(new ReLU())
  .pipe(new Linear(256, 128))

// Decoder: 128 -> 256 -> 512 -> 784
const decoder = new Linear(128, 256)
  .pipe(new ReLU())
  .pipe(new Linear(256, 512))
  .pipe(new ReLU())
  .pipe(new Linear(512, 784))
  .pipe(new Sigmoid())

// Compose into full autoencoder
const autoencoder = encoder.pipe(decoder)
// Type: PipedModule<readonly [number, 784], readonly [number, 784]>

Reusable Components

// Define building blocks
const hiddenLayer = (inFeatures: number, outFeatures: number) => new Linear(inFeatures, outFeatures).pipe(new ReLU())

const outputLayer = (inFeatures: number, numClasses: number) => new Linear(inFeatures, numClasses).pipe(new Softmax(-1))

// Compose them
const classifier = hiddenLayer(784, 512)
  .pipe(hiddenLayer(512, 256))
  .pipe(hiddenLayer(256, 128))
  .pipe(outputLayer(128, 10))

Parameter Management

const model = new Linear(784, 128).pipe(new ReLU()).pipe(new Linear(128, 10))

// Get all parameters
const params = model.parameters()
console.log(`Model has ${params.length} parameter tensors`)

// Get named parameters (for debugging/analysis)
const namedParams = model.namedParameters()
for (const [name, param] of namedParams) {
  console.log(`${name}: shape=${param.data.shape}, requires_grad=${param.requiresGrad}`)
}
// Output:
// 0.weight: shape=[128, 784], requires_grad=true
// 0.bias: shape=[128], requires_grad=true
// 1.weight: shape=[10, 128], requires_grad=true
// 1.bias: shape=[10], requires_grad=true

Training vs Evaluation Mode

const model = new Linear(784, 128).pipe(new ReLU()).pipe(new Linear(128, 10))

// Training mode (enables dropout, etc.)
model.train()
const trainOutput = model.forward(input)

// Evaluation mode (disables dropout, etc.)
model.eval()
const evalOutput = model.forward(input)

// Toggle back to training
model.train(true)

Type System

The module system uses advanced TypeScript generics to provide compile-time guarantees:

/**
 * Base Module type signature
 */
abstract class Module<
  InShape extends Shape = Shape,      // Input tensor shape
  OutShape extends Shape = Shape,     // Output tensor shape
  D extends DType<string> = float32   // Data type
>

/**
 * Example: Linear layer
 */
class Linear<
  InFeatures extends number,
  OutFeatures extends number,
  D extends DType<string> = float32
> extends Module<
  readonly [number, InFeatures],      // Input: [Batch, InFeatures]
  readonly [number, OutFeatures],     // Output: [Batch, OutFeatures]
  D
>

Shape Constraints

The .pipe() method enforces shape compatibility at compile time:

pipe<NextOut extends Shape>(
  next: Module<OutShape, NextOut, D>
): PipedModule<InShape, OutShape, NextOut, D>

The next module's input shape must match OutShape (this module's output shape).

Best Practices

1. Use .pipe() for Linear Compositions

// Good: Type-safe chaining
const model = new Linear(784, 128).pipe(new ReLU()).pipe(new Linear(128, 10))

// Also good: Sequential builder
const model = sequential<readonly [number, 784]>()
  .add(new Linear(784, 128))
  .add(new ReLU())
  .add(new Linear(128, 10))
  .build()

2. Specify Exact Dimensions as Const

const INPUT_DIM = 784 as const
const HIDDEN_DIM = 128 as const
const OUTPUT_DIM = 10 as const

const model = new Linear(INPUT_DIM, HIDDEN_DIM).pipe(new ReLU()).pipe(new Linear(HIDDEN_DIM, OUTPUT_DIM))

3. Use Type Parameters for Generic Models

function createClassifier<InputDim extends number, OutputDim extends number>(inputDim: InputDim, outputDim: OutputDim) {
  return new Linear(inputDim, 256)
    .pipe(new ReLU())
    .pipe(new Linear(256, 128))
    .pipe(new ReLU())
    .pipe(new Linear(128, outputDim))
}

const mnist = createClassifier(784, 10)
const cifar = createClassifier(3072, 10)

4. Leverage Functional API in Custom Modules

import { Module, F } from '@ts-torch/nn'

class CustomLayer extends Module<readonly [number, 128], readonly [number, 64]> {
  weight: Parameter<readonly [64, 128]>

  forward(x: Tensor<readonly [number, 128]>): Tensor<readonly [number, 64]> {
    let out = F.linear(x, this.weight)
    out = F.relu(out)
    out = F.dropout(out, 0.5, this.training)
    return out
  }
}

Weight Initialization

Linear layers support multiple initialization strategies:

Kaiming (He) Initialization

For ReLU networks. Based on He et al. 2015.

// Uniform: W ~ U(-√(6/fan_in), √(6/fan_in))
const layer = new Linear(784, 128, { init: 'kaiming_uniform' })

// Normal: W ~ N(0, √(2/fan_in))
const layer = new Linear(784, 128, { init: 'kaiming_normal' })

Xavier (Glorot) Initialization

For tanh/sigmoid networks. Based on Glorot & Bengio 2010.

// Uniform: W ~ U(-√(6/(fan_in+fan_out)), √(6/(fan_in+fan_out)))
const layer = new Linear(784, 128, { init: 'xavier_uniform' })

// Normal: W ~ N(0, √(2/(fan_in+fan_out)))
const layer = new Linear(784, 128, { init: 'xavier_normal' })

License

MIT