natural 0.1.27 → 0.2.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.
- package/.editorconfig +7 -0
- package/LICENSE.txt +0 -0
- package/Makefile +0 -0
- package/README.md +237 -24
- package/benchmarks/index.js +1 -1
- package/benchmarks/metaphone.js +0 -0
- package/benchmarks/soundex.js +0 -0
- package/examples/classification/basic.js +0 -0
- package/examples/classification/recall.js +0 -0
- package/examples/classification/store.js +0 -0
- package/examples/inflection/count.js +0 -0
- package/examples/inflection/noun.js +0 -0
- package/examples/inflection/noun_attach.js +0 -0
- package/examples/phonetics/compare.js +0 -0
- package/examples/phonetics/sounds_like.js +0 -0
- package/examples/phonetics/tokenize_and_phoneticize.js +0 -0
- package/examples/stemming/stem_corpus.js +0 -0
- package/examples/stemming/stem_word.js +0 -0
- package/examples/tfidf/array_example.js +0 -0
- package/examples/tfidf/multiple_terms.js +0 -0
- package/examples/tfidf/tfidf_example.js +0 -0
- package/index.js +0 -0
- package/io_spec/test_data/tfidf/one +0 -0
- package/io_spec/test_data/tfidf/two +0 -0
- package/io_spec/tfidf_spec.js +0 -0
- package/io_spec/wordnet_spec.js +0 -0
- package/lib/natural/analyzers/sentence_analyzer.js +16 -13
- package/lib/natural/classifiers/bayes_classifier.js +6 -2
- package/lib/natural/classifiers/classifier.js +0 -0
- package/lib/natural/classifiers/logistic_regression_classifier.js +0 -0
- package/lib/natural/distance/dice_coefficient.js +0 -0
- package/lib/natural/distance/jaro-winkler_distance.js +13 -8
- package/lib/natural/distance/levenshtein_distance.js +0 -0
- package/lib/natural/index.js +8 -0
- package/lib/natural/inflectors/count_inflector.js +0 -0
- package/lib/natural/inflectors/form_set.js +0 -0
- package/lib/natural/inflectors/fr/count_inflector.js +0 -0
- package/lib/natural/inflectors/fr/noun_inflector.js +0 -0
- package/lib/natural/inflectors/ja/noun_inflector.js +0 -0
- package/lib/natural/inflectors/noun_inflector.js +0 -0
- package/lib/natural/inflectors/present_verb_inflector.js +1 -0
- package/lib/natural/inflectors/singular_plural_inflector.js +1 -2
- package/lib/natural/ngrams/ngrams.js +45 -8
- package/lib/natural/ngrams/ngrams_zh.js +83 -0
- package/lib/natural/normalizers/normalizer.js +30 -38
- package/lib/natural/normalizers/normalizer_ja.js +26 -8
- package/lib/natural/normalizers/normalizer_no.js +59 -0
- package/lib/natural/phonetics/double_metaphone.js +9 -4
- package/lib/natural/phonetics/metaphone.js +6 -1
- package/lib/natural/phonetics/phonetic.js +0 -0
- package/lib/natural/phonetics/soundex.js +11 -7
- package/lib/natural/spellcheck/spellcheck.js +80 -0
- package/lib/natural/stemmers/lancaster_rules.js +4 -4
- package/lib/natural/stemmers/lancaster_stemmer.js +0 -0
- package/lib/natural/stemmers/porter_stemmer.js +90 -63
- package/lib/natural/stemmers/porter_stemmer_es.js +22 -23
- package/lib/natural/stemmers/porter_stemmer_fr.js +377 -0
- package/lib/natural/stemmers/porter_stemmer_no.js +155 -0
- package/lib/natural/stemmers/porter_stemmer_pt.js +302 -0
- package/lib/natural/stemmers/stemmer.js +0 -0
- package/lib/natural/stemmers/stemmer_fr.js +58 -0
- package/lib/natural/stemmers/stemmer_no.js +61 -0
- package/lib/natural/stemmers/stemmer_pt.js +65 -0
- package/lib/natural/stemmers/token.js +163 -0
- package/lib/natural/tfidf/tfidf.js +50 -19
- package/lib/natural/tokenizers/aggressive_tokenizer.js +0 -0
- package/lib/natural/tokenizers/aggressive_tokenizer_es.js +0 -0
- package/lib/natural/tokenizers/aggressive_tokenizer_fr.js +36 -0
- package/lib/natural/tokenizers/aggressive_tokenizer_nl.js +0 -0
- package/lib/natural/tokenizers/aggressive_tokenizer_no.js +39 -0
- package/lib/natural/tokenizers/aggressive_tokenizer_pt.js +0 -0
- package/lib/natural/tokenizers/regexp_tokenizer.js +0 -0
- package/lib/natural/tokenizers/tokenizer.js +2 -2
- package/lib/natural/tokenizers/treebank_word_tokenizer.js +0 -0
- package/lib/natural/trie/trie.js +47 -0
- package/lib/natural/util/bag.js +50 -0
- package/lib/natural/util/edge_weighted_digraph.js +112 -0
- package/lib/natural/util/longest_path_tree.js +99 -0
- package/lib/natural/util/shortest_path_tree.js +100 -0
- package/lib/natural/util/stopwords.js +0 -0
- package/lib/natural/util/stopwords_fr.js +194 -0
- package/lib/natural/util/stopwords_nl.js +43 -0
- package/lib/natural/util/stopwords_no.js +42 -0
- package/lib/natural/util/stopwords_pt.js +136 -0
- package/lib/natural/util/topological.js +98 -0
- package/lib/natural/wordnet/data_file.js +0 -0
- package/lib/natural/wordnet/index_file.js +0 -0
- package/lib/natural/wordnet/wordnet.js +0 -0
- package/lib/natural/wordnet/wordnet_file.js +0 -0
- package/package.json +2 -2
- package/spec/aggressive_tokenizer_fr_spec.js +101 -0
- package/spec/aggressive_tokenizer_pt_spec.js +0 -0
- package/spec/aggressive_tokenizer_spec.js +0 -0
- package/spec/bayes_classifier_spec.js +12 -0
- package/spec/classifier_spec.js +84 -0
- package/spec/count_inflector_fr_spec.js +0 -0
- package/spec/count_inflector_spec.js +0 -0
- package/spec/dice_coefficient_spec.js +0 -0
- package/spec/double_metaphone_spec.js +10 -1
- package/spec/jaro-winkler_spec.js +0 -0
- package/spec/lancaster_stemmer_spec.js +10 -1
- package/spec/levenshtein_spec.js +0 -0
- package/spec/logistic_regression_classifier_spec.js +0 -0
- package/spec/longest_path_tree_spec.js +102 -0
- package/spec/metaphone_spec.js +10 -0
- package/spec/ngram_spec.js +61 -0
- package/spec/ngram_zh_spec.js +122 -0
- package/spec/normalizer_ja_spec.js +9 -3
- package/spec/normalizer_no_spec.js +111 -0
- package/spec/normalizer_spec.js +26 -5
- package/spec/noun_inflector_fr_spec.js +0 -0
- package/spec/noun_inflector_ja_spec.js +0 -0
- package/spec/noun_inflector_spec.js +0 -0
- package/spec/porter_stemmer_fr_spec.js +101 -0
- package/spec/porter_stemmer_no_spec.js +143 -0
- package/spec/porter_stemmer_pt_spec.js +50 -0
- package/spec/porter_stemmer_spec.js +49 -0
- package/spec/present_verb_inflector_spec.js +3 -0
- package/spec/remove_diacritics_spec.js +31 -0
- package/spec/sentence_analyzer_spec.js +248 -0
- package/spec/shortest_path_tree_spec.js +132 -0
- package/spec/soundex_spec.js +13 -9
- package/spec/spellcheck_spec.js +92 -0
- package/spec/stemmer_token_spec.js +161 -0
- package/spec/test_data/snowball_fr.txt +20402 -0
- package/spec/test_data/snowball_no.txt +20628 -0
- package/spec/test_data/snowball_pt.txt +32016 -0
- package/spec/test_data/tfdif_testcorpus.txt +0 -0
- package/spec/test_data/tfidf_teststopwords.txt +0 -0
- package/spec/test_data/wordnet_mini.sql +0 -0
- package/spec/tfidf_spec.js +153 -28
- package/spec/tokenizer_ja_spec.js +0 -0
- package/spec/treebank_word_tokenizer_spec.js +0 -0
- package/spec/trie_spec.js +27 -3
package/.editorconfig
ADDED
package/LICENSE.txt
CHANGED
|
File without changes
|
package/Makefile
CHANGED
|
File without changes
|
package/README.md
CHANGED
|
@@ -18,15 +18,6 @@ will be in order. Thanks to Polyakov Vladimir, Russian stemming has been added!,
|
|
|
18
18
|
|
|
19
19
|
Aside from this README, the only documentation is [this DZone article](http://www.dzone.com/links/r/using_natural_a_nlp_module_for_nodejs.html) and [here on my blog](http://www.chrisumbel.com/article/node_js_natural_language_porter_stemmer_lancaster_bayes_naive_metaphone_soundex), which is a bit older.
|
|
20
20
|
|
|
21
|
-
Looking for Help Maintaining Natural!
|
|
22
|
-
-------------------------------------
|
|
23
|
-
|
|
24
|
-
I'm having trouble devoting the time necessary to maintain natural. While I'm certainly not
|
|
25
|
-
leaving the project I'd like someone to take over the day-to-day maintenance of dealing with
|
|
26
|
-
issues, pull requests and driving the direction of the software moving forward. Please contact
|
|
27
|
-
chris@chrisumbel.com if you're interested!
|
|
28
|
-
|
|
29
|
-
|
|
30
21
|
Installation
|
|
31
22
|
------------
|
|
32
23
|
|
|
@@ -47,24 +38,24 @@ arrays of tokens:
|
|
|
47
38
|
```javascript
|
|
48
39
|
var natural = require('natural'),
|
|
49
40
|
tokenizer = new natural.WordTokenizer();
|
|
50
|
-
console.log(tokenizer.tokenize("your dog has
|
|
51
|
-
// [ 'your', 'dog', 'has', '
|
|
41
|
+
console.log(tokenizer.tokenize("your dog has fleas."));
|
|
42
|
+
// [ 'your', 'dog', 'has', 'fleas' ]
|
|
52
43
|
```
|
|
53
44
|
|
|
54
45
|
The other tokenizers follow a similar pattern:
|
|
55
46
|
|
|
56
47
|
```javascript
|
|
57
48
|
tokenizer = new natural.TreebankWordTokenizer();
|
|
58
|
-
console.log(tokenizer.tokenize("my dog hasn't any
|
|
59
|
-
// [ 'my', 'dog', 'has', 'n\'t', 'any', '
|
|
49
|
+
console.log(tokenizer.tokenize("my dog hasn't any fleas."));
|
|
50
|
+
// [ 'my', 'dog', 'has', 'n\'t', 'any', 'fleas', '.' ]
|
|
60
51
|
|
|
61
52
|
tokenizer = new natural.RegexpTokenizer({pattern: /\-/});
|
|
62
|
-
console.log(tokenizer.tokenize("
|
|
63
|
-
// [ '
|
|
53
|
+
console.log(tokenizer.tokenize("flea-dog"));
|
|
54
|
+
// [ 'flea', 'dog' ]
|
|
64
55
|
|
|
65
56
|
tokenizer = new natural.WordPunctTokenizer();
|
|
66
|
-
console.log(tokenizer.tokenize("my dog hasn't any
|
|
67
|
-
// [ 'my', 'dog', 'hasn', '\'', 't', 'any', '
|
|
57
|
+
console.log(tokenizer.tokenize("my dog hasn't any fleas."));
|
|
58
|
+
// [ 'my', 'dog', 'hasn', '\'', 't', 'any', 'fleas', '.' ]
|
|
68
59
|
```
|
|
69
60
|
|
|
70
61
|
String Distance
|
|
@@ -193,7 +184,7 @@ tokenize and stem the text.
|
|
|
193
184
|
|
|
194
185
|
```javascript
|
|
195
186
|
classifier.addDocument('i am long qqqq', 'buy');
|
|
196
|
-
classifier.addDocument('buy the q'
|
|
187
|
+
classifier.addDocument('buy the q\'s', 'buy');
|
|
197
188
|
classifier.addDocument('short gold', 'sell');
|
|
198
189
|
classifier.addDocument('sell gold', 'sell');
|
|
199
190
|
|
|
@@ -217,8 +208,8 @@ You have access to the set of matched classes and the associated value from the
|
|
|
217
208
|
Outputs:
|
|
218
209
|
|
|
219
210
|
```javascript
|
|
220
|
-
[ { label: '
|
|
221
|
-
{ label: '
|
|
211
|
+
[ { label: 'buy', value: 0.39999999999999997 },
|
|
212
|
+
{ label: 'sell', value: 0.19999999999999998 } ]
|
|
222
213
|
```
|
|
223
214
|
|
|
224
215
|
From this:
|
|
@@ -492,6 +483,57 @@ The above outputs: `[ [ 'some', 'other', 'words', 'here' ],
|
|
|
492
483
|
[ 'other', 'words', 'here', 'for' ],
|
|
493
484
|
[ 'words', 'here', 'for', 'you' ] ]`
|
|
494
485
|
|
|
486
|
+
### padding
|
|
487
|
+
|
|
488
|
+
n-grams can also be returned with left or right padding by passing a start and/or end symbol to the bigrams, trigrams or ngrams.
|
|
489
|
+
|
|
490
|
+
```javascript
|
|
491
|
+
console.log(NGrams.ngrams('some other words here for you', 4, '[start]', '[end]'));
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
The above will output:
|
|
495
|
+
```
|
|
496
|
+
[ [ '[start]', '[start]', '[start]', 'some' ],
|
|
497
|
+
[ '[start]', '[start]', 'some', 'other' ],
|
|
498
|
+
[ '[start]', 'some', 'other', 'words' ],
|
|
499
|
+
[ 'some', 'other', 'words', 'here' ],
|
|
500
|
+
[ 'other', 'words', 'here', 'for' ],
|
|
501
|
+
[ 'words', 'here', 'for', 'you' ],
|
|
502
|
+
[ 'here', 'for', 'you', '[end]' ],
|
|
503
|
+
[ 'for', 'you', '[end]', '[end]' ],
|
|
504
|
+
[ 'you', '[end]', '[end]', '[end]' ] ]
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
For only end symbols, pass `null` for the start symbol, for instance:
|
|
508
|
+
```javascript
|
|
509
|
+
console.log(NGrams.ngrams('some other words here for you', 4, null, '[end]'));
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
Will output:
|
|
513
|
+
```
|
|
514
|
+
[ [ 'some', 'other', 'words', 'here' ],
|
|
515
|
+
[ 'other', 'words', 'here', 'for' ],
|
|
516
|
+
[ 'words', 'here', 'for', 'you' ],
|
|
517
|
+
[ 'here', 'for', 'you', '[end]' ],
|
|
518
|
+
[ 'for', 'you', '[end]', '[end]' ],
|
|
519
|
+
[ 'you', '[end]', '[end]', '[end]' ] ]
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
### NGramsZH
|
|
523
|
+
|
|
524
|
+
For Chinese like languages, you can use NGramsZH to do a n-gram, and all apis are the same:
|
|
525
|
+
|
|
526
|
+
```javascript
|
|
527
|
+
var NGramsZH = natural.NGramsZH;
|
|
528
|
+
console.log(NGramsZH.bigrams('中文测试'));
|
|
529
|
+
console.log(NGramsZH.bigrams(['中', '文', '测', '试']));
|
|
530
|
+
console.log(NGramsZH.trigrams('中文测试'));
|
|
531
|
+
console.log(NGramsZH.trigrams(['中', '文', '测', '试']));
|
|
532
|
+
console.log(NGramsZH.ngrams('一个中文测试', 4));
|
|
533
|
+
console.log(NGramsZH.ngrams(['一', '个', '中', '文', '测',
|
|
534
|
+
'试'], 4));
|
|
535
|
+
```
|
|
536
|
+
|
|
495
537
|
tf-idf
|
|
496
538
|
-----
|
|
497
539
|
|
|
@@ -555,7 +597,7 @@ tfidf.addFileSync('data_files/two.txt');
|
|
|
555
597
|
|
|
556
598
|
Multiple terms can be measured as well, with their weights being added into
|
|
557
599
|
a single measure value. The following example determines that the last document
|
|
558
|
-
is the most
|
|
600
|
+
is the most relevant to the words "node" and "ruby".
|
|
559
601
|
|
|
560
602
|
```javascript
|
|
561
603
|
var natural = require('natural'),
|
|
@@ -608,7 +650,7 @@ tfidf.listTerms(0 /*document index*/).forEach(function(item) {
|
|
|
608
650
|
});
|
|
609
651
|
```
|
|
610
652
|
|
|
611
|
-
A TfIdf instance can also be serialized and
|
|
653
|
+
A TfIdf instance can also be serialized and deserialized for save and recall.
|
|
612
654
|
|
|
613
655
|
```javascript
|
|
614
656
|
var tfidf = new TfIdf();
|
|
@@ -625,8 +667,8 @@ Tries
|
|
|
625
667
|
-----
|
|
626
668
|
|
|
627
669
|
Tries are a very efficient data structure used for prefix-based searches.
|
|
628
|
-
Natural comes packaged with a basic Trie implementation
|
|
629
|
-
|
|
670
|
+
Natural comes packaged with a basic Trie implementation which can support match collection along a path,
|
|
671
|
+
existence search and prefix search.
|
|
630
672
|
|
|
631
673
|
### Building The Trie
|
|
632
674
|
|
|
@@ -677,6 +719,14 @@ trie.addString("est");
|
|
|
677
719
|
console.log(trie.findMatchesOnPath("tester")); // ['tes', 'test'];
|
|
678
720
|
```
|
|
679
721
|
|
|
722
|
+
### All Keys with Prefix
|
|
723
|
+
|
|
724
|
+
This search will return all of the words in the Trie with the given prefix, or [ ] if not found.
|
|
725
|
+
|
|
726
|
+
```javascript
|
|
727
|
+
console.log(trie.keysWithPrefix("string")); // ["string1", "string2", "string3"]
|
|
728
|
+
```
|
|
729
|
+
|
|
680
730
|
### Case-Sensitivity
|
|
681
731
|
|
|
682
732
|
By default the trie is case-sensitive, you can use it in case-_in_sensitive mode by passing `false`
|
|
@@ -691,6 +741,144 @@ ciTrie.contains("TEsT"); // true
|
|
|
691
741
|
```
|
|
692
742
|
In the case of the searches which return strings, all strings returned will be in lower case if you are in case-_in_sensitive mode.
|
|
693
743
|
|
|
744
|
+
EdgeWeightedDigraph
|
|
745
|
+
-------------------
|
|
746
|
+
EdgeWeightedDigraph represents a digraph, you can add an edge, get the number vertexes, edges, get all edges and use toString to print the Digraph.
|
|
747
|
+
|
|
748
|
+
initialize a digraph:
|
|
749
|
+
|
|
750
|
+
```javascript
|
|
751
|
+
var EdgeWeightedDigraph = natural.EdgeWeightedDigraph;
|
|
752
|
+
var digraph = new EdgeWeightedDigraph();
|
|
753
|
+
digraph.add(5,4,0.35);
|
|
754
|
+
digraph.add(5,1,0.32);
|
|
755
|
+
digraph.add(1,3,0.29);
|
|
756
|
+
digraph.add(6,2,0.40);
|
|
757
|
+
digraph.add(3,6,0.52);
|
|
758
|
+
digraph.add(6,4,0.93);
|
|
759
|
+
```
|
|
760
|
+
the api used is: add(from, to, weight).
|
|
761
|
+
|
|
762
|
+
get the number of vertexes:
|
|
763
|
+
|
|
764
|
+
```javascript
|
|
765
|
+
console.log(digraph.v());
|
|
766
|
+
```
|
|
767
|
+
you will get 5.
|
|
768
|
+
|
|
769
|
+
get the number of edges:
|
|
770
|
+
|
|
771
|
+
```javascript
|
|
772
|
+
console.log(digraph.e());
|
|
773
|
+
```
|
|
774
|
+
you will get 5.
|
|
775
|
+
|
|
776
|
+
|
|
777
|
+
|
|
778
|
+
ShortestPathTree
|
|
779
|
+
----------------
|
|
780
|
+
|
|
781
|
+
ShortestPathTree represents a data type for solving the single-source shortest paths problem in
|
|
782
|
+
edge-weighted directed acyclic graphs (DAGs).
|
|
783
|
+
The edge weights can be positive, negative, or zero. There are three APIs:
|
|
784
|
+
getDistTo(vertex),
|
|
785
|
+
hasPathTo(vertex),
|
|
786
|
+
pathTo(vertex).
|
|
787
|
+
|
|
788
|
+
```javascript
|
|
789
|
+
var ShortestPathTree = natural.ShortestPathTree;
|
|
790
|
+
var spt = new ShortestPathTree(digraph, 5);
|
|
791
|
+
```
|
|
792
|
+
digraph is an instance of EdgeWeightedDigraph, the second param is the start vertex of DAG.
|
|
793
|
+
|
|
794
|
+
### getDistTo(vertex)
|
|
795
|
+
|
|
796
|
+
Will return the dist to vertex.
|
|
797
|
+
|
|
798
|
+
```javascript
|
|
799
|
+
console.log(spt.getDistTo(4));
|
|
800
|
+
```
|
|
801
|
+
the output will be: 0.35
|
|
802
|
+
|
|
803
|
+
### hasDistTo(vertex)
|
|
804
|
+
|
|
805
|
+
```javascript
|
|
806
|
+
console.log(spt.hasDistTo(4));
|
|
807
|
+
console.log(spt.hasDistTo(5));
|
|
808
|
+
```
|
|
809
|
+
|
|
810
|
+
output will be:
|
|
811
|
+
|
|
812
|
+
```javascript
|
|
813
|
+
true
|
|
814
|
+
false
|
|
815
|
+
```
|
|
816
|
+
|
|
817
|
+
### pathTo(vertex)
|
|
818
|
+
this will return a shortest path:
|
|
819
|
+
|
|
820
|
+
```javascript
|
|
821
|
+
console.log(spt.pathTo(4));
|
|
822
|
+
```
|
|
823
|
+
|
|
824
|
+
output will be:
|
|
825
|
+
|
|
826
|
+
```javascript
|
|
827
|
+
[5, 4]
|
|
828
|
+
```
|
|
829
|
+
|
|
830
|
+
LongestPathTree
|
|
831
|
+
----------------
|
|
832
|
+
|
|
833
|
+
LongestPathTree represents a data type for solving the single-source shortest paths problem in
|
|
834
|
+
edge-weighted directed acyclic graphs (DAGs).
|
|
835
|
+
The edge weights can be positive, negative, or zero. There are three APIs same as ShortestPathTree:
|
|
836
|
+
getDistTo(vertex),
|
|
837
|
+
hasPathTo(vertex),
|
|
838
|
+
pathTo(vertex).
|
|
839
|
+
|
|
840
|
+
```javascript
|
|
841
|
+
var ShortestPathTree = natural.ShortestPathTree;
|
|
842
|
+
var spt = new ShortestPathTree(digraph, 5);
|
|
843
|
+
```
|
|
844
|
+
digraph is an instance of EdgeWeightedDigraph, the second param is the start vertex of DAG.
|
|
845
|
+
|
|
846
|
+
### getDistTo(vertex)
|
|
847
|
+
|
|
848
|
+
Will return the dist to vertex.
|
|
849
|
+
|
|
850
|
+
```javascript
|
|
851
|
+
console.log(spt.getDistTo(4));
|
|
852
|
+
```
|
|
853
|
+
the output will be: 2.06
|
|
854
|
+
|
|
855
|
+
### hasDistTo(vertex)
|
|
856
|
+
|
|
857
|
+
```javascript
|
|
858
|
+
console.log(spt.hasDistTo(4));
|
|
859
|
+
console.log(spt.hasDistTo(5));
|
|
860
|
+
```
|
|
861
|
+
|
|
862
|
+
output will be:
|
|
863
|
+
|
|
864
|
+
```javascript
|
|
865
|
+
true
|
|
866
|
+
false
|
|
867
|
+
```
|
|
868
|
+
|
|
869
|
+
### pathTo(vertex)
|
|
870
|
+
this will return a shortest path:
|
|
871
|
+
|
|
872
|
+
```javascript
|
|
873
|
+
console.log(spt.pathTo(4));
|
|
874
|
+
```
|
|
875
|
+
|
|
876
|
+
output will be:
|
|
877
|
+
|
|
878
|
+
```javascript
|
|
879
|
+
[5, 1, 3, 6, 4]
|
|
880
|
+
```
|
|
881
|
+
|
|
694
882
|
WordNet
|
|
695
883
|
-------
|
|
696
884
|
|
|
@@ -747,6 +935,31 @@ As of v0.1.11, WordNet data files are no longer automatically downloaded.
|
|
|
747
935
|
|
|
748
936
|
Princeton University "About WordNet." WordNet. Princeton University. 2010. <http://wordnet.princeton.edu>
|
|
749
937
|
|
|
938
|
+
Spellcheck
|
|
939
|
+
------------
|
|
940
|
+
A probabilistic spellchecker based on http://norvig.com/spell-correct.html
|
|
941
|
+
|
|
942
|
+
This is best constructed with an array of tokens from a corpus, but a simple list of words from a dictionary will work.
|
|
943
|
+
|
|
944
|
+
```javascript
|
|
945
|
+
var corpus = ['something', 'soothing'];
|
|
946
|
+
var spellcheck = new Spellcheck(corpus);
|
|
947
|
+
```
|
|
948
|
+
|
|
949
|
+
It uses the trie datastructure for fast boolean lookup of a word
|
|
950
|
+
|
|
951
|
+
```javascript
|
|
952
|
+
spellcheck.isCorrect('cat'); // false
|
|
953
|
+
```
|
|
954
|
+
|
|
955
|
+
It suggests corrections (sorted by probability in descending order) that are up to a maximum edit distance away from the input word. According to Norvig, a max distance of 1 will cover 80% to 95% of spelling mistakes. After a distance of 2, it becomes very slow.
|
|
956
|
+
|
|
957
|
+
```javascript
|
|
958
|
+
spellcheck.getCorrections('soemthing', 1); // ['something']
|
|
959
|
+
spellcheck.getCorrections('soemthing', 2); // ['something', 'soothing']
|
|
960
|
+
```
|
|
961
|
+
|
|
962
|
+
|
|
750
963
|
Development
|
|
751
964
|
-----------
|
|
752
965
|
When developing, please:
|
package/benchmarks/index.js
CHANGED
package/benchmarks/metaphone.js
CHANGED
|
File without changes
|
package/benchmarks/soundex.js
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/index.js
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/io_spec/tfidf_spec.js
CHANGED
|
File without changes
|
package/io_spec/wordnet_spec.js
CHANGED
|
File without changes
|
|
@@ -46,7 +46,7 @@ var Sentences = function(pos, callback) {
|
|
|
46
46
|
this.posObj = pos;
|
|
47
47
|
this.senType = null;
|
|
48
48
|
callback(this);
|
|
49
|
-
}
|
|
49
|
+
};
|
|
50
50
|
|
|
51
51
|
Sentences.prototype.part = function(callback) {
|
|
52
52
|
var subject = [],
|
|
@@ -88,7 +88,7 @@ Sentences.prototype.part = function(callback) {
|
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
callback(this);
|
|
91
|
-
}
|
|
91
|
+
};
|
|
92
92
|
|
|
93
93
|
// Takes POS and removes IN to NN or NNS
|
|
94
94
|
// Adds a PP for each prepositionPhrases
|
|
@@ -108,15 +108,15 @@ Sentences.prototype.prepositionPhrases = function() {
|
|
|
108
108
|
remove = false;
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
|
-
}
|
|
111
|
+
};
|
|
112
112
|
|
|
113
113
|
Sentences.prototype.subjectToString = function() {
|
|
114
114
|
return this.posObj.tags.map(function(t){ if (t.spos == "SP" || t.spos == "S" ) return t.token }).join(' ');
|
|
115
|
-
}
|
|
115
|
+
};
|
|
116
116
|
|
|
117
117
|
Sentences.prototype.predicateToString = function() {
|
|
118
118
|
return this.posObj.tags.map(function(t){ if (t.spos == "PP" || t.spos == "P" ) return t.token }).join(' ');
|
|
119
|
-
}
|
|
119
|
+
};
|
|
120
120
|
|
|
121
121
|
Sentences.prototype.implicitYou = function() {
|
|
122
122
|
for (var i = 0; i < this.posObj.tags.length;i++) {
|
|
@@ -126,22 +126,25 @@ Sentences.prototype.implicitYou = function() {
|
|
|
126
126
|
}
|
|
127
127
|
|
|
128
128
|
return false;
|
|
129
|
-
}
|
|
129
|
+
};
|
|
130
130
|
|
|
131
131
|
Sentences.prototype.toString = function() {
|
|
132
132
|
return this.posObj.tags.map(function(t){return t.token}).join(' ');
|
|
133
|
-
}
|
|
133
|
+
};
|
|
134
134
|
|
|
135
135
|
// This is quick and incomplete.
|
|
136
136
|
Sentences.prototype.type = function(callback) {
|
|
137
137
|
var callback = callback || false;
|
|
138
|
-
|
|
138
|
+
|
|
139
|
+
// Check for implicit you before popping a tag.
|
|
140
|
+
var implicitYou = this.implicitYou();
|
|
141
|
+
|
|
139
142
|
// FIXME - punct seems useless
|
|
140
143
|
var lastElement = this.posObj.punct();
|
|
141
144
|
lastElement = (lastElement.length != 0) ? lastElement.pop() : this.posObj.tags.pop();
|
|
142
|
-
|
|
145
|
+
|
|
143
146
|
if (lastElement.pos !== ".") {
|
|
144
|
-
if (
|
|
147
|
+
if (implicitYou) {
|
|
145
148
|
this.senType = "COMMAND";
|
|
146
149
|
} else if (_(["WDT","WP","WP$","WRB"]).contains(this.posObj.tags[0].pos)) {
|
|
147
150
|
// Sentences that start with: who, what where when why and how, then they are questions
|
|
@@ -158,8 +161,8 @@ Sentences.prototype.type = function(callback) {
|
|
|
158
161
|
} else {
|
|
159
162
|
switch(lastElement.token) {
|
|
160
163
|
case "?": this.senType = "INTERROGATIVE"; break;
|
|
161
|
-
case "!": this.senType = (
|
|
162
|
-
case ".": this.senType = (
|
|
164
|
+
case "!": this.senType = (implicitYou) ? "COMMAND":"EXCLAMATORY"; break;
|
|
165
|
+
case ".": this.senType = (implicitYou) ? "COMMAND":"DECLARATIVE"; break;
|
|
163
166
|
}
|
|
164
167
|
}
|
|
165
168
|
|
|
@@ -168,6 +171,6 @@ Sentences.prototype.type = function(callback) {
|
|
|
168
171
|
} else {
|
|
169
172
|
return this.senType;
|
|
170
173
|
}
|
|
171
|
-
}
|
|
174
|
+
};
|
|
172
175
|
|
|
173
176
|
module.exports = Sentences;
|
|
@@ -25,8 +25,12 @@ util = require('util'),
|
|
|
25
25
|
Classifier = require('./classifier'),
|
|
26
26
|
ApparatusBayesClassifier = require('apparatus').BayesClassifier;
|
|
27
27
|
|
|
28
|
-
var BayesClassifier = function(stemmer) {
|
|
29
|
-
|
|
28
|
+
var BayesClassifier = function(stemmer, smoothing) {
|
|
29
|
+
var abc = new ApparatusBayesClassifier();
|
|
30
|
+
if (smoothing && isFinite(smoothing)) {
|
|
31
|
+
abc = new ApparatusBayesClassifier(smoothing);
|
|
32
|
+
}
|
|
33
|
+
Classifier.call(this, abc, stemmer);
|
|
30
34
|
};
|
|
31
35
|
|
|
32
36
|
util.inherits(BayesClassifier, Classifier);
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -99,13 +99,18 @@ function distance(s1, s2) {
|
|
|
99
99
|
// s2 is the second string to compare
|
|
100
100
|
// dj is the Jaro Distance (if you've already computed it), leave blank and the method handles it
|
|
101
101
|
function JaroWinklerDistance(s1, s2, dj) {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
102
|
+
if (s1 == s2) {
|
|
103
|
+
return 1
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
var jaro;
|
|
107
|
+
(typeof(dj) == 'undefined')? jaro = distance(s1,s2) : jaro = dj;
|
|
108
|
+
var p = 0.1; //
|
|
109
|
+
var l = 0 // length of the matching prefix
|
|
110
|
+
while(s1[l] == s2[l] && l < 4)
|
|
111
|
+
l++;
|
|
112
|
+
|
|
113
|
+
return jaro + l * p * (1 - jaro);
|
|
114
|
+
}
|
|
110
115
|
}
|
|
111
116
|
module.exports = JaroWinklerDistance;
|
|
File without changes
|
package/lib/natural/index.js
CHANGED
|
@@ -26,10 +26,13 @@ exports.DoubleMetaphone = require('./phonetics/double_metaphone');
|
|
|
26
26
|
exports.SoundExDM = require('./phonetics/dm_soundex');
|
|
27
27
|
exports.PorterStemmer = require('./stemmers/porter_stemmer');
|
|
28
28
|
exports.PorterStemmerFa = require('./stemmers/porter_stemmer_fa');
|
|
29
|
+
exports.PorterStemmerFr = require('./stemmers/porter_stemmer_fr');
|
|
29
30
|
exports.PorterStemmerRu = require('./stemmers/porter_stemmer_ru');
|
|
30
31
|
exports.PorterStemmerEs = require('./stemmers/porter_stemmer_es');
|
|
31
32
|
exports.PorterStemmerIt = require('./stemmers/porter_stemmer_it');
|
|
33
|
+
exports.PorterStemmerNo = require('./stemmers/porter_stemmer_no');
|
|
32
34
|
exports.LancasterStemmer = require('./stemmers/lancaster_stemmer');
|
|
35
|
+
exports.StemmerFr = require('./stemmers/stemmer_fr');
|
|
33
36
|
exports.StemmerPl = require('./stemmers/stemmer_pl');
|
|
34
37
|
exports.StemmerJa = require('./stemmers/stemmer_ja');
|
|
35
38
|
exports.AggressiveTokenizerNl = require('./tokenizers/aggressive_tokenizer_nl');
|
|
@@ -39,6 +42,7 @@ exports.AggressiveTokenizerEs = require('./tokenizers/aggressive_tokenizer_es');
|
|
|
39
42
|
exports.AggressiveTokenizerIt = require('./tokenizers/aggressive_tokenizer_it');
|
|
40
43
|
exports.AggressiveTokenizerPl = require('./tokenizers/aggressive_tokenizer_pl');
|
|
41
44
|
exports.AggressiveTokenizerPt = require('./tokenizers/aggressive_tokenizer_pt');
|
|
45
|
+
exports.AggressiveTokenizerNo = require('./tokenizers/aggressive_tokenizer_no');
|
|
42
46
|
exports.AggressiveTokenizer = require('./tokenizers/aggressive_tokenizer');
|
|
43
47
|
exports.RegexpTokenizer = require('./tokenizers/regexp_tokenizer').RegexpTokenizer;
|
|
44
48
|
exports.WordTokenizer = require('./tokenizers/regexp_tokenizer').WordTokenizer;
|
|
@@ -57,7 +61,11 @@ exports.TfIdf = require('./tfidf/tfidf');
|
|
|
57
61
|
exports.Trie = require('./trie/trie');
|
|
58
62
|
exports.SentenceAnalyzer = require('./analyzers/sentence_analyzer');
|
|
59
63
|
exports.stopwords = require('./util/stopwords').words;
|
|
64
|
+
exports.ShortestPathTree = require('./util/shortest_path_tree');
|
|
65
|
+
exports.LongestPathTree = require('./util/longest_path_tree');
|
|
66
|
+
exports.EdgeWeightedDigraph = require('./util/edge_weighted_digraph');
|
|
60
67
|
exports.NGrams = require('./ngrams/ngrams');
|
|
68
|
+
exports.NGramsZH = require('./ngrams/ngrams_zh');
|
|
61
69
|
exports.JaroWinklerDistance = require('./distance/jaro-winkler_distance');
|
|
62
70
|
exports.LevenshteinDistance = require('./distance/levenshtein_distance');
|
|
63
71
|
exports.DiceCoefficient = require('./distance/dice_coefficient');
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -51,6 +51,7 @@ var VerbInflector = function() {
|
|
|
51
51
|
this.addIrregular("am", "are");
|
|
52
52
|
this.addIrregular("is", "are");
|
|
53
53
|
this.addIrregular("was", "were");
|
|
54
|
+
this.addIrregular("has", "have");
|
|
54
55
|
|
|
55
56
|
this.singularForms.regularForms.push([/ed$/i, 'ed']);
|
|
56
57
|
this.singularForms.regularForms.push([/ss$/i, 'sses']);
|
|
@@ -77,8 +77,7 @@ TenseInflector.prototype.restoreCase = function(token) {
|
|
|
77
77
|
|
|
78
78
|
TenseInflector.prototype.izeRegulars = function(token, formSet) {
|
|
79
79
|
token = token.toLowerCase();
|
|
80
|
-
|
|
81
|
-
if(formSet.irregularForms[token])
|
|
80
|
+
if(formSet.irregularForms.hasOwnProperty(token) && formSet.irregularForms[token])
|
|
82
81
|
return formSet.irregularForms[token];
|
|
83
82
|
|
|
84
83
|
return false;
|