naive-bayes icon indicating copy to clipboard operation
naive-bayes copied to clipboard

TypeError: first argument must be a positive number

Open goldsziggy opened this issue 7 years ago • 11 comments

When attempting to run with the following data-sets:

const cases = [ [ 200, 100, 1500, 500, 2700 ],
  [ 300, 25, 1555, 750, 2800 ],
  [ 150, 200, 2000, 50, 2150 ],
  [ 400, 15, 1250, 450, 3000 ],
  [ 202, 45, 1555, 400, 2500 ],
  [ 251, 87, 1575, 325, 2000 ],
  [ 175, 30, 1475, 300, 2222 ],
  [ 225, 100, 1444, 500, 2300 ],
  [ 300, 15, 1543, 555, 2500 ],
  [ 222, 10, 1345, 520, 2345 ] ]
const predictions = [ 2.5555555555555554,
  2.817857142857143,
  4,
  2.1149999999999998,
  2.6424000000000003,
  4,
  2.6732673267326734,
  2.959565217391304,
  2.8956,
  2.6827292110874197 ]

I am getting the following stsack:

TypeError: First argument must be a positive number or an array
    at Matrix (/Users/ZYG9085/sandbox/geek-out/machine-learn-test/node_modules/ml-matrix/matrix.js:3006:19)
    at NaiveBayesEx.separateClasses (/Users/ZYG9085/sandbox/geek-out/machine-learn-test/src/app/components/naive-bayes.js:89:29)
    at new NaiveBayesEx (/Users/ZYG9085/sandbox/geek-out/machine-learn-test/src/app/components/naive-bayes.js:40:10)

I believe this is from the implementation of seperateClasses, but have yet to dig too deep

goldsziggy avatar Aug 31 '17 15:08 goldsziggy

Are you doing some kind of regression? because predictions should be integers @goldsziggy

JeffersonH44 avatar Sep 01 '17 09:09 JeffersonH44

In fact when we use classification the result is a defined class. So the result can't be continuous. You will probably have to define classes (e.g : class "0" corresponds to float < 2, class "1" to float between 2 and 2.1, class "2" to float between 2.1 and 2.2, etc.). I believe that what you want to do is a regression, not a classification.

jajoe avatar Sep 01 '17 11:09 jajoe

I was looking thoght this issue and I looked this method separateClasses and it is doing wrong, becose it went creating an array and incrementing every index corresponding the classes of y, then when it interates with 'classes' variable certatly it will find an undefined value and will throws an Exception. I will try to fix this as soon as posible, I will be glad if the repository admin looked at this too

rzorzal avatar Oct 25 '17 18:10 rzorzal

I will look at it, thanks for reporting it @rzorzal

JeffersonH44 avatar Oct 25 '17 23:10 JeffersonH44

I have run into the same issue, the reason is that the classes need to be a continuous sequence of integers, starting with 0. So, [ 0, 1, 2, 3] is valid, while invalid are all of [ 1, 2, 3 ] [ 0, 1, 3 ] [ 'a', 'b', 'c' ]

I'm solving it by

let classIndices = stringPredictions.reduce((o, key) => { o[key] = 0; return o; }, {});
Object.keys(classIndices).forEach((key, idx) => { classIndices[key] = idx; });
var predictions = stringPredictions.map(r => classIndices[r]);

but this won't work if I train on several datasets and some of them just don't contain some of the classes.

pavelstudeny avatar Mar 01 '18 15:03 pavelstudeny

I encountered this issue as well and when debugging I found exactly what @rzorzal was talking about. my "classes" were two integers: 1 and -1 and it went to the undefined case already mentioned. When I changed the classes to 0 and 1 it was OK, still it means we need to have some dictionaries in our code when dealing with certain examples whose classes are not consecutive integers.

victorbadila avatar Oct 29 '18 12:10 victorbadila

We would gladly accept a pull request to fix this :)

targos avatar Oct 29 '18 13:10 targos

I think I made a fix for it locally, but it's pretty ugly right now. I'll clean it up and push a branch tomorrow if I get some time in the afternoon.

victorbadila avatar Oct 29 '18 17:10 victorbadila

@targos check out this branch and how it diffs with the current master https://github.com/victorbadila/naive-bayes/tree/fix/type-error-first-argument

It's work in progress but hopefully it reveals details about the problem. I added some tests for the extra cases, however there is a recurring problem with separateClasses returning an array whose indexes would be the predictions values (0, 1, etc.). If we want to support chars or strings for example as prediction values they would still be assignable as array indexes (you can do myArray["a"]), however if you want to loop through it later you would have to get it's actual keys and not use the usual iteration, and finally getting the keys via Object.keys(myArray) would lead to possible type changes for prediction values which are numbers, as Object.keys.. returns an array of strings. This can be seen in how I modified the tests. But this breaks the API. I would propose having separateClasses return a dictionary instead of an array and have some extra info for each entry in order to know if the key should be a string, number, etc. aka the original prediction value.

victorbadila avatar Oct 30 '18 08:10 victorbadila

@targos please check this PR: https://github.com/mljs/naive-bayes/pull/12/files

It works so far for GaussianNB, if you or anyone maintining this are OK with the changes over there I will update the things for MultinomialNB as well.

victorbadila avatar Nov 05 '18 18:11 victorbadila

Can this please be merged yet? I experienced the same issue, 3 years later.

niftylettuce avatar Apr 26 '20 01:04 niftylettuce