| 2996 | } |
| 2997 | } |
| 2998 | LoadModelFromString(model_str) { |
| 2999 | const lines = model_str.split('\n'); |
| 3000 | const signature = lines.shift() || '?'; |
| 3001 | if (signature.trim() !== 'tree') { |
| 3002 | throw new python.Error(`Invalid signature '${signature.trim()}'.`); |
| 3003 | } |
| 3004 | // GBDT::LoadModelFromString() in https://github.com/microsoft/LightGBM/blob/master/src/boosting/gbdt_model_text.cpp |
| 3005 | const key_vals = new Map(); |
| 3006 | while (lines.length > 0 && !lines[0].startsWith('Tree=')) { |
| 3007 | const cur_line = lines.shift().trim(); |
| 3008 | if (cur_line.length > 0) { |
| 3009 | const strs = cur_line.split('='); |
| 3010 | if (strs.length === 1) { |
| 3011 | key_vals.set(strs[0], ''); |
| 3012 | } else if (strs.length === 2) { |
| 3013 | key_vals.set(strs[0], strs[1]); |
| 3014 | } else if (strs.length > 2) { |
| 3015 | if (strs[0] === "feature_names") { |
| 3016 | key_vals.set(strs[0], cur_line.substring("feature_names=".length)); |
| 3017 | } else if (strs[0] === 'monotone_constraints') { |
| 3018 | key_vals.set(strs[0], cur_line.substring('monotone_constraints='.length)); |
| 3019 | } else { |
| 3020 | throw new python.Error(`Wrong line: ${cur_line.substring(0, Math.min(128, cur_line.length))}`); |
| 3021 | } |
| 3022 | } |
| 3023 | } |
| 3024 | } |
| 3025 | const atoi = (key, value) => { |
| 3026 | if (key_vals.has(key)) { |
| 3027 | return parseInt(key_vals.get(key), 10); |
| 3028 | } |
| 3029 | if (value !== undefined) { |
| 3030 | return value; |
| 3031 | } |
| 3032 | throw new python.Error(`Model file does not specify ${key}.`); |
| 3033 | }; |
| 3034 | const list = (key, size) => { |
| 3035 | if (key_vals.has(key)) { |
| 3036 | const value = key_vals.get(key).split(' '); |
| 3037 | if (value.length !== size) { |
| 3038 | throw new python.Error(`Wrong size of ${key}.`); |
| 3039 | } |
| 3040 | return value; |
| 3041 | } |
| 3042 | throw new python.Error(`Model file does not contain ${key}.`); |
| 3043 | }; |
| 3044 | this.version = key_vals.get('version') || ''; |
| 3045 | this.num_class = atoi('num_class'); |
| 3046 | this.num_tree_per_iteration = atoi('num_tree_per_iteration', this.num_class); |
| 3047 | this.label_index = atoi('label_index'); |
| 3048 | this.max_feature_idx = atoi('max_feature_idx'); |
| 3049 | if (key_vals.has('average_output')) { |
| 3050 | this.average_output = true; |
| 3051 | } |
| 3052 | this.feature_names = list('feature_names', this.max_feature_idx + 1); |
| 3053 | this.feature_infos = list('feature_infos', this.max_feature_idx + 1); |
| 3054 | if (key_vals.has('monotone_constraints')) { |
| 3055 | this.monotone_constraints = list('monotone_constraints', this.max_feature_idx + 1); |