gyrdym/ml_linalg

Mathematical operations with vectors

MoiShO opened this issue · 2 comments

In version bigger then 12.7.1 trouble with multiply vectors, in version 12.7.1 all ok

// factorize.dart
import 'dart:math';
import 'package:ml_linalg/linalg.dart';

class Factorization {
  Matrix weights;
  Matrix features;

  Factorization(this.weights, this.features);
}

var weights = Matrix.fromList([
  [0.745161771774292, 0.49491751194000244, 0.31594449281692505],
  [0.4236903786659241, 0.7222552299499512, 0.03950809687376022]
]);

var features = Matrix.fromList([
  [
    0.034754883497953415, 0.15588359534740448, 0.6534027457237244, 0.3005395531654358, 0.610332727432251,
    0.3886837959289551, 0.8214156031608582, 0.5842974185943604, 0.8119133114814758, 0.0993831604719162,
    0.5189520120620728, 0.28814324736595154, 0.07271663844585419, 0.9153922200202942, 0.5082831978797913,
    0.9108881950378418, 0.7938997745513916, 0.6407602429389954
  ],
  [
    0.7462620735168457, 0.3884164094924927, 0.1176198273897171, 0.7724294662475586, 0.10357396304607391,
    0.7664274573326111, 0.5673727989196777, 0.3002673387527466, 0.4880940318107605, 0.5815929770469666, 0.8687184453010559,
    0.32184433937072754, 0.15984183549880981, 0.9650658965110779, 0.30762118101119995, 0.4106738269329071, 0.054108526557683945,
    0.040961407124996185
  ],
  [
    0.6315397620201111, 0.7050033807754517, 0.4593125283718109, 0.816363513469696, 0.6307060718536377, 0.8713419437408447,
    0.39600563049316406, 0.9930526614189148, 0.521530270576477, 0.8103489279747009, 0.713289737701416, 0.13782964646816254, 0.8388209939002991,
    0.9939820766448975, 0.01218094676733017, 0.744495153427124, 0.041512444615364075, 0.6160798072814941
  ]
]);

var m = Matrix.fromList([
  [4.0, 4.0, 5.0, 5.0, 5.0, 2.0, 2.0, 1.0, 1.0, 1.0, 1.0, 2.0, 2.0, 1.0, 1.0, 1.0, 1.0, 1.0],
  [4.0, 5.0, 4.0, 4.0, 5.0, 2.0, 1.0, 1.0, 1.0, 1.0, 1.0, 2.0, 2.0, 1.0, 1.0, 2.0, 2.0, 1.0]
]);

Factorization factorize(Matrix m, {int numOfFeatures = 3, int numOfIterations = 50}) {

  for (var i = 0; i < numOfIterations; i++) {
    final wf = weights * features;
    if (_cost(m, wf) == 0) break;

    final fn = weights.transpose() * m;
    final fd = weights.transpose() * weights * features;
    features = Matrix.fromRows(
      List<Vector>.generate(
        features.rowsNum, (row) => features.getRow(row) * fn.getRow(row) / fd.getRow(row)
      )
    );
    //trouble with multiply vectors here -->
    final wn = m * features.transpose(); // Matrix (NaN, NaN, NaN)
    final wd = weights * features * features.transpose(); // Matrix (NaN, NaN, NaN)
    // <--
    weights = Matrix.fromRows(
      List<Vector>.generate(
        weights.rowsNum, (row) => weights.getRow(row) * wn.getRow(row) / wd.getRow(row)
      )
    );
  }

  return Factorization(weights, features);
}

double _cost(Matrix a, Matrix b) {
  var cost = 0.0;
  for (var i = 0; i < a.rowsNum; i++) {
    for (var j = 0; j < a.columnsNum; j++) {
      cost += pow(a.getRow(i).elementAt(j) - b.getRow(i).elementAt(j), 2);
    }
  }
  return cost;
}

@MoiShO thank you for creating the issue, I will take a look at this

@MoiShO I've found a bug. Please, check out the version 12.17.1. By the way, I'd recommend you to rewrite your code in more concise manner:

Factorization factorize(Matrix m, {int numOfFeatures = 3, int numOfIterations = 50}) {
  for (var i = 0; i < numOfIterations; i++) {
    final wf = weights * features;
    if (_cost(m, wf) == 0) break;

    final fn = weights.transpose() * m;
    final fd = weights.transpose() * weights * features;

    features = features.multiply(fn) / fd;

    final wn = m * features.transpose();
    final wd = weights * features * features.transpose();

    weights = weights.multiply(wn) / wd;
  }

  return Factorization(weights, features);
}

double _cost(Matrix a, Matrix b) {
  return (a - b).pow(2).sum();
}