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

DecisionTreeClassifier serialization/deserialization #254

Open
1 task done
Baael opened this issue Jul 28, 2019 · 5 comments
Open
1 task done

DecisionTreeClassifier serialization/deserialization #254

Baael opened this issue Jul 28, 2019 · 5 comments
Labels
bug Something isn't working

Comments

@Baael
Copy link

Baael commented Jul 28, 2019

  • I'm submitting a ...
  • question about how to use this project
  • Summary
    I am trying to serialize and deserialize DecisionTreeClassifier, however it throws an error. What is a valid way to save tree to file and restore it later?

Source:

const decision = new DecisionTreeClassifier({ featureLabels: ['a','b'] });
const deserialized = new DecisionTreeClassifier({ featureLabels: ['a','b'] });

const X = [[0, 0], [1, 1]];
const y = [0, 1];
decision.fit( X, y );
const serialized = JSON.stringify(decision.toJSON())
deserialized.fromJSON(JSON.parse(serialized))

Stacktrace:

TypeError: node.question.match is not a function
    at DecisionTreeClassifier._predict (C:\apps\ml\src\lib\tree\tree.ts:434:23)
    at DecisionTreeClassifier.predict (C:\apps\ml\src\lib\tree\tree.ts:202:24)
    at Object.predict (C:\apps\ml/dttest.js:12:27)

@gilles-bara
Copy link

The problem is that JSON.stringify will convert the typed classes to regular, non-typed objects. Providing that string to a fromJSON will then only create objects with the same properties, but these objects won't be the original classes with their appropriate methods. I suppose the fromJSON needs to be extended so that proper instances are created of the correct classes.

For the forest this could be something like this:

    BaseRandomForest.prototype.fromJSON = function (_a) {
        var _b = _a.trees, trees = _b === void 0 ? null : _b;
        if (!trees) {
            throw new Error('You must provide both tree to restore the model');
        }
        this.trees = [];
        for (const tree of trees) {
            const t = new tree_1.DecisionTreeClassifier();
            t.fromJSON(tree);
            this.trees.push(t);
        }
    };

A single classifier could then be:

    DecisionTreeClassifier.prototype.fromJSON = function (_a) {
        var _b = _a.featureLabels, featureLabels = _b === void 0 ? null : _b, _c = _a.tree, tree = _c === void 0 ? null : _c, _d = _a.verbose, verbose = _d === void 0 ? false : _d, _e = _a.random_state, random_state = _e === void 0 ? null : _e;
        this.featureLabels = featureLabels;
        const t = new DecisionNode();
        this.tree = t.fromJSON(tree);
        this.verbose = verbose;
        this.randomState = random_state;
    };

And the nodes:

    DecisionNode.prototype.fromJSON = function (_a) {
        if (typeof _a.prediction !== "undefined") {
            return Object.assign(new Leaf([]), _a);
        }
        const q = _a.question;
        this.question = new Question(q.features, q.column, q.value);
        this.falseBranch = (new DecisionNode()).fromJSON(_a.falseBranch);
        this.trueBranch = (new DecisionNode()).fromJSON(_a.trueBranch);
        return this;
    };

Allthough the fromJSON should probably not return the result to be consistent with the existing fromJSON methods, but you get the idea.

@Baael
Copy link
Author

Baael commented Jul 30, 2019

Ahh ok that's explains a lot, thank you very much :)

@JasonShin
Copy link
Member

Hey guys, thanks for the issue! I will check it out shortly!

@JasonShin JasonShin added the bug Something isn't working label Aug 2, 2019
@asvsfs
Copy link

asvsfs commented Jul 31, 2020

It seems to be solved @JasonShin

@danechung
Copy link

danechung commented Aug 4, 2020

I have the same problem.
I tried to handle using the above example, but some classes are not exported.

import { DecisionTreeClassifier } from './tree';
export { DecisionTreeClassifier };

then i'm fork and fix it
import { DecisionTreeClassifier, DecisionNode, Question, Leaf } from './tree';
export { DecisionTreeClassifier, DecisionNode, Question, Leaf };

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

5 participants