natural 6.10.2 → 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 (42) 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/tfidf/tfidf.js +118 -114
  35. package/lib/natural/trie/trie.js +161 -159
  36. package/lib/natural/util/directed_edge.js +49 -0
  37. package/lib/natural/util/edge_weighted_digraph.js +54 -74
  38. package/lib/natural/util/index.js +1 -0
  39. package/lib/natural/util/longest_path_tree.js +54 -52
  40. package/lib/natural/util/shortest_path_tree.js +56 -54
  41. package/lib/natural/util/topological.js +17 -15
  42. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  Classifier class that provides functionality for training and
3
3
  classification
4
- Copyright (C) 2017 Hugo W.L. ter Doest
4
+ Copyright (C) 2017, 2023 Hugo W.L. ter Doest
5
5
 
6
6
  Permission is hereby granted, free of charge, to any person obtaining a copy
7
7
  of this software and associated documentation files (the "Software"), to deal
@@ -32,96 +32,98 @@ const Sample = require('./Sample')
32
32
  const Scaler = require('./GISScaler')
33
33
  const FeatureSet = require('./FeatureSet')
34
34
 
35
- function Classifier (features, sample) {
36
- if (features) {
35
+ class Classifier {
36
+ constructor (features, sample) {
37
+ if (features) {
38
+ this.features = features
39
+ } else {
40
+ this.features = new FeatureSet()
41
+ }
37
42
  this.features = features
38
- } else {
39
- this.features = new FeatureSet()
43
+ if (sample) {
44
+ this.sample = sample
45
+ } else {
46
+ this.sample = new Sample()
47
+ }
40
48
  }
41
- this.features = features
42
- if (sample) {
43
- this.sample = sample
44
- } else {
45
- this.sample = new Sample()
49
+
50
+ // Loads a classifier from file.
51
+ // Caveat: feature functions are generated from the sample elements. You need
52
+ // to create your own specialisation of the Element class that can generate
53
+ // your own specific feature functions
54
+ load (filename, ElementClass, callback) {
55
+ fs.readFile(filename, 'utf8', function (err, data) {
56
+ if (!err) {
57
+ const classifierData = JSON.parse(data)
58
+ const sample = new Sample()
59
+ classifierData.sample.elements.forEach(function (elementData) {
60
+ const elt = new ElementClass(elementData.a, new Context(elementData.b.data))
61
+ sample.addElement(elt)
62
+ })
63
+ const featureSet = new FeatureSet()
64
+ sample.generateFeatures(featureSet)
65
+ const classifier = new Classifier(featureSet, sample)
66
+ callback(err, classifier)
67
+ } else {
68
+ if (callback) {
69
+ callback(err)
70
+ }
71
+ }
72
+ })
46
73
  }
47
- }
48
74
 
49
- // Loads a classifier from file.
50
- // Caveat: feature functions are generated from the sample elements. You need
51
- // to create your own specialisation of the Element class that can generate
52
- // your own specific feature functions
53
- Classifier.prototype.load = function (filename, ElementClass, callback) {
54
- fs.readFile(filename, 'utf8', function (err, data) {
55
- if (!err) {
56
- const classifierData = JSON.parse(data)
57
- const sample = new Sample()
58
- classifierData.sample.elements.forEach(function (elementData) {
59
- const elt = new ElementClass(elementData.a, new Context(elementData.b.data))
60
- sample.addElement(elt)
61
- })
62
- const featureSet = new FeatureSet()
63
- sample.generateFeatures(featureSet)
64
- const classifier = new Classifier(featureSet, sample)
65
- callback(err, classifier)
66
- } else {
75
+ save (filename, callback) {
76
+ const data = JSON.stringify(this, null, 2)
77
+ const classifier = this
78
+ fs.writeFile(filename, data, 'utf8', function (err) {
67
79
  if (callback) {
68
- callback(err)
80
+ console.log('Saved classifier to ' + filename)
81
+ callback(err, err ? null : classifier)
69
82
  }
70
- }
71
- })
72
- }
73
-
74
- Classifier.prototype.save = function (filename, callback) {
75
- const data = JSON.stringify(this, null, 2)
76
- const classifier = this
77
- fs.writeFile(filename, data, 'utf8', function (err) {
78
- if (callback) {
79
- console.log('Saved classifier to ' + filename)
80
- callback(err, err ? null : classifier)
81
- }
82
- })
83
- }
83
+ })
84
+ }
84
85
 
85
- Classifier.prototype.addElement = function (x) {
86
- this.sample.addElement(x)
87
- }
86
+ addElement (x) {
87
+ this.sample.addElement(x)
88
+ }
88
89
 
89
- Classifier.prototype.addDocument = function (context, classification, ElementClass) {
90
- Classifier.prototype.addElement(new ElementClass(classification, context))
91
- }
90
+ addDocument (context, classification, ElementClass) {
91
+ Classifier.prototype.addElement(new ElementClass(classification, context))
92
+ }
92
93
 
93
- Classifier.prototype.train = function (maxIterations, minImprovement, approxExpectation) {
94
- this.scaler = new Scaler(this.features, this.sample)
95
- this.p = this.scaler.run(maxIterations, minImprovement, approxExpectation)
96
- }
94
+ train (maxIterations, minImprovement, approxExpectation) {
95
+ this.scaler = new Scaler(this.features, this.sample)
96
+ this.p = this.scaler.run(maxIterations, minImprovement, approxExpectation)
97
+ }
97
98
 
98
- Classifier.prototype.getClassifications = function (b) {
99
- const scores = []
100
- const that = this
101
- this.sample.getClasses().forEach(function (a) {
102
- const x = new Element(a, b)
103
- scores.push({
104
- label: a,
105
- value: that.p.calculateAPriori(x)
99
+ getClassifications (b) {
100
+ const scores = []
101
+ const that = this
102
+ this.sample.getClasses().forEach(function (a) {
103
+ const x = new Element(a, b)
104
+ scores.push({
105
+ label: a,
106
+ value: that.p.calculateAPriori(x)
107
+ })
106
108
  })
107
- })
108
- return scores
109
- }
109
+ return scores
110
+ }
110
111
 
111
- Classifier.prototype.classify = function (b) {
112
- const scores = this.getClassifications(b)
113
- // Sort the scores in an array
114
- scores.sort(function (a, b) {
115
- return b.value - a.value
116
- })
117
- // Check if the classifier discriminates
118
- const min = scores[scores.length - 1].value
119
- const max = scores[0].value
120
- if (min === max) {
121
- return ''
122
- } else {
123
- // Return the highest scoring classes
124
- return scores[0].label
112
+ classify (b) {
113
+ const scores = this.getClassifications(b)
114
+ // Sort the scores in an array
115
+ scores.sort(function (a, b) {
116
+ return b.value - a.value
117
+ })
118
+ // Check if the classifier discriminates
119
+ const min = scores[scores.length - 1].value
120
+ const max = scores[0].value
121
+ if (min === max) {
122
+ return ''
123
+ } else {
124
+ // Return the highest scoring classes
125
+ return scores[0].label
126
+ }
125
127
  }
126
128
  }
127
129
 
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  Context class
3
- Copyright (C) 2017 Hugo W.L. ter Doest
3
+ Copyright (C) 2017, 2023 Hugo W.L. ter Doest
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -25,16 +25,18 @@ THE SOFTWARE.
25
25
 
26
26
  const stringify = require('safe-stable-stringify')
27
27
 
28
- function Context (data) {
29
- this.data = data
30
- }
28
+ class Context {
29
+ constructor (data) {
30
+ this.data = data
31
+ }
31
32
 
32
- // Create a predictable key string for looking up in a hash
33
- Context.prototype.toString = function () {
34
- if (!this.key) {
35
- this.key = stringify(this.data)
33
+ // Create a predictable key string for looking up in a hash
34
+ toString () {
35
+ if (!this.key) {
36
+ this.key = stringify(this.data)
37
+ }
38
+ return this.key
36
39
  }
37
- return this.key
38
40
  }
39
41
 
40
42
  module.exports = Context
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  Distribution class for probability distributions
3
- Copyright (C) 2017 Hugo W.L. ter Doest
3
+ Copyright (C) 2017, 2023 Hugo W.L. ter Doest
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -25,128 +25,130 @@ THE SOFTWARE.
25
25
 
26
26
  const Element = require('./Element')
27
27
 
28
- function Distribution (alpha, featureSet, sample) {
29
- this.alpha = alpha
30
- this.featureSet = featureSet
31
- this.sample = sample
32
- }
33
-
34
- // Returns the distribution as a string that can be stored for later usage
35
- Distribution.prototype.toString = function () {
28
+ class Distribution {
29
+ constructor (alpha, featureSet, sample) {
30
+ this.alpha = alpha
31
+ this.featureSet = featureSet
32
+ this.sample = sample
33
+ }
36
34
 
37
- }
35
+ // Returns the distribution as a string that can be stored for later usage
36
+ toString () {
38
37
 
39
- Distribution.prototype.weight = function (x) {
40
- let product = 1
41
- const that = this
38
+ }
42
39
 
43
- this.alpha.forEach(function (alphaj, j) {
44
- product *= Math.pow(alphaj, that.featureSet.getFeatures()[j].apply(x))
45
- })
46
- return product
47
- }
40
+ weight (x) {
41
+ let product = 1
42
+ const that = this
48
43
 
49
- Distribution.prototype.calculateAPriori = function (x) {
50
- if (!this.aPriorisBeforeNormalisation[x.toString()]) {
51
- this.aPriorisBeforeNormalisation[x.toString()] = this.weight(x)
44
+ this.alpha.forEach(function (alphaj, j) {
45
+ product *= Math.pow(alphaj, that.featureSet.getFeatures()[j].apply(x))
46
+ })
47
+ return product
52
48
  }
53
- return this.aPriorisBeforeNormalisation[x.toString()]// / this.aPrioriNormalisationConstant;
54
- }
55
49
 
56
- // Memoize a priori probabilities of sample elements
57
- Distribution.prototype.prepareWeights = function () {
58
- this.aPriorisBeforeNormalisation = {}
59
- this.aPrioriNormalisationConstant = 0
60
- let sum = 0
61
- const that = this
62
- this.sample.elements.forEach(function (x) {
63
- that.aPriorisBeforeNormalisation[x.toString()] = that.weight(x)
64
- sum += that.aPriorisBeforeNormalisation[x.toString()]
65
- })
66
- this.aPrioriNormalisationConstant = sum
67
- }
50
+ calculateAPriori (x) {
51
+ if (!this.aPriorisBeforeNormalisation[x.toString()]) {
52
+ this.aPriorisBeforeNormalisation[x.toString()] = this.weight(x)
53
+ }
54
+ return this.aPriorisBeforeNormalisation[x.toString()]// / this.aPrioriNormalisationConstant;
55
+ }
68
56
 
69
- Distribution.prototype.calculateAPosteriori = function (x) {
70
- if (!this.aPriorisBeforeNormalisation[x.toString()]) {
71
- this.aPriorisBeforeNormalisation[x.toString()] = this.weight(x)
57
+ // Memoize a priori probabilities of sample elements
58
+ prepareWeights () {
59
+ this.aPriorisBeforeNormalisation = {}
60
+ this.aPrioriNormalisationConstant = 0
61
+ let sum = 0
62
+ const that = this
63
+ this.sample.elements.forEach(function (x) {
64
+ that.aPriorisBeforeNormalisation[x.toString()] = that.weight(x)
65
+ sum += that.aPriorisBeforeNormalisation[x.toString()]
66
+ })
67
+ this.aPrioriNormalisationConstant = sum
72
68
  }
73
- if (!this.aPosterioriNormalisationConstants[x.b.toString()]) {
74
- this.aPosterioriNormalisationConstants[x.b.toString()] = this.aPosterioriNormalisation(x.b)
69
+
70
+ calculateAPosteriori (x) {
71
+ if (!this.aPriorisBeforeNormalisation[x.toString()]) {
72
+ this.aPriorisBeforeNormalisation[x.toString()] = this.weight(x)
73
+ }
74
+ if (!this.aPosterioriNormalisationConstants[x.b.toString()]) {
75
+ this.aPosterioriNormalisationConstants[x.b.toString()] = this.aPosterioriNormalisation(x.b)
76
+ }
77
+ return this.aPriorisBeforeNormalisation[x] / this.aPosterioriNormalisationConstants[x.b.toString()]
75
78
  }
76
- return this.aPriorisBeforeNormalisation[x] / this.aPosterioriNormalisationConstants[x.b.toString()]
77
- }
78
79
 
79
- Distribution.prototype.aPosterioriNormalisation = function (b) {
80
- let sum = 0
80
+ aPosterioriNormalisation (b) {
81
+ let sum = 0
81
82
 
82
- const that = this
83
- this.sample.getClasses().forEach(function (a) {
84
- sum += that.weight(new Element(a, b))
85
- })
83
+ const that = this
84
+ this.sample.getClasses().forEach(function (a) {
85
+ sum += that.weight(new Element(a, b))
86
+ })
86
87
 
87
- return (sum)
88
- }
88
+ return (sum)
89
+ }
89
90
 
90
- // Memoize a posteriori probabilities of sample elements
91
- Distribution.prototype.prepareAPosterioris = function () {
92
- this.aPosterioriNormalisationConstants = {}
93
-
94
- const contextSeen = {}
95
- const that = this
96
- this.sample.elements.forEach(function (sampleElement) {
97
- const context = sampleElement.b
98
- if (!contextSeen[context]) {
99
- contextSeen[context] = true
100
- that.aPosterioriNormalisationConstants[context] =
101
- that.aPosterioriNormalisation(context)
102
- }
103
- })
104
- }
91
+ // Memoize a posteriori probabilities of sample elements
92
+ prepareAPosterioris () {
93
+ this.aPosterioriNormalisationConstants = {}
94
+
95
+ const contextSeen = {}
96
+ const that = this
97
+ this.sample.elements.forEach(function (sampleElement) {
98
+ const context = sampleElement.b
99
+ if (!contextSeen[context]) {
100
+ contextSeen[context] = true
101
+ that.aPosterioriNormalisationConstants[context] =
102
+ that.aPosterioriNormalisation(context)
103
+ }
104
+ })
105
+ }
105
106
 
106
- // Memoize all probabilities of sample elements
107
- Distribution.prototype.prepare = function () {
108
- this.prepareWeights()
109
- // console.log("Weights prepared");
110
- this.prepareAPosterioris()
111
- }
107
+ // Memoize all probabilities of sample elements
108
+ prepare () {
109
+ this.prepareWeights()
110
+ // console.log("Weights prepared");
111
+ this.prepareAPosterioris()
112
+ }
112
113
 
113
- // Relative entropy between observered distribution and derived distribution
114
- Distribution.prototype.KullbackLieblerDistance = function () {
115
- let sum = 0
116
- const that = this
117
- this.sample.elements.forEach(function (x) {
118
- sum += that.sample.observedProbability(x) * Math.log(that.sample.observedProbability(x) / that.calculateAPriori(x))
119
- })
120
- return sum
121
- }
114
+ // Relative entropy between observered distribution and derived distribution
115
+ KullbackLieblerDistance () {
116
+ let sum = 0
117
+ const that = this
118
+ this.sample.elements.forEach(function (x) {
119
+ sum += that.sample.observedProbability(x) * Math.log(that.sample.observedProbability(x) / that.calculateAPriori(x))
120
+ })
121
+ return sum
122
+ }
122
123
 
123
- Distribution.prototype.logLikelihood = function () {
124
- let sum = 0
125
- const that = this
126
- this.sample.elements.forEach(function (x) {
127
- sum += that.sample.observedProbability(x) * Math.log(that.calculateAPriori(x))
128
- })
129
- return sum
130
- }
124
+ logLikelihood () {
125
+ let sum = 0
126
+ const that = this
127
+ this.sample.elements.forEach(function (x) {
128
+ sum += that.sample.observedProbability(x) * Math.log(that.calculateAPriori(x))
129
+ })
130
+ return sum
131
+ }
131
132
 
132
- Distribution.prototype.entropy = function () {
133
- let sum = 0
134
- const that = this
135
- this.sample.elements.forEach(function (x) {
136
- const p = that.calculateAPriori(x)
137
- sum += p * Math.log(p)
138
- })
139
- return sum
140
- }
133
+ entropy () {
134
+ let sum = 0
135
+ const that = this
136
+ this.sample.elements.forEach(function (x) {
137
+ const p = that.calculateAPriori(x)
138
+ sum += p * Math.log(p)
139
+ })
140
+ return sum
141
+ }
141
142
 
142
- Distribution.prototype.checkSum = function () {
143
- let sum = 0
144
- const that = this
145
- this.sample.elements.forEach(function (x) {
146
- sum += that.calculateAPriori(x)
147
- })
148
- // console.log("Distribution.checkSum is " + sum);
149
- return sum
143
+ checkSum () {
144
+ let sum = 0
145
+ const that = this
146
+ this.sample.elements.forEach(function (x) {
147
+ sum += that.calculateAPriori(x)
148
+ })
149
+ // console.log("Distribution.checkSum is " + sum);
150
+ return sum
151
+ }
150
152
  }
151
153
 
152
154
  module.exports = Distribution
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  Element class for elements in the event space
3
- Copyright (C) 2017 Hugo W.L. ter Doest
3
+ Copyright (C) 2017, 2023 Hugo W.L. ter Doest
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -23,17 +23,19 @@ THE SOFTWARE.
23
23
 
24
24
  'use strict'
25
25
 
26
- // a is class and b is context
27
- function Element (a, b) {
28
- this.a = a
29
- this.b = b
30
- }
26
+ class Element {
27
+ // a is class and b is context
28
+ constructor (a, b) {
29
+ this.a = a
30
+ this.b = b
31
+ }
31
32
 
32
- Element.prototype.toString = function () {
33
- if (!this.key) {
34
- this.key = this.a + this.b.toString()
33
+ toString () {
34
+ if (!this.key) {
35
+ this.key = this.a + this.b.toString()
36
+ }
37
+ return this.key
35
38
  }
36
- return this.key
37
39
  }
38
40
 
39
41
  module.exports = Element
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  Feature class for features that fire (or don't) on combinations of context
3
3
  and class
4
- Copyright (C) 2017 Hugo W.L. ter Doest
4
+ Copyright (C) 2017, 2023 Hugo W.L. ter Doest
5
5
 
6
6
  Permission is hereby granted, free of charge, to any person obtaining a copy
7
7
  of this software and associated documentation files (the "Software"), to deal
@@ -26,69 +26,71 @@ THE SOFTWARE.
26
26
 
27
27
  const Element = require('./Element')
28
28
 
29
- function Feature (f, name, parameters) {
30
- this.evaluate = f
31
- this.name = name
32
- this.parameters = parameters
29
+ class Feature {
30
+ constructor (f, name, parameters) {
31
+ this.evaluate = f
32
+ this.name = name
33
+ this.parameters = parameters
33
34
 
34
- let tmp = ''
35
- parameters.forEach(function (par) {
36
- tmp += par + '|'
37
- })
38
- this.parametersKey = tmp.substr(0, tmp.length - 1)
39
- }
35
+ let tmp = ''
36
+ parameters.forEach(function (par) {
37
+ tmp += par + '|'
38
+ })
39
+ this.parametersKey = tmp.substr(0, tmp.length - 1)
40
+ }
40
41
 
41
- Feature.prototype.apply = function (x) {
42
- return this.evaluate(x)
43
- }
42
+ apply (x) {
43
+ return this.evaluate(x)
44
+ }
44
45
 
45
- Feature.prototype.expectationApprox = function (p, sample) {
46
- const that = this
47
- let sum = 0
48
- const seen = {}
49
- const A = sample.getClasses()
50
- sample.elements.forEach(function (sampleElement) {
51
- const bi = sampleElement.b
46
+ expectationApprox (p, sample) {
47
+ const that = this
48
+ let sum = 0
49
+ const seen = {}
50
+ const A = sample.getClasses()
51
+ sample.elements.forEach(function (sampleElement) {
52
+ const bi = sampleElement.b
52
53
 
53
- if (!seen[bi.toString()]) {
54
- seen[bi.toString()] = true
54
+ if (!seen[bi.toString()]) {
55
+ seen[bi.toString()] = true
55
56
 
56
- A.forEach(function (a) {
57
- const x = new Element(a, bi)
58
- sum += sample.observedProbabilityOfContext(bi) * p.calculateAPosteriori(x) * that.apply(x)
59
- })
60
- }
61
- })
62
- return sum
63
- }
57
+ A.forEach(function (a) {
58
+ const x = new Element(a, bi)
59
+ sum += sample.observedProbabilityOfContext(bi) * p.calculateAPosteriori(x) * that.apply(x)
60
+ })
61
+ }
62
+ })
63
+ return sum
64
+ }
64
65
 
65
- // Direct calculation of expected value of this feature according to distribution p
66
- // In real-life applications with a lot of features this is not tractable
67
- Feature.prototype.expectation = function (p, A, B) {
68
- let sum = 0
69
- const that = this
70
- A.forEach(function (a) {
71
- B.forEach(function (b) {
72
- const x = new Element(a, b)
73
- sum += (p.calculateAPriori(x) * that.apply(x))
66
+ // Direct calculation of expected value of this feature according to distribution p
67
+ // In real-life applications with a lot of features this is not tractable
68
+ expectation (p, A, B) {
69
+ let sum = 0
70
+ const that = this
71
+ A.forEach(function (a) {
72
+ B.forEach(function (b) {
73
+ const x = new Element(a, b)
74
+ sum += (p.calculateAPriori(x) * that.apply(x))
75
+ })
74
76
  })
75
- })
76
- return sum
77
- }
77
+ return sum
78
+ }
78
79
 
79
- // Observed expectation of this feature in the sample
80
- Feature.prototype.observedExpectation = function (sample) {
81
- if (this.observedExpect) {
80
+ // Observed expectation of this feature in the sample
81
+ observedExpectation (sample) {
82
+ if (this.observedExpect) {
83
+ return this.observedExpect
84
+ }
85
+ const N = sample.size()
86
+ let sum = 0
87
+ const that = this
88
+ sample.elements.forEach(function (x) {
89
+ sum += that.apply(x)
90
+ })
91
+ this.observedExpect = sum / N
82
92
  return this.observedExpect
83
93
  }
84
- const N = sample.size()
85
- let sum = 0
86
- const that = this
87
- sample.elements.forEach(function (x) {
88
- sum += that.apply(x)
89
- })
90
- this.observedExpect = sum / N
91
- return this.observedExpect
92
94
  }
93
95
 
94
96
  module.exports = Feature