or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

callbacks.mdimage-processing.mdindex.mdio.mdsavedmodel.mdtensorboard.md

tensorboard.mddocs/

0

# TensorBoard Integration

1

2

TensorFlow.js Node provides comprehensive TensorBoard integration for logging training metrics, visualizing model performance, and monitoring training progress. This enables the same rich visualization capabilities available in Python TensorFlow directly in Node.js applications.

3

4

## Capabilities

5

6

### Summary File Writer

7

8

#### Create Summary Writer

9

10

Create a TensorBoard summary writer for logging scalar and histogram data.

11

12

```typescript { .api }

13

/**

14

* Create a TensorBoard summary writer

15

* @param logdir - Directory to write TensorBoard logs

16

* @param maxQueue - Maximum number of summaries to queue before writing (default: 10)

17

* @param flushMillis - How often to flush summaries to disk in milliseconds (default: 120000)

18

* @param filenameSuffix - Optional suffix for log filenames

19

* @returns SummaryFileWriter instance

20

*/

21

function summaryFileWriter(

22

logdir: string,

23

maxQueue?: number,

24

flushMillis?: number,

25

filenameSuffix?: string

26

): SummaryFileWriter;

27

```

28

29

**Usage Example:**

30

31

```typescript

32

import * as tf from '@tensorflow/tfjs-node';

33

34

// Create a summary writer

35

const writer = tf.node.summaryFileWriter('./logs/training');

36

37

// Log scalar values

38

writer.scalar('loss', 0.5, 1);

39

writer.scalar('accuracy', 0.85, 1);

40

writer.scalar('learning_rate', 0.001, 1);

41

42

// Log with different step

43

writer.scalar('loss', 0.4, 2);

44

writer.scalar('accuracy', 0.87, 2);

45

46

// Force write to disk

47

writer.flush();

48

```

49

50

### TensorBoard Callback

51

52

#### Create TensorBoard Callback

53

54

Create a callback for automatic logging during model training.

55

56

```typescript { .api }

57

/**

58

* Create a TensorBoard callback for model training

59

* @param logdir - Directory to write TensorBoard logs (optional, defaults to './logs')

60

* @param args - Additional configuration options

61

* @returns TensorBoardCallback instance

62

*/

63

function tensorBoard(

64

logdir?: string,

65

args?: TensorBoardCallbackArgs

66

): TensorBoardCallback;

67

68

interface TensorBoardCallbackArgs {

69

/** How often to log ('batch' or 'epoch') */

70

updateFreq?: 'batch' | 'epoch';

71

72

/** How often to log histograms (0 = never) */

73

histogramFreq?: number;

74

}

75

```

76

77

**Usage Example:**

78

79

```typescript

80

import * as tf from '@tensorflow/tfjs-node';

81

82

// Create model

83

const model = tf.sequential({

84

layers: [

85

tf.layers.dense({ inputShape: [4], units: 10, activation: 'relu' }),

86

tf.layers.dense({ units: 3, activation: 'softmax' })

87

]

88

});

89

90

model.compile({

91

optimizer: 'adam',

92

loss: 'sparseCategoricalCrossentropy',

93

metrics: ['accuracy']

94

});

95

96

// Create TensorBoard callback

97

const tensorboardCallback = tf.node.tensorBoard('./logs/experiment_1', {

98

updateFreq: 'epoch',

99

histogramFreq: 1 // Log histograms every epoch

100

});

101

102

// Generate training data

103

const xs = tf.randomNormal([1000, 4]);

104

const ys = tf.randomUniform([1000, 1], 0, 3, 'int32');

105

106

// Train with TensorBoard logging

107

await model.fit(xs, ys, {

108

epochs: 50,

109

batchSize: 32,

110

validationSplit: 0.2,

111

callbacks: [tensorboardCallback]

112

});

113

114

console.log('Training complete. View logs with: tensorboard --logdir ./logs');

115

```

116

117

## SummaryFileWriter Interface

118

119

The `SummaryFileWriter` class provides methods for logging different types of data to TensorBoard.

120

121

```typescript { .api }

122

interface SummaryFileWriter {

123

/** Write a scalar value */

124

scalar(name: string, value: number, step: number, description?: string): void;

125

126

/** Write a histogram of tensor values */

127

histogram(name: string, data: Tensor, step: number, buckets?: number, description?: string): void;

128

129

/** Force write buffered summaries to disk */

130

flush(): void;

131

}

132

```

133

134

### Scalar Logging

135

136

Log scalar metrics like loss, accuracy, and learning rate.

137

138

```typescript { .api }

139

/**

140

* Write a scalar summary

141

* @param name - Name of the scalar (will appear in TensorBoard)

142

* @param value - Scalar value to log

143

* @param step - Training step or epoch number

144

* @param description - Optional description for the metric

145

*/

146

scalar(name: string, value: number, step: number, description?: string): void;

147

```

148

149

**Usage Example:**

150

151

```typescript

152

const writer = tf.node.summaryFileWriter('./logs/metrics');

153

154

// Log training metrics

155

for (let epoch = 0; epoch < 100; epoch++) {

156

// Simulate training

157

const loss = Math.exp(-epoch * 0.1) + Math.random() * 0.1;

158

const accuracy = 1 - Math.exp(-epoch * 0.05) - Math.random() * 0.05;

159

const lr = 0.001 * Math.pow(0.95, epoch);

160

161

// Log to TensorBoard

162

writer.scalar('training/loss', loss, epoch, 'Cross-entropy loss during training');

163

writer.scalar('training/accuracy', accuracy, epoch, 'Classification accuracy');

164

writer.scalar('hyperparameters/learning_rate', lr, epoch, 'Current learning rate');

165

166

// Log validation metrics (simulated)

167

if (epoch % 5 === 0) {

168

const valLoss = loss + Math.random() * 0.05;

169

const valAccuracy = accuracy - Math.random() * 0.02;

170

171

writer.scalar('validation/loss', valLoss, epoch);

172

writer.scalar('validation/accuracy', valAccuracy, epoch);

173

}

174

}

175

176

writer.flush();

177

console.log('Metrics logged. Run: tensorboard --logdir ./logs');

178

```

179

180

### Histogram Logging

181

182

Log histograms of tensor values to visualize weight distributions and activations.

183

184

```typescript { .api }

185

/**

186

* Write a histogram summary

187

* @param name - Name of the histogram

188

* @param data - Tensor containing the data to histogram

189

* @param step - Training step or epoch number

190

* @param buckets - Number of histogram buckets (default: 30)

191

* @param description - Optional description

192

*/

193

histogram(name: string, data: Tensor, step: number, buckets?: number, description?: string): void;

194

```

195

196

**Usage Example:**

197

198

```typescript

199

const writer = tf.node.summaryFileWriter('./logs/weights');

200

201

// Create a model to monitor

202

const model = tf.sequential({

203

layers: [

204

tf.layers.dense({ inputShape: [10], units: 5, activation: 'relu', name: 'hidden' }),

205

tf.layers.dense({ units: 1, activation: 'sigmoid', name: 'output' })

206

]

207

});

208

209

// Log initial weight distributions

210

model.layers.forEach((layer, layerIndex) => {

211

if ('getWeights' in layer) {

212

const weights = layer.getWeights();

213

weights.forEach((weight, weightIndex) => {

214

writer.histogram(

215

`layer_${layerIndex}/weights_${weightIndex}`,

216

weight,

217

0,

218

50,

219

`Weight distribution for layer ${layer.name}`

220

);

221

});

222

}

223

});

224

225

// Simulate training and log weight changes

226

for (let epoch = 1; epoch <= 10; epoch++) {

227

// ... training code here ...

228

229

// Log weight distributions periodically

230

if (epoch % 5 === 0) {

231

model.layers.forEach((layer, layerIndex) => {

232

if ('getWeights' in layer) {

233

const weights = layer.getWeights();

234

weights.forEach((weight, weightIndex) => {

235

writer.histogram(

236

`layer_${layerIndex}/weights_${weightIndex}`,

237

weight,

238

epoch,

239

50

240

);

241

});

242

}

243

});

244

}

245

}

246

247

writer.flush();

248

```

249

250

## TensorBoard Callback Interface

251

252

The `TensorBoardCallback` automatically logs metrics during training.

253

254

```typescript { .api }

255

class TensorBoardCallback extends CustomCallback {

256

constructor(logdir?: string, updateFreq?: 'batch' | 'epoch', histogramFreq?: number);

257

}

258

259

interface TensorBoardCallbackArgs {

260

/** How often to log: 'batch' logs after each batch, 'epoch' logs after each epoch */

261

updateFreq?: 'batch' | 'epoch';

262

263

/** How often to log weight/activation histograms (in epochs, 0 = never) */

264

histogramFreq?: number;

265

}

266

```

267

268

## Advanced Usage Patterns

269

270

### Multi-Experiment Logging

271

272

```typescript

273

async function runExperiment(

274

experimentName: string,

275

learningRate: number,

276

batchSize: number

277

) {

278

const logdir = `./logs/${experimentName}`;

279

const writer = tf.node.summaryFileWriter(logdir);

280

281

// Log hyperparameters

282

writer.scalar('hyperparameters/learning_rate', learningRate, 0);

283

writer.scalar('hyperparameters/batch_size', batchSize, 0);

284

285

// Create model

286

const model = tf.sequential({

287

layers: [

288

tf.layers.dense({ inputShape: [784], units: 128, activation: 'relu' }),

289

tf.layers.dropout({ rate: 0.2 }),

290

tf.layers.dense({ units: 10, activation: 'softmax' })

291

]

292

});

293

294

model.compile({

295

optimizer: tf.train.adam(learningRate),

296

loss: 'sparseCategoricalCrossentropy',

297

metrics: ['accuracy']

298

});

299

300

// Create TensorBoard callback

301

const tbCallback = tf.node.tensorBoard(logdir, {

302

updateFreq: 'epoch',

303

histogramFreq: 5

304

});

305

306

// Generate dummy data

307

const xs = tf.randomNormal([5000, 784]);

308

const ys = tf.randomUniform([5000, 1], 0, 10, 'int32');

309

310

// Train

311

const history = await model.fit(xs, ys, {

312

epochs: 50,

313

batchSize: batchSize,

314

validationSplit: 0.2,

315

callbacks: [tbCallback]

316

});

317

318

// Log final metrics

319

const finalLoss = history.history.loss.slice(-1)[0];

320

const finalAccuracy = history.history.acc.slice(-1)[0];

321

322

writer.scalar('final/loss', finalLoss, 50);

323

writer.scalar('final/accuracy', finalAccuracy, 50);

324

325

writer.flush();

326

327

// Cleanup

328

xs.dispose();

329

ys.dispose();

330

model.dispose();

331

332

return { finalLoss, finalAccuracy };

333

}

334

335

// Run multiple experiments

336

async function hyperparameterSweep() {

337

const experiments = [

338

{ name: 'exp_lr_001_bs_32', lr: 0.001, bs: 32 },

339

{ name: 'exp_lr_01_bs_32', lr: 0.01, bs: 32 },

340

{ name: 'exp_lr_001_bs_64', lr: 0.001, bs: 64 },

341

{ name: 'exp_lr_01_bs_64', lr: 0.01, bs: 64 }

342

];

343

344

for (const exp of experiments) {

345

console.log(`Running experiment: ${exp.name}`);

346

const results = await runExperiment(exp.name, exp.lr, exp.bs);

347

console.log(`Results: loss=${results.finalLoss}, acc=${results.finalAccuracy}`);

348

}

349

350

console.log('All experiments complete. Run: tensorboard --logdir ./logs');

351

}

352

```

353

354

### Custom Metrics Logging

355

356

```typescript

357

class CustomMetricsLogger {

358

private writer: tf.SummaryFileWriter;

359

360

constructor(logdir: string) {

361

this.writer = tf.node.summaryFileWriter(logdir);

362

}

363

364

logTrainingStep(

365

step: number,

366

loss: number,

367

accuracy: number,

368

gradientNorm: number,

369

learningRate: number

370

) {

371

this.writer.scalar('training/loss', loss, step);

372

this.writer.scalar('training/accuracy', accuracy, step);

373

this.writer.scalar('training/gradient_norm', gradientNorm, step);

374

this.writer.scalar('training/learning_rate', learningRate, step);

375

}

376

377

logValidationStep(step: number, valLoss: number, valAccuracy: number) {

378

this.writer.scalar('validation/loss', valLoss, step);

379

this.writer.scalar('validation/accuracy', valAccuracy, step);

380

}

381

382

logModelWeights(model: tf.LayersModel, step: number) {

383

model.layers.forEach((layer, layerIdx) => {

384

if ('getWeights' in layer && layer.getWeights().length > 0) {

385

const weights = layer.getWeights();

386

387

weights.forEach((weight, weightIdx) => {

388

// Log weight statistics

389

const mean = tf.mean(weight);

390

const std = tf.moments(weight).variance.sqrt();

391

const min = tf.min(weight);

392

const max = tf.max(weight);

393

394

this.writer.scalar(`weights/layer_${layerIdx}_${weightIdx}/mean`, mean.dataSync()[0], step);

395

this.writer.scalar(`weights/layer_${layerIdx}_${weightIdx}/std`, std.dataSync()[0], step);

396

this.writer.scalar(`weights/layer_${layerIdx}_${weightIdx}/min`, min.dataSync()[0], step);

397

this.writer.scalar(`weights/layer_${layerIdx}_${weightIdx}/max`, max.dataSync()[0], step);

398

399

// Log histogram

400

this.writer.histogram(`weights/layer_${layerIdx}_${weightIdx}/distribution`, weight, step);

401

402

// Cleanup

403

mean.dispose();

404

std.dispose();

405

min.dispose();

406

max.dispose();

407

});

408

}

409

});

410

}

411

412

flush() {

413

this.writer.flush();

414

}

415

}

416

417

// Usage

418

const logger = new CustomMetricsLogger('./logs/detailed');

419

420

// During training loop

421

for (let step = 0; step < 1000; step++) {

422

// ... training step ...

423

424

logger.logTrainingStep(step, loss, accuracy, gradNorm, lr);

425

426

if (step % 100 === 0) {

427

logger.logValidationStep(step, valLoss, valAccuracy);

428

logger.logModelWeights(model, step);

429

}

430

}

431

432

logger.flush();

433

```

434

435

### Real-time Monitoring

436

437

```typescript

438

class RealTimeTrainingMonitor {

439

private writer: tf.SummaryFileWriter;

440

private startTime: number;

441

442

constructor(logdir: string) {

443

this.writer = tf.node.summaryFileWriter(logdir, 1, 1000); // Flush every second

444

this.startTime = Date.now();

445

}

446

447

logSystemMetrics(step: number) {

448

const memUsage = process.memoryUsage();

449

const timeElapsed = (Date.now() - this.startTime) / 1000; // seconds

450

451

// Log memory usage

452

this.writer.scalar('system/memory_rss_mb', memUsage.rss / 1024 / 1024, step);

453

this.writer.scalar('system/memory_heap_used_mb', memUsage.heapUsed / 1024 / 1024, step);

454

this.writer.scalar('system/memory_heap_total_mb', memUsage.heapTotal / 1024 / 1024, step);

455

456

// Log timing

457

this.writer.scalar('system/time_elapsed_sec', timeElapsed, step);

458

459

// Log TensorFlow.js memory

460

const tfMemory = tf.memory();

461

this.writer.scalar('tensorflow/num_tensors', tfMemory.numTensors, step);

462

this.writer.scalar('tensorflow/num_data_buffers', tfMemory.numDataBuffers, step);

463

this.writer.scalar('tensorflow/num_bytes', tfMemory.numBytes, step);

464

}

465

466

flush() {

467

this.writer.flush();

468

}

469

}

470

471

// Usage during training

472

const monitor = new RealTimeTrainingMonitor('./logs/monitoring');

473

474

// Log system metrics every 10 steps

475

for (let step = 0; step < 1000; step++) {

476

// ... training ...

477

478

if (step % 10 === 0) {

479

monitor.logSystemMetrics(step);

480

monitor.flush();

481

}

482

}

483

```

484

485

## Starting TensorBoard

486

487

After logging data, start TensorBoard to visualize the results:

488

489

```bash

490

tensorboard --logdir ./logs

491

492

# For multiple experiments

493

tensorboard --logdir ./logs --port 6007

494

495

# With custom sampling

496

tensorboard --logdir ./logs --reload_interval 5

497

```

498

499

Then open your browser to `http://localhost:6006` (or the specified port) to view the visualizations.