natural 0.5.4 → 0.6.1

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 (82) hide show
  1. package/.dockerignore +2 -0
  2. package/.npmignore +1 -0
  3. package/.travis.yml +1 -1
  4. package/README.md +412 -89
  5. package/bayes_classifier.json +1 -1
  6. package/classifier.json +418 -0
  7. package/data/kata-dasar.txt +29933 -0
  8. package/lib/natural/brill_pos_tagger/lib/Brill_POS_Tagger.js +8 -9
  9. package/lib/natural/brill_pos_tagger/lib/Brill_POS_Tester.js +5 -5
  10. package/lib/natural/brill_pos_tagger/lib/Brill_POS_Trainer.js +10 -6
  11. package/lib/natural/brill_pos_tagger/lib/Corpus.js +21 -16
  12. package/lib/natural/brill_pos_tagger/lib/Lexicon.js +22 -13
  13. package/lib/natural/brill_pos_tagger/lib/Predicate.js +2 -2
  14. package/lib/natural/brill_pos_tagger/lib/RuleTemplate.js +2 -2
  15. package/lib/natural/brill_pos_tagger/lib/RuleTemplates.js +132 -146
  16. package/lib/natural/brill_pos_tagger/lib/Sentence.js +41 -0
  17. package/lib/natural/brill_pos_tagger/lib/TF_Parser.js +83 -76
  18. package/lib/natural/brill_pos_tagger/lib/TF_Parser.pegjs +19 -4
  19. package/lib/natural/brill_pos_tagger/lib/TransformationRule.js +10 -11
  20. package/lib/natural/classifiers/classifier.js +15 -8
  21. package/lib/natural/classifiers/maxent/Classifier.js +125 -0
  22. package/lib/natural/classifiers/maxent/Context.js +33 -0
  23. package/lib/natural/classifiers/maxent/Distribution.js +145 -0
  24. package/lib/natural/classifiers/maxent/Element.js +34 -0
  25. package/lib/natural/classifiers/maxent/Feature.js +88 -0
  26. package/lib/natural/classifiers/maxent/FeatureSet.js +67 -0
  27. package/lib/natural/classifiers/maxent/GISScaler.js +148 -0
  28. package/lib/natural/classifiers/maxent/POS/ME_Corpus.js +56 -0
  29. package/lib/natural/classifiers/maxent/POS/ME_Sentence.js +73 -0
  30. package/lib/natural/classifiers/maxent/POS/POS_Element.js +172 -0
  31. package/lib/natural/classifiers/maxent/Sample.js +141 -0
  32. package/lib/natural/classifiers/maxent/SimpleExample/SE_Element.js +49 -0
  33. package/lib/natural/distance/hamming_distance.js +52 -0
  34. package/lib/natural/distance/jaro-winkler_distance.js +16 -6
  35. package/lib/natural/distance/levenshtein_distance.js +164 -11
  36. package/lib/natural/index.js +26 -5
  37. package/lib/natural/inflectors/noun_inflector.js +15 -13
  38. package/lib/natural/ngrams/ngrams.js +83 -25
  39. package/lib/natural/normalizers/normalizer_sv.js +41 -0
  40. package/lib/natural/sentiment/Basque/senticon_eu.json +21557 -0
  41. package/lib/natural/sentiment/Catalan/senticon_ca.json +36352 -0
  42. package/lib/natural/sentiment/Dutch/negations_du.json +3 -0
  43. package/lib/natural/sentiment/Dutch/pattern-sentiment-nl.json +39650 -0
  44. package/lib/natural/sentiment/English/negations_en.json +3 -0
  45. package/lib/natural/sentiment/English/pattern-sentiment-en.json +16024 -0
  46. package/lib/natural/sentiment/English/senticon_en.json +124197 -0
  47. package/lib/natural/sentiment/French/pattern-sentiment-fr.json +40906 -0
  48. package/lib/natural/sentiment/Galician/senticon_gl.json +24427 -0
  49. package/lib/natural/sentiment/Italian/pattern-sentiment-it.json +24522 -0
  50. package/lib/natural/sentiment/SentimentAnalyzer.js +116 -0
  51. package/lib/natural/sentiment/Spanish/afinnShortSortedSpanish.json +1655 -0
  52. package/lib/natural/sentiment/Spanish/negations_es.json +3 -0
  53. package/lib/natural/sentiment/Spanish/senticon_es.json +56722 -0
  54. package/lib/natural/sentiment/tools/README.md +31 -0
  55. package/lib/natural/sentiment/tools/XmlParser4PatternData.js +31 -0
  56. package/lib/natural/sentiment/tools/sentimentXmlParser.js +30 -0
  57. package/lib/natural/stemmers/indonesian/base_stemmer_id.js +86 -0
  58. package/lib/natural/stemmers/indonesian/prefix_rules.js +1027 -0
  59. package/lib/natural/stemmers/indonesian/removal.js +49 -0
  60. package/lib/natural/stemmers/indonesian/stemmer_id.js +307 -0
  61. package/lib/natural/stemmers/indonesian/suffix_rules.js +75 -0
  62. package/lib/natural/stemmers/porter_stemmer_es.js +265 -199
  63. package/lib/natural/stemmers/porter_stemmer_fr.js +1 -1
  64. package/lib/natural/stemmers/porter_stemmer_nl.js +362 -0
  65. package/lib/natural/stemmers/porter_stemmer_sv.js +99 -0
  66. package/lib/natural/stemmers/stemmer_es.js +18 -12
  67. package/lib/natural/stemmers/stemmer_nl.js +64 -0
  68. package/lib/natural/stemmers/stemmer_sv.js +61 -0
  69. package/lib/natural/tfidf/tfidf.js +27 -4
  70. package/lib/natural/tokenizers/aggressive_tokenizer_id.js +44 -0
  71. package/lib/natural/tokenizers/aggressive_tokenizer_sv.js +40 -0
  72. package/lib/natural/tokenizers/aggressive_tokenizer_vi.js +37 -0
  73. package/lib/natural/tokenizers/orthography_matchers.js +33 -0
  74. package/lib/natural/tokenizers/regexp_tokenizer.js +23 -3
  75. package/lib/natural/tokenizers/sentence_tokenizer.js +1 -1
  76. package/lib/natural/util/stopwords_id.js +119 -0
  77. package/lib/natural/util/stopwords_no.js +1 -1
  78. package/lib/natural/util/stopwords_sv.js +70 -0
  79. package/lib/natural/wordnet/wordnet_file.js +7 -1
  80. package/lr_classifier.json +1 -1
  81. package/package-lock.json +378 -0
  82. package/package.json +29 -21
@@ -0,0 +1,33 @@
1
+ /*
2
+ Context class
3
+ Copyright (C) 2017 Hugo W.L. ter Doest
4
+
5
+ This program is free software: you can redistribute it and/or modify
6
+ it under the terms of the GNU General Public License as published by
7
+ the Free Software Foundation, either version 3 of the License, or
8
+ (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU General Public License for more details.
14
+
15
+ You should have received a copy of the GNU General Public License
16
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+ var stringify = require('json-stable-stringify');
20
+
21
+ function Context(data) {
22
+ this.data = data;
23
+ }
24
+
25
+ // Create a predictable key string for looking up in a hash
26
+ Context.prototype.toString = function() {
27
+ if (!this.key) {
28
+ this.key = stringify(this.data);
29
+ }
30
+ return this.key;
31
+ };
32
+
33
+ module.exports = Context;
@@ -0,0 +1,145 @@
1
+ /*
2
+ Distribution class for probability distributions
3
+ Copyright (C) 2017 Hugo W.L. ter Doest
4
+
5
+ This program is free software: you can redistribute it and/or modify
6
+ it under the terms of the GNU General Public License as published by
7
+ the Free Software Foundation, either version 3 of the License, or
8
+ (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU General Public License for more details.
14
+
15
+ You should have received a copy of the GNU General Public License
16
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+ var Element = require('./Element');
20
+
21
+ function Distribution(alpha, featureSet, sample) {
22
+ this.alpha = alpha;
23
+ this.featureSet = featureSet;
24
+ this.sample = sample;
25
+ }
26
+
27
+ // Returns the distribution as a string that can be stored for later usage
28
+ Distribution.prototype.toString = function() {
29
+
30
+ }
31
+
32
+ Distribution.prototype.weight = function(x) {
33
+ var product = 1;
34
+ var that = this;
35
+
36
+ this.alpha.forEach(function(alpha_j, j) {
37
+ product *= Math.pow(alpha_j, that.featureSet.getFeatures()[j].apply(x));
38
+ });
39
+ return product;
40
+ };
41
+
42
+ Distribution.prototype.calculateAPriori = function(x) {
43
+ if (!this.aPriorisBeforeNormalisation[x.toString()]) {
44
+ this.aPriorisBeforeNormalisation[x.toString()] = this.weight(x);
45
+ }
46
+ return this.aPriorisBeforeNormalisation[x.toString()];// / this.aPrioriNormalisationConstant;
47
+ };
48
+
49
+ // Memoize a priori probabilities of sample elements
50
+ Distribution.prototype.prepareWeights = function() {
51
+ this.aPriorisBeforeNormalisation = {};
52
+ this.aPrioriNormalisationConstant = 0;
53
+ var sum = 0;
54
+ var that = this;
55
+ this.sample.elements.forEach(function(x) {
56
+ that.aPriorisBeforeNormalisation[x.toString()] = that.weight(x);
57
+ sum += that.aPriorisBeforeNormalisation[x.toString()];
58
+ });
59
+ this.aPrioriNormalisationConstant = sum;
60
+ };
61
+
62
+ Distribution.prototype.calculateAPosteriori = function(x) {
63
+ if (!this.aPriorisBeforeNormalisation[x.toString()]) {
64
+ this.aPriorisBeforeNormalisation[x.toString()] = this.weight(x);
65
+ }
66
+ if (!this.aPosterioriNormalisationConstants[x.b.toString()]) {
67
+ this.aPosterioriNormalisationConstants[x.b.toString()] = this.aPosterioriNormalisation(x.b);
68
+ }
69
+ return this.aPriorisBeforeNormalisation[x] / this.aPosterioriNormalisationConstants[x.b.toString()];
70
+ };
71
+
72
+ Distribution.prototype.aPosterioriNormalisation = function(b) {
73
+ var sum = 0;
74
+
75
+ var that = this;
76
+ this.sample.getClasses().forEach(function(a) {
77
+ sum += that.weight(new Element(a, b));
78
+ });
79
+
80
+ return(sum);
81
+ };
82
+
83
+ // Memoize a posteriori probabilities of sample elements
84
+ Distribution.prototype.prepareAPosterioris = function() {
85
+ this.aPosterioriNormalisationConstants = {};
86
+
87
+ var contextSeen = {};
88
+ var that = this;
89
+ this.sample.elements.forEach(function(sampleElement) {
90
+ var context = sampleElement.b;
91
+ if (!contextSeen[context]) {
92
+ contextSeen[context] = true;
93
+ that.aPosterioriNormalisationConstants[context] =
94
+ that.aPosterioriNormalisation(context);
95
+ }
96
+ });
97
+ };
98
+
99
+ // Memoize all probabilities of sample elements
100
+ Distribution.prototype.prepare = function() {
101
+ this.prepareWeights();
102
+ //console.log("Weights prepared");
103
+ this.prepareAPosterioris();
104
+ };
105
+
106
+ // Relative entropy between observered distribution and derived distribution
107
+ Distribution.prototype.KullbackLieblerDistance = function() {
108
+ var sum = 0;
109
+ var that = this;
110
+ this.sample.elements.forEach(function(x) {
111
+ sum += that.sample.observedProbability(x) * Math.log(that.sample.observedProbability(x) / that.calculateAPriori(x));
112
+ });
113
+ return sum;
114
+ };
115
+
116
+ Distribution.prototype.logLikelihood = function() {
117
+ var sum = 0;
118
+ var that = this;
119
+ this.sample.elements.forEach(function(x) {
120
+ sum += that.sample.observedProbability(x) * Math.log(that.calculateAPriori(x));
121
+ });
122
+ return sum;
123
+ };
124
+
125
+ Distribution.prototype.entropy = function() {
126
+ var sum = 0;
127
+ var that = this;
128
+ this.sample.elements.forEach(function(x) {
129
+ var p = that.calculateAPriori(x);
130
+ sum += p * Math.log(p);
131
+ });
132
+ return sum;
133
+ };
134
+
135
+ Distribution.prototype.checkSum = function() {
136
+ var sum = 0;
137
+ var that = this;
138
+ this.sample.elements.forEach(function(x) {
139
+ sum += that.calculateAPriori(x);
140
+ });
141
+ //console.log("Distribution.checkSum is " + sum);
142
+ return sum;
143
+ }
144
+
145
+ module.exports = Distribution;
@@ -0,0 +1,34 @@
1
+ /*
2
+ Element class for elements in the event space
3
+ Copyright (C) 2017 Hugo W.L. ter Doest
4
+
5
+ This program is free software: you can redistribute it and/or modify
6
+ it under the terms of the GNU General Public License as published by
7
+ the Free Software Foundation, either version 3 of the License, or
8
+ (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU General Public License for more details.
14
+
15
+ You should have received a copy of the GNU General Public License
16
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+ var Feature = require('./Feature');
20
+
21
+ // a is class and b is context
22
+ function Element(a, b) {
23
+ this.a = a;
24
+ this.b = b;
25
+ }
26
+
27
+ Element.prototype.toString = function() {
28
+ if (!this.key) {
29
+ this.key = this.a + this.b.toString();
30
+ }
31
+ return this.key;
32
+ };
33
+
34
+ module.exports = Element;
@@ -0,0 +1,88 @@
1
+ /*
2
+ Feature class for features that fire (or don't) on combinations of context
3
+ and class
4
+ Copyright (C) 2017 Hugo W.L. ter Doest
5
+
6
+ This program is free software: you can redistribute it and/or modify
7
+ it under the terms of the GNU General Public License as published by
8
+ the Free Software Foundation, either version 3 of the License, or
9
+ (at your option) any later version.
10
+
11
+ This program is distributed in the hope that it will be useful,
12
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ GNU General Public License for more details.
15
+
16
+ You should have received a copy of the GNU General Public License
17
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ */
19
+
20
+
21
+ function Feature(f, name, parameters) {
22
+ this.evaluate = f;
23
+ this.name = name;
24
+ this.parameters = parameters;
25
+
26
+ var tmp = "";
27
+ parameters.forEach(function(par) {
28
+ tmp += par + "|";
29
+ });
30
+ this.parametersKey = tmp.substr(0, tmp.length - 1);
31
+ }
32
+
33
+ Feature.prototype.apply = function(x) {
34
+ return this.evaluate(x);
35
+ };
36
+
37
+ Feature.prototype.expectationApprox = function(p, sample) {
38
+ var totalSum = 0;
39
+ var that = this;
40
+ var sum = 0;
41
+ var seen = {};
42
+ var A = sample.getClasses();
43
+ sample.elements.forEach(function(sampleElement) {
44
+ var b_i = sampleElement.b;
45
+
46
+ if (!seen[b_i.toString()]) {
47
+ seen[b_i.toString()] = true;
48
+ var Element = require('./Element');
49
+
50
+ A.forEach(function(a) {
51
+ var x = new Element(a, b_i);
52
+ sum += sample.observedProbabilityOfContext(b_i) * p.calculateAPosteriori(x) * that.apply(x);
53
+ });
54
+ }
55
+ });
56
+ return sum;
57
+ };
58
+
59
+ // Diect calculation of expected value of this feature according to distribution p
60
+ // In real-life applications with a lot of features this is not tractable
61
+ Feature.prototype.expectation = function(p, A, B) {
62
+ var sum = 0;
63
+ var that = this;
64
+ A.forEach(function(a) {
65
+ B.forEach(function(b) {
66
+ var x = new Element(a, b);
67
+ sum += (p.calculateAPriori(x) * that.apply(x));
68
+ });
69
+ });
70
+ return sum;
71
+ };
72
+
73
+ // Observed expectation of this feature in the sample
74
+ Feature.prototype.observedExpectation = function(sample) {
75
+ if (this.observedExpect) {
76
+ return this.observedExpect;
77
+ }
78
+ var N = sample.size();
79
+ var sum = 0;
80
+ var that = this;
81
+ sample.elements.forEach(function(x) {
82
+ sum += that.apply(x);
83
+ });
84
+ this.observedExpect = sum / N;
85
+ return this.observedExpect;
86
+ };
87
+
88
+ module.exports = Feature;
@@ -0,0 +1,67 @@
1
+ /*
2
+ Feature set class for administrating a set of unique feature
3
+ Copyright (C) 2017 Hugo W.L. ter Doest
4
+
5
+ This program is free software: you can redistribute it and/or modify
6
+ it under the terms of the GNU General Public License as published by
7
+ the Free Software Foundation, either version 3 of the License, or
8
+ (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU General Public License for more details.
14
+
15
+ You should have received a copy of the GNU General Public License
16
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+
20
+ function FeatureSet() {
21
+ this.features = [];
22
+ this.map = {};
23
+ }
24
+
25
+ // Returns true if the feature did not exist and was added
26
+ FeatureSet.prototype.addFeature = function(feature) {
27
+ if (!this.featureExists(feature)) {
28
+ this.map[feature.name +" | " + feature.parametersKey] = true;
29
+ this.features.push(feature);
30
+ //console.log("FeatureSet.addFeature: feature added: " + feature.name + " - " + feature.parametersKey);
31
+ return true;
32
+ }
33
+ else {
34
+ return false;
35
+ }
36
+ };
37
+
38
+ FeatureSet.prototype.featureExists = function(feature) {
39
+ if (this.map[feature.name +" | " + feature.parametersKey]) {
40
+ //console.log("FeatureSet.featureExists: feature already exists: " +
41
+ // feature.name + " - " + feature.parameters);
42
+ return true;
43
+ }
44
+ else {
45
+ return false;
46
+ }
47
+ };
48
+
49
+ // Returns an array of features
50
+ // If the available array this.features is up to date it is returned immediately
51
+ FeatureSet.prototype.getFeatures = function() {
52
+ return this.features;
53
+ };
54
+
55
+ FeatureSet.prototype.size = function() {
56
+ return this.features.length;
57
+ };
58
+
59
+ FeatureSet.prototype.prettyPrint = function() {
60
+ var s = "";
61
+ Object.keys(this.map).forEach(function(key) {
62
+ s += key + "\n";
63
+ });
64
+ return s;
65
+ };
66
+
67
+ module.exports = FeatureSet;
@@ -0,0 +1,148 @@
1
+ /*
2
+ GISScaler class that finds parameters of features
3
+ Copyright (C) 2017 Hugo W.L. ter Doest
4
+
5
+ This program is free software: you can redistribute it and/or modify
6
+ it under the terms of the GNU General Public License as published by
7
+ the Free Software Foundation, either version 3 of the License, or
8
+ (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU General Public License for more details.
14
+
15
+ You should have received a copy of the GNU General Public License
16
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+ var Element = require('./Element');
20
+ var Feature = require('./Feature');
21
+ var Distribution = require('./Distribution');
22
+
23
+ // classes is an array of classes
24
+ // features is an array of feature functions
25
+ function GISScaler(featureSet, sample) {
26
+ this.featureSet = featureSet;
27
+ this.sample = sample;
28
+ }
29
+
30
+ // Returns true if a correction feature is necessary
31
+ GISScaler.prototype.calculateMaxSumOfFeatures = function() {
32
+ var that = this;
33
+ this.C = 0;
34
+ this.featureSums = {};
35
+ var listOfSumValues = [];
36
+
37
+ // Since feature functions are derived from the sample
38
+ // we can use the sample to calculate the max sum
39
+ // We look at each sample element only once
40
+ this.sample.elements.forEach(function(x) {
41
+ if (!that.featureSums[x.toString()]) {
42
+ var sum = 0;
43
+ that.featureSet.getFeatures().forEach(function(f) {
44
+ sum += f.apply(x);
45
+ });
46
+ if (sum > that.C) {
47
+ that.C = sum;
48
+ }
49
+ that.featureSums[x.toString()] = sum;
50
+ listOfSumValues.push(sum);
51
+ }
52
+ });
53
+ //console.log("GISScaler:calculateMaxSumOfFeatures:maxSum is " + this.C);
54
+
55
+ // Check if a correction feature is necessary
56
+ listOfSumValues.sort(function(a, b) {
57
+ return a - b;
58
+ });
59
+ return(listOfSumValues[0] !== listOfSumValues[listOfSumValues.length - 1]);
60
+ };
61
+
62
+ GISScaler.prototype.addCorrectionFeature = function() {
63
+ if (this.calculateMaxSumOfFeatures()) {
64
+ //console.log("GISScaler:addCorrectionFeature:C is " + this.C);
65
+ var that = this;
66
+
67
+ function f(x) {
68
+ if (that.featureSums[x.toString()] !== undefined) {
69
+ return that.C - that.featureSums[x.toString()];
70
+ }
71
+ return 0;
72
+ }
73
+
74
+ var correctionFeature = new Feature(f, "Correction feature", []);
75
+ //console.log("GISScaler:addCorrectionFeature:correctionFeature " + JSON.stringify(correctionFeature));
76
+ this.featureSet.addFeature(correctionFeature);
77
+ }
78
+ else {
79
+ //console.log("Correction feature not needed");
80
+ }
81
+ };
82
+
83
+ // This is the Generalised Iterative Scaling algorithm
84
+ // It ends if the improvement in likelihood of the distribution does not
85
+ // improve more than minImprovement or if the maximum number of iterations is
86
+ // reached.
87
+ GISScaler.prototype.run = function(maxIterations, minImprovement) {
88
+ this.iteration = 0;
89
+ this.improvement = 0;
90
+
91
+ this.addCorrectionFeature();
92
+ // Build up the distribution p
93
+ var alpha = new Array(this.featureSet.size());
94
+ for (var i = 0; i < alpha.length; i++) {
95
+ alpha[i] = 1;
96
+ }
97
+ var p = new Distribution(alpha, this.featureSet, this.sample);
98
+ //console.log("Distribution created");
99
+ p.prepare();
100
+ //console.log("Distribution prepared");
101
+ var likelihood = p.logLikelihood();
102
+ var KLDistance = p.KullbackLieblerDistance();
103
+
104
+ var newAlpha = new Array(this.featureSet.size());
105
+ var observedExpectation = 0;
106
+ var expectationApprox = 0;
107
+ do {
108
+ //console.log("Iteration " + this.iteration + " - Log likelihood of sample: " + likelihood + " - Entropy: " + p.entropy());
109
+ for (var i = 0; i < this.featureSet.size(); i++) {
110
+ observedExpectation = this.featureSet.getFeatures()[i].observedExpectation(this.sample);
111
+ expectationApprox = this.featureSet.getFeatures()[i].expectationApprox(p, this.sample);
112
+ //console.log("Iteration " + this.iteration + " - Feature " + i);
113
+ newAlpha[i] = p.alpha[i] * Math.pow(observedExpectation / expectationApprox, 1 / this.C);
114
+
115
+ //console.log("GISScaler.run: old alpha[" + i + "]: " + p.alpha[i]);
116
+ //console.log("GISScaler.run: new alpha[" + i + "]: " + newAlpha[i]);
117
+ }
118
+
119
+ // Make the newly calculated parameters current parameters
120
+ newAlpha.forEach(function(newAlpha_j, j) {
121
+ p.alpha[j] = newAlpha_j;
122
+ });
123
+ // Recalculate a priori and a posteriori probabilities
124
+ p.prepare();
125
+
126
+ this.iteration++;
127
+ var newLikelihood = p.logLikelihood();
128
+ var newKLDistance = p.KullbackLieblerDistance();
129
+ this.improvement = KLDistance - newKLDistance;
130
+ //console.log("Iteration " + this.iteration + " - Old likelihood: " + likelihood + " - New likelihood: " + newLikelihood);
131
+ //console.log("Iteration " + this.iteration + " - Old KL: " + KLDistance + " - New KL: " + newKLDistance);
132
+
133
+ likelihood = newLikelihood;
134
+ KLDistance = newKLDistance;
135
+ } while ((this.iteration < maxIterations) && (this.improvement > minImprovement));
136
+ //} while (iteration < maxIterations);
137
+ /*
138
+ var that = this;
139
+ this.featureSet.getFeatures().forEach(function(f, j) {
140
+ console.log("Observed expectation of feature " + j + ": " + f.observedExpectation(that.sample) +
141
+ " - Expection of feature according to p: " + f.expectationApprox(p, that.sample));
142
+ });
143
+ */
144
+
145
+ return p;
146
+ };
147
+
148
+ module.exports = GISScaler;
@@ -0,0 +1,56 @@
1
+ /*
2
+ Corpus class specific for MaxEnt modeling
3
+ Copyright (C) 2018 Hugo W.L. ter Doest
4
+
5
+ This program is free software: you can redistribute it and/or modify
6
+ it under the terms of the GNU General Public License as published by
7
+ the Free Software Foundation, either version 3 of the License, or
8
+ (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU General Public License for more details.
14
+
15
+ You should have received a copy of the GNU General Public License
16
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+ var util = require('util');
20
+ var Sample = require('../Sample');
21
+ var Corpus = require('../../../brill_pos_tagger/lib/Corpus');
22
+
23
+ function ME_Corpus(data, BROWN, SentenceClass) {
24
+ ME_Corpus.super_.call(this, data, BROWN, SentenceClass);
25
+ }
26
+
27
+ util.inherits(ME_Corpus, Corpus);
28
+
29
+ ME_Corpus.prototype.generateSample = function() {
30
+ var sample = new Sample([]);
31
+ this.sentences.forEach(function(sentence) {
32
+ sentence.generateSampleElements(sample);
33
+ });
34
+ return sample;
35
+ };
36
+
37
+ // Splits the corpus in a training and testing set.
38
+ // percentageTrain is the size of the training corpus in percent
39
+ // Returns an array with two elements: training corpus, testing corpus
40
+ ME_Corpus.prototype.splitInTrainAndTest = function(percentageTrain) {
41
+ var corpusTrain = new ME_Corpus();
42
+ var corpusTest = new ME_Corpus();
43
+
44
+ var p = percentageTrain / 100;
45
+ this.sentences.forEach(function(sentence, i) {
46
+ if (Math.random() < p) {
47
+ corpusTrain.sentences.push(sentence);
48
+ }
49
+ else {
50
+ corpusTest.sentences.push(sentence);
51
+ }
52
+ });
53
+ return [corpusTrain, corpusTest];
54
+ };
55
+
56
+ module.exports = ME_Corpus;
@@ -0,0 +1,73 @@
1
+ /*
2
+ Sentence class specific for MaxEnt modeling
3
+ Copyright (C) 2018 Hugo W.L. ter Doest
4
+
5
+ This program is free software: you can redistribute it and/or modify
6
+ it under the terms of the GNU General Public License as published by
7
+ the Free Software Foundation, either version 3 of the License, or
8
+ (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU General Public License for more details.
14
+
15
+ You should have received a copy of the GNU General Public License
16
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+ var util = require('util');
20
+ var Context = require('../Context');
21
+ var Sentence = require('../../../brill_pos_tagger/lib/Sentence');
22
+ var Element = require('./POS_Element');
23
+
24
+ function ME_Sentence() {
25
+ ME_Sentence.super_.call(this);
26
+ }
27
+
28
+ util.inherits(ME_Sentence, Sentence);
29
+
30
+ ME_Sentence.prototype.generateSampleElements = function(sample) {
31
+ var sentence = this.taggedWords;
32
+ sentence.forEach(function(token, index) {
33
+ var x = new Element(
34
+ token.tag,
35
+ new Context({
36
+ wordWindow: {},
37
+ tagWindow: {}
38
+ })
39
+ );
40
+
41
+ // Current word and tag
42
+ x.b.data.wordWindow["0"] = token.token;
43
+ x.b.data.tagWindow["0"] = sentence[index].tag;
44
+
45
+ // Previous bigram
46
+ if (index > 1) {
47
+ x.b.data.tagWindow["-2"] = sentence[index - 2].tag;
48
+ x.b.data.wordWindow["-2"] = sentence[index - 2].token;
49
+ }
50
+
51
+ // Left bigram
52
+ if (index > 0) {
53
+ x.b.data.tagWindow["-1"] = sentence[index - 1].tag;
54
+ x.b.data.wordWindow["-1"] = sentence[index - 1].token;
55
+ }
56
+
57
+ // Right bigram
58
+ if (index < sentence.length - 1) {
59
+ x.b.data.tagWindow["1"] = sentence[index + 1].tag;
60
+ x.b.data.wordWindow["1"] = sentence[index + 1].token;
61
+ }
62
+
63
+ // Next bigram
64
+ if (index < sentence.length - 2) {
65
+ x.b.data.tagWindow["2"] = sentence[index + 2].tag;
66
+ x.b.data.wordWindow["2"] = sentence[index + 2].token;
67
+ }
68
+
69
+ sample.addElement(x);
70
+ });
71
+ };
72
+
73
+ module.exports = ME_Sentence;