natural 6.10.0 → 6.10.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/.github/workflows/node.js.yml +1 -1
  2. package/.github/workflows/npm-publish.yml +4 -4
  3. package/lib/natural/brill_pos_tagger/lib/Brill_POS_Tagger.js +33 -31
  4. package/lib/natural/brill_pos_tagger/lib/Brill_POS_Tester.js +33 -35
  5. package/lib/natural/brill_pos_tagger/lib/Brill_POS_Trainer.js +326 -324
  6. package/lib/natural/brill_pos_tagger/lib/Corpus.js +140 -138
  7. package/lib/natural/brill_pos_tagger/lib/Lexicon.js +78 -76
  8. package/lib/natural/brill_pos_tagger/lib/Predicate.js +19 -17
  9. package/lib/natural/brill_pos_tagger/lib/RuleSet.js +58 -56
  10. package/lib/natural/brill_pos_tagger/lib/RuleTemplate.js +11 -9
  11. package/lib/natural/brill_pos_tagger/lib/Sentence.js +21 -20
  12. package/lib/natural/brill_pos_tagger/lib/TransformationRule.js +58 -58
  13. package/lib/natural/classifiers/bayes_classifier.js +24 -29
  14. package/lib/natural/classifiers/classifier.js +136 -121
  15. package/lib/natural/classifiers/logistic_regression_classifier.js +33 -37
  16. package/lib/natural/classifiers/maxent/Classifier.js +81 -79
  17. package/lib/natural/classifiers/maxent/Context.js +11 -9
  18. package/lib/natural/classifiers/maxent/Distribution.js +107 -105
  19. package/lib/natural/classifiers/maxent/Element.js +12 -10
  20. package/lib/natural/classifiers/maxent/Feature.js +56 -54
  21. package/lib/natural/classifiers/maxent/FeatureSet.js +40 -38
  22. package/lib/natural/classifiers/maxent/GISScaler.js +110 -109
  23. package/lib/natural/classifiers/maxent/POS/ME_Corpus.js +26 -31
  24. package/lib/natural/classifiers/maxent/POS/ME_Sentence.js +37 -42
  25. package/lib/natural/classifiers/maxent/POS/POS_Element.js +119 -124
  26. package/lib/natural/classifiers/maxent/Sample.js +96 -94
  27. package/lib/natural/classifiers/maxent/SimpleExample/SE_Element.js +14 -20
  28. package/lib/natural/inflectors/fr/count_inflector.js +1 -1
  29. package/lib/natural/inflectors/fr/noun_inflector.js +179 -196
  30. package/lib/natural/inflectors/ja/noun_inflector.js +67 -84
  31. package/lib/natural/inflectors/noun_inflector.js +124 -139
  32. package/lib/natural/inflectors/present_verb_inflector.js +34 -48
  33. package/lib/natural/inflectors/singular_plural_inflector.js +62 -61
  34. package/lib/natural/sentiment/SentimentAnalyzer.js +1 -1
  35. package/lib/natural/tfidf/tfidf.js +118 -114
  36. package/lib/natural/tokenizers/aggressive_tokenizer.js +11 -15
  37. package/lib/natural/tokenizers/aggressive_tokenizer_es.js +5 -9
  38. package/lib/natural/tokenizers/aggressive_tokenizer_fa.js +16 -20
  39. package/lib/natural/tokenizers/aggressive_tokenizer_fr.js +5 -9
  40. package/lib/natural/tokenizers/aggressive_tokenizer_hi.js +5 -10
  41. package/lib/natural/tokenizers/aggressive_tokenizer_id.js +13 -17
  42. package/lib/natural/tokenizers/aggressive_tokenizer_it.js +5 -9
  43. package/lib/natural/tokenizers/aggressive_tokenizer_nl.js +5 -9
  44. package/lib/natural/tokenizers/aggressive_tokenizer_no.js +7 -11
  45. package/lib/natural/tokenizers/aggressive_tokenizer_pl.js +12 -17
  46. package/lib/natural/tokenizers/aggressive_tokenizer_pt.js +9 -13
  47. package/lib/natural/tokenizers/aggressive_tokenizer_ru.js +12 -17
  48. package/lib/natural/tokenizers/aggressive_tokenizer_sv.js +8 -12
  49. package/lib/natural/tokenizers/aggressive_tokenizer_uk.js +35 -17
  50. package/lib/natural/tokenizers/aggressive_tokenizer_vi.js +5 -10
  51. package/lib/natural/tokenizers/regexp_tokenizer.js +50 -41
  52. package/lib/natural/tokenizers/sentence_tokenizer.js +15 -18
  53. package/lib/natural/tokenizers/sentence_tokenizer_parser.js +4 -9
  54. package/lib/natural/tokenizers/tokenizer.js +5 -24
  55. package/lib/natural/tokenizers/tokenizer_case.js +16 -31
  56. package/lib/natural/trie/trie.js +161 -159
  57. package/lib/natural/util/directed_edge.js +49 -0
  58. package/lib/natural/util/edge_weighted_digraph.js +54 -74
  59. package/lib/natural/util/index.js +1 -0
  60. package/lib/natural/util/longest_path_tree.js +54 -52
  61. package/lib/natural/util/shortest_path_tree.js +56 -54
  62. package/lib/natural/util/topological.js +17 -15
  63. package/package.json +2 -2
@@ -16,16 +16,18 @@
16
16
  along with this program. If not, see <http://www.gnu.org/licenses/>.
17
17
  */
18
18
 
19
- function RuleTemplate (templateName, metadata) {
20
- this.predicateName = templateName
21
- this.meta = metadata
22
- }
19
+ class RuleTemplate {
20
+ constructor (templateName, metadata) {
21
+ this.predicateName = templateName
22
+ this.meta = metadata
23
+ }
23
24
 
24
- RuleTemplate.prototype.windowFitsSite = function (sentence, i) {
25
- return ((i + this.meta.window[0] >= 0) &&
26
- (i + this.meta.window[0] < sentence.taggedWords.length) &&
27
- (i + this.meta.window[1] >= 0) &&
28
- (i + this.meta.window[1] < sentence.taggedWords.length))
25
+ windowFitsSite (sentence, i) {
26
+ return ((i + this.meta.window[0] >= 0) &&
27
+ (i + this.meta.window[0] < sentence.taggedWords.length) &&
28
+ (i + this.meta.window[1] >= 0) &&
29
+ (i + this.meta.window[1] < sentence.taggedWords.length))
30
+ }
29
31
  }
30
32
 
31
33
  module.exports = RuleTemplate
@@ -16,28 +16,29 @@
16
16
  along with this program. If not, see <http://www.gnu.org/licenses/>.
17
17
  */
18
18
 
19
- 'úse strict'
20
-
21
- function Sentence (data) {
22
- this.taggedWords = []
23
- if (data) {
24
- this.taggedWords = data
19
+ 'use strict'
20
+
21
+ class Sentence {
22
+ constructor (data) {
23
+ this.taggedWords = []
24
+ if (data) {
25
+ this.taggedWords = data
26
+ }
25
27
  }
26
- }
27
28
 
28
- Sentence.prototype.addTaggedWord = function (token, tag) {
29
- this.taggedWords.push({
30
- token: token,
31
- tag: tag
32
- })
33
- }
29
+ addTaggedWord (token, tag) {
30
+ this.taggedWords.push({
31
+ token: token,
32
+ tag: tag
33
+ })
34
+ }
34
35
 
35
- Sentence.prototype.clone = function () {
36
- const s = new Sentence()
37
- this.taggedWords.forEach(function (wordObject) {
38
- s.addTaggedWord(wordObject.token, wordObject.tag)
39
- })
40
- return s
36
+ clone () {
37
+ const s = new Sentence()
38
+ this.taggedWords.forEach(function (wordObject) {
39
+ s.addTaggedWord(wordObject.token, wordObject.tag)
40
+ })
41
+ return s
42
+ }
41
43
  }
42
-
43
44
  module.exports = Sentence
@@ -20,80 +20,80 @@
20
20
 
21
21
  const Predicate = require('./Predicate')
22
22
 
23
- // logger.setLevel('INFO');
24
-
25
23
  const categoryWildCard = '*'
26
24
 
27
- function TransformationRule (c1, c2, predicate, parameter1, parameter2) {
28
- this.literal = [c1, c2, predicate, parameter1, parameter2]
29
- this.predicate = new Predicate(predicate, parameter1, parameter2)
30
- this.oldCategory = c1
31
- this.newCategory = c2
32
- // These members are for the learning algorithm
33
- this.neutral = 0
34
- this.negative = 0
35
- this.positive = 0
36
- this.hasBeenSelectedAsHighRuleBefore = false
37
- }
25
+ class TransformationRule {
26
+ constructor (c1, c2, predicate, parameter1, parameter2) {
27
+ this.literal = [c1, c2, predicate, parameter1, parameter2]
28
+ this.predicate = new Predicate(predicate, parameter1, parameter2)
29
+ this.oldCategory = c1
30
+ this.newCategory = c2
31
+ // These members are for the learning algorithm
32
+ this.neutral = 0
33
+ this.negative = 0
34
+ this.positive = 0
35
+ this.hasBeenSelectedAsHighRuleBefore = false
36
+ }
38
37
 
39
- TransformationRule.prototype.key = function () {
40
- return (this.literal.toString())
41
- }
38
+ key () {
39
+ return (this.literal.toString())
40
+ }
42
41
 
43
- TransformationRule.prototype.apply = function (sentence, position) {
44
- if ((sentence.taggedWords[position].tag === this.oldCategory) ||
45
- (this.oldCategory === categoryWildCard)) {
46
- if (this.predicate.evaluate(sentence, position)) {
47
- sentence.taggedWords[position].tag = this.newCategory
42
+ apply (sentence, position) {
43
+ if ((sentence.taggedWords[position].tag === this.oldCategory) ||
44
+ (this.oldCategory === categoryWildCard)) {
45
+ if (this.predicate.evaluate(sentence, position)) {
46
+ sentence.taggedWords[position].tag = this.newCategory
47
+ }
48
48
  }
49
49
  }
50
- }
51
50
 
52
- //
53
- // Methods for processing sentences from a corpus that consist of an array of tokens
54
- //
51
+ //
52
+ // Methods for processing sentences from a corpus that consist of an array of tokens
53
+ //
55
54
 
56
- // Returns true if the rule applies at site. As a side effect it assigns the new
57
- // category to newTag
58
- TransformationRule.prototype.isApplicableAt = function (sentence, taggedSentence, i) {
59
- const applies = (taggedSentence.taggedWords[i].tag === this.oldCategory) &&
60
- this.predicate.evaluate(taggedSentence, i)
55
+ // Returns true if the rule applies at site. As a side effect it assigns the new
56
+ // category to newTag
57
+ isApplicableAt (sentence, taggedSentence, i) {
58
+ const applies = (taggedSentence.taggedWords[i].tag === this.oldCategory) &&
59
+ this.predicate.evaluate(taggedSentence, i)
61
60
 
62
- // Set newTag to let the trainer know what the new tag would become
63
- if (applies) {
64
- sentence.taggedWords[i].newTag = this.newCategory
61
+ // Set newTag to let the trainer know what the new tag would become
62
+ if (applies) {
63
+ sentence.taggedWords[i].newTag = this.newCategory
64
+ }
65
+ return (applies)
65
66
  }
66
- return (applies)
67
- }
68
67
 
69
- TransformationRule.prototype.prettyPrint = function () {
70
- let result = ''
71
- // Old category and new category
72
- result += this.oldCategory + ' ' + this.newCategory
73
- // Predicate name
74
- result += ' ' + this.predicate.name
75
- // Parameter 1 and 2
76
- if (this.predicate.parameter1) {
77
- result += ' ' + this.predicate.parameter1
78
- if (this.predicate.parameter2) {
79
- result += ' ' + this.predicate.parameter2
68
+ prettyPrint () {
69
+ let result = ''
70
+ // Old category and new category
71
+ result += this.oldCategory + ' ' + this.newCategory
72
+ // Predicate name
73
+ result += ' ' + this.predicate.name
74
+ // Parameter 1 and 2
75
+ if (this.predicate.parameter1) {
76
+ result += ' ' + this.predicate.parameter1
77
+ if (this.predicate.parameter2) {
78
+ result += ' ' + this.predicate.parameter2
79
+ }
80
80
  }
81
+ return result
81
82
  }
82
- return result
83
- }
84
83
 
85
- // Applies the rule the given location (if it applies)
86
- TransformationRule.prototype.applyAt = function (sentence, i) {
87
- const taggedSentence = sentence.clone()
84
+ // Applies the rule the given location (if it applies)
85
+ applyAt (sentence, i) {
86
+ const taggedSentence = sentence.clone()
88
87
 
89
- this.apply(sentence, i)
90
- // Assign the new tag to the corpus site
91
- sentence.taggedWords[i].testTag = taggedSentence.taggedWords[i].tag
92
- }
88
+ this.apply(sentence, i)
89
+ // Assign the new tag to the corpus site
90
+ sentence.taggedWords[i].testTag = taggedSentence.taggedWords[i].tag
91
+ }
93
92
 
94
- // Calculate the net score of this rule
95
- TransformationRule.prototype.score = function () {
96
- return (this.positive - this.negative)
93
+ // Calculate the net score of this rule
94
+ score () {
95
+ return (this.positive - this.negative)
96
+ }
97
97
  }
98
98
 
99
99
  module.exports = TransformationRule
@@ -22,41 +22,36 @@ THE SOFTWARE.
22
22
 
23
23
  'use strict'
24
24
 
25
- const util = require('util')
26
25
  const Classifier = require('./classifier')
27
26
  const ApparatusBayesClassifier = require('apparatus').BayesClassifier
28
27
 
29
- const BayesClassifier = function (stemmer, smoothing) {
30
- let abc = new ApparatusBayesClassifier()
31
- if (smoothing && isFinite(smoothing)) {
32
- abc = new ApparatusBayesClassifier(smoothing)
28
+ class BayesClassifier extends Classifier {
29
+ constructor (stemmer, smoothing) {
30
+ let abc = new ApparatusBayesClassifier()
31
+ if (smoothing && isFinite(smoothing)) {
32
+ abc = new ApparatusBayesClassifier(smoothing)
33
+ }
34
+ super(abc, stemmer)
33
35
  }
34
- Classifier.call(this, abc, stemmer)
35
- }
36
-
37
- util.inherits(BayesClassifier, Classifier)
38
36
 
39
- function restore (classifier, stemmer) {
40
- classifier = Classifier.restore(classifier, stemmer)
41
- // __proto__ is deprecated
42
- // classifier.__proto__ = BayesClassifier.prototype
43
- Object.setPrototypeOf(classifier, BayesClassifier.prototype)
44
- classifier.classifier = ApparatusBayesClassifier.restore(classifier.classifier)
45
-
46
- return classifier
47
- }
37
+ static restore (classifier, stemmer) {
38
+ classifier = Classifier.restore(classifier, stemmer)
39
+ // __proto__ is deprecated
40
+ // classifier.__proto__ = BayesClassifier.prototype
41
+ Object.setPrototypeOf(classifier, BayesClassifier.prototype)
42
+ classifier.classifier = ApparatusBayesClassifier.restore(classifier.classifier)
43
+ return classifier
44
+ }
48
45
 
49
- function load (filename, stemmer, callback) {
50
- Classifier.load(filename, function (err, classifier) {
51
- if (err) {
52
- return callback(err)
53
- } else {
54
- callback(err, restore(classifier, stemmer))
55
- }
56
- })
46
+ load (filename, stemmer, callback) {
47
+ Classifier.load(filename, function (err, classifier) {
48
+ if (err) {
49
+ return callback(err)
50
+ } else {
51
+ callback(err, this.restore(classifier, stemmer))
52
+ }
53
+ })
54
+ }
57
55
  }
58
56
 
59
- BayesClassifier.restore = restore
60
- BayesClassifier.load = load
61
-
62
57
  module.exports = BayesClassifier
@@ -22,164 +22,179 @@ THE SOFTWARE.
22
22
 
23
23
  'use strict'
24
24
 
25
- const PorterStemmer = require('../stemmers/porter_stemmer')
26
- const events = require('events')
25
+ const EventEmitter = require('events')
27
26
 
27
+ const PorterStemmer = require('../stemmers/porter_stemmer')
28
28
  const parallelTrainer = require('./classifier_train_parallel')
29
29
 
30
- const Classifier = function (classifier, stemmer) {
31
- this.classifier = classifier
32
- this.docs = []
33
- this.features = {}
34
- this.stemmer = stemmer || PorterStemmer
35
- this.lastAdded = 0
36
- this.events = new events.EventEmitter()
37
- }
30
+ class Classifier extends EventEmitter {
31
+ constructor (classifier, stemmer) {
32
+ super()
33
+ this.classifier = classifier
34
+ this.docs = []
35
+ this.features = {}
36
+ this.stemmer = stemmer || PorterStemmer
37
+ this.lastAdded = 0
38
+ }
38
39
 
39
- function addDocument (text, classification) {
40
- // Ignore further processing if classification is undefined
41
- if (typeof classification === 'undefined') return
40
+ addDocument (text, classification) {
41
+ // Ignore further processing if classification is undefined
42
+ if (typeof classification === 'undefined') return
42
43
 
43
- // If classification is type of string then make sure it's dosen't have blank space at both end
44
- if (typeof classification === 'string') {
45
- classification = classification.trim()
46
- }
44
+ // If classification is type of string then make sure it's dosen't have blank space at both end
45
+ if (typeof classification === 'string') {
46
+ classification = classification.trim()
47
+ }
47
48
 
48
- if (typeof text === 'string') { text = this.stemmer.tokenizeAndStem(text, this.keepStops) }
49
+ if (typeof text === 'string') { text = this.stemmer.tokenizeAndStem(text, this.keepStops) }
49
50
 
50
- if (text.length === 0) {
51
- // ignore empty documents
52
- return
53
- }
51
+ if (text.length === 0) {
52
+ // ignore empty documents
53
+ return
54
+ }
54
55
 
55
- this.docs.push({
56
- label: classification,
57
- text: text
58
- })
56
+ this.docs.push({
57
+ label: classification,
58
+ text: text
59
+ })
59
60
 
60
- for (let i = 0; i < text.length; i++) {
61
- const token = text[i]
62
- this.features[token] = (this.features[token] || 0) + 1
61
+ for (let i = 0; i < text.length; i++) {
62
+ const token = text[i]
63
+ this.features[token] = (this.features[token] || 0) + 1
64
+ }
63
65
  }
64
- }
65
66
 
66
- function removeDocument (text, classification) {
67
- const docs = this.docs
68
- let doc
69
- let pos
67
+ removeDocument (text, classification) {
68
+ const docs = this.docs
69
+ let doc
70
+ let pos
70
71
 
71
- if (typeof text === 'string') {
72
- text = this.stemmer.tokenizeAndStem(text, this.keepStops)
73
- }
72
+ if (typeof text === 'string') {
73
+ text = this.stemmer.tokenizeAndStem(text, this.keepStops)
74
+ }
74
75
 
75
- for (let i = 0, ii = docs.length; i < ii; i++) {
76
- doc = docs[i]
77
- if (doc.text.join(' ') === text.join(' ') &&
78
- doc.label === classification) {
79
- pos = i
76
+ for (let i = 0, ii = docs.length; i < ii; i++) {
77
+ doc = docs[i]
78
+ if (doc.text.join(' ') === text.join(' ') &&
79
+ doc.label === classification) {
80
+ pos = i
81
+ }
80
82
  }
81
- }
82
83
 
83
- // Remove if there's a match
84
- if (!isNaN(pos)) {
85
- this.docs.splice(pos, 1)
84
+ // Remove if there's a match
85
+ if (!isNaN(pos)) {
86
+ this.docs.splice(pos, 1)
86
87
 
87
- for (let i = 0, ii = text.length; i < ii; i++) {
88
- delete this.features[text[i]]
88
+ for (let i = 0, ii = text.length; i < ii; i++) {
89
+ delete this.features[text[i]]
90
+ }
89
91
  }
90
92
  }
91
- }
92
93
 
93
- function textToFeatures (observation) {
94
- const features = []
94
+ textToFeatures (observation) {
95
+ const features = []
95
96
 
96
- if (typeof observation === 'string') { observation = this.stemmer.tokenizeAndStem(observation, this.keepStops) }
97
+ if (typeof observation === 'string') { observation = this.stemmer.tokenizeAndStem(observation, this.keepStops) }
98
+
99
+ for (const feature in this.features) {
100
+ if (observation.indexOf(feature) > -1) {
101
+ features.push(1)
102
+ } else {
103
+ features.push(0)
104
+ }
105
+ }
97
106
 
98
- for (const feature in this.features) {
99
- if (observation.indexOf(feature) > -1) { features.push(1) } else { features.push(0) }
107
+ return features
100
108
  }
101
109
 
102
- return features
103
- }
110
+ train () {
111
+ const totalDocs = this.docs.length
112
+ for (let i = this.lastAdded; i < totalDocs; i++) {
113
+ const features = this.textToFeatures(this.docs[i].text)
114
+ this.classifier.addExample(features, this.docs[i].label)
115
+ this.emit('trainedWithDocument', { index: i, total: totalDocs, doc: this.docs[i] })
116
+ this.lastAdded++
117
+ }
118
+ this.emit('doneTraining', true)
119
+ this.classifier.train()
120
+ }
104
121
 
105
- function train () {
106
- const totalDocs = this.docs.length
107
- for (let i = this.lastAdded; i < totalDocs; i++) {
108
- const features = this.textToFeatures(this.docs[i].text)
109
- this.classifier.addExample(features, this.docs[i].label)
110
- this.events.emit('trainedWithDocument', { index: i, total: totalDocs, doc: this.docs[i] })
111
- this.lastAdded++
122
+ retrain () {
123
+ this.classifier = new (this.classifier.constructor)()
124
+ this.lastAdded = 0
125
+ this.train()
112
126
  }
113
- this.events.emit('doneTraining', true)
114
- this.classifier.train()
115
- }
116
127
 
117
- function retrain () {
118
- this.classifier = new (this.classifier.constructor)()
119
- this.lastAdded = 0
120
- this.train()
121
- }
128
+ getClassifications (observation) {
129
+ return this.classifier.getClassifications(this.textToFeatures(observation))
130
+ }
122
131
 
123
- function getClassifications (observation) {
124
- return this.classifier.getClassifications(this.textToFeatures(observation))
125
- }
132
+ classify (observation) {
133
+ return this.classifier.classify(this.textToFeatures(observation))
134
+ }
126
135
 
127
- function classify (observation) {
128
- return this.classifier.classify(this.textToFeatures(observation))
129
- }
136
+ static restore (classifier, stemmer) {
137
+ classifier.stemmer = stemmer || PorterStemmer
138
+ return classifier
139
+ }
130
140
 
131
- function restore (classifier, stemmer) {
132
- classifier.stemmer = stemmer || PorterStemmer
133
- classifier.events = new events.EventEmitter()
134
- return classifier
135
- }
141
+ save (filename, callback) {
142
+ const data = JSON.stringify(this)
143
+ const fs = require('fs')
144
+ const classifier = this
145
+ fs.writeFile(filename, data, 'utf8', function (err) {
146
+ if (callback) {
147
+ callback(err, err ? null : classifier)
148
+ }
149
+ })
150
+ }
136
151
 
137
- function save (filename, callback) {
138
- const data = JSON.stringify(this)
139
- const fs = require('fs')
140
- const classifier = this
141
- fs.writeFile(filename, data, 'utf8', function (err) {
142
- if (callback) {
143
- callback(err, err ? null : classifier)
144
- }
145
- })
146
- }
152
+ static load (filename, callback) {
153
+ const fs = require('fs')
147
154
 
148
- function load (filename, callback) {
149
- const fs = require('fs')
155
+ if (!callback) {
156
+ return
157
+ }
158
+ fs.readFile(filename, 'utf8', function (err, data) {
159
+ if (err) {
160
+ callback(err, null)
161
+ } else {
162
+ const classifier = JSON.parse(data)
163
+ callback(err, classifier)
164
+ }
165
+ })
166
+ }
150
167
 
151
- if (!callback) {
152
- return
168
+ setOptions (options) {
169
+ this.keepStops = !!(options.keepStops)
153
170
  }
154
- fs.readFile(filename, 'utf8', function (err, data) {
155
- if (err) {
156
- callback(err, null)
171
+
172
+ ClassifiertrainParallel (numThreads, callback) {
173
+ if (parallelTrainer.Threads) {
174
+ return parallelTrainer.trainParallel(numThreads, callback)
157
175
  } else {
158
- const classifier = JSON.parse(data)
159
- callback(err, classifier)
176
+ this.emit('No threads available')
177
+ return this.train()
160
178
  }
161
- })
162
- }
179
+ }
163
180
 
164
- function setOptions (options) {
165
- this.keepStops = !!(options.keepStops)
166
- }
181
+ trainParallelBatches (options) {
182
+ if (parallelTrainer.Threads) {
183
+ return parallelTrainer.trainParallelBatches(options)
184
+ } else {
185
+ this.emit('No threads available')
186
+ return this.train()
187
+ }
188
+ }
167
189
 
168
- Classifier.prototype.addDocument = addDocument
169
- Classifier.prototype.removeDocument = removeDocument
170
- Classifier.prototype.train = train
171
- if (parallelTrainer.Threads) {
172
- Classifier.prototype.trainParallel = parallelTrainer.trainParallel
173
- Classifier.prototype.trainParallelBatches = parallelTrainer.trainParallelBatches
174
- Classifier.prototype.retrainParallel = parallelTrainer.retrainParallel
190
+ retrainParallel (numThreads, callback) {
191
+ if (parallelTrainer.Threads) {
192
+ return parallelTrainer.trainParallel(numThreads, callback)
193
+ } else {
194
+ this.emit('No threads available')
195
+ return this.retrain()
196
+ }
197
+ }
175
198
  }
176
- Classifier.prototype.retrain = retrain
177
- Classifier.prototype.classify = classify
178
- Classifier.prototype.textToFeatures = textToFeatures
179
- Classifier.prototype.save = save
180
- Classifier.prototype.getClassifications = getClassifications
181
- Classifier.prototype.setOptions = setOptions
182
- Classifier.restore = restore
183
- Classifier.load = load
184
199
 
185
200
  module.exports = Classifier
@@ -22,46 +22,42 @@ THE SOFTWARE.
22
22
 
23
23
  'use strict'
24
24
 
25
- const util = require('util')
26
25
  const Classifier = require('./classifier')
27
26
  const ApparatusLogisticRegressionClassifier = require('apparatus').LogisticRegressionClassifier
28
27
 
29
- const LogisticRegressionClassifier = function (stemmer) {
30
- Classifier.call(this, new ApparatusLogisticRegressionClassifier(), stemmer)
28
+ class LogisticRegressionClassifier extends Classifier {
29
+ constructor (stemmer) {
30
+ const abc = new ApparatusLogisticRegressionClassifier()
31
+ super(abc, stemmer)
32
+ }
33
+
34
+ static restore (classifier, stemmer) {
35
+ classifier = Classifier.restore(classifier, stemmer)
36
+ // Using ___proto__ is deprecated
37
+ // classifier.__proto__ = LogisticRegressionClassifier.prototype
38
+ Object.setPrototypeOf(classifier, LogisticRegressionClassifier.prototype)
39
+ classifier.classifier = ApparatusLogisticRegressionClassifier.restore(classifier.classifier)
40
+
41
+ return classifier
42
+ }
43
+
44
+ static load (filename, stemmer, callback) {
45
+ Classifier.load(filename, function (err, classifier) {
46
+ if (err) {
47
+ callback(err)
48
+ } else {
49
+ callback(err, this.restore(classifier, stemmer))
50
+ }
51
+ })
52
+ }
53
+
54
+ train () {
55
+ // we need to reset the training state because logistic regression
56
+ // needs its matricies to have their widths synced, etc.
57
+ this.lastAdded = 0
58
+ this.classifier = new ApparatusLogisticRegressionClassifier()
59
+ Classifier.prototype.train.call(this)
60
+ }
31
61
  }
32
62
 
33
- util.inherits(LogisticRegressionClassifier, Classifier)
34
-
35
- function restore (classifier, stemmer) {
36
- classifier = Classifier.restore(classifier, stemmer)
37
- // Using ___proto__ is deprecated
38
- // classifier.__proto__ = LogisticRegressionClassifier.prototype
39
- Object.setPrototypeOf(classifier, LogisticRegressionClassifier.prototype)
40
- classifier.classifier = ApparatusLogisticRegressionClassifier.restore(classifier.classifier)
41
-
42
- return classifier
43
- }
44
-
45
- function load (filename, stemmer, callback) {
46
- Classifier.load(filename, function (err, classifier) {
47
- if (err) {
48
- callback(err)
49
- } else {
50
- callback(err, restore(classifier, stemmer))
51
- }
52
- })
53
- }
54
-
55
- function train () {
56
- // we need to reset the traning state because logistic regression
57
- // needs its matricies to have their widths synced, etc.
58
- this.lastAdded = 0
59
- this.classifier = new ApparatusLogisticRegressionClassifier()
60
- Classifier.prototype.train.call(this)
61
- }
62
-
63
- LogisticRegressionClassifier.prototype.train = train
64
- LogisticRegressionClassifier.restore = restore
65
- LogisticRegressionClassifier.load = load
66
-
67
63
  module.exports = LogisticRegressionClassifier