From cdb2d83e168b8602bcaa98b1a8f2842908eaad49 Mon Sep 17 00:00:00 2001 From: Matthew Honnibal Date: Thu, 28 Sep 2017 18:47:13 -0500 Subject: [PATCH 1/8] Pass dropout in parser --- spacy/syntax/nn_parser.pyx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spacy/syntax/nn_parser.pyx b/spacy/syntax/nn_parser.pyx index 7b45db0d8..1efdc4474 100644 --- a/spacy/syntax/nn_parser.pyx +++ b/spacy/syntax/nn_parser.pyx @@ -533,7 +533,7 @@ cdef class Parser: states, golds, max_steps = self._init_gold_batch(docs, golds) (tokvecs, bp_tokvecs), state2vec, vec2scores = self.get_batch_model(docs, cuda_stream, - 0.0) + drop) todo = [(s, g) for (s, g) in zip(states, golds) if not s.is_final() and g is not None] if not todo: @@ -598,7 +598,7 @@ cdef class Parser: self.moves.preprocess_gold(gold) cuda_stream = get_cuda_stream() - (tokvecs, bp_tokvecs), state2vec, vec2scores = self.get_batch_model(docs, cuda_stream, 0.0) + (tokvecs, bp_tokvecs), state2vec, vec2scores = self.get_batch_model(docs, cuda_stream, drop) states_d_scores, backprops = _beam_utils.update_beam(self.moves, self.nr_feature, 500, states, golds, @@ -685,7 +685,7 @@ cdef class Parser: tok2vec, lower, upper = self.model tokvecs, bp_tokvecs = tok2vec.begin_update(docs, drop=dropout) state2vec = precompute_hiddens(len(docs), tokvecs, - lower, stream, drop=dropout) + lower, stream, drop=0.0) return (tokvecs, bp_tokvecs), state2vec, upper nr_feature = 8 From 7d77dc490fb2f8cf5232690f3775e77cdadc59ee Mon Sep 17 00:00:00 2001 From: ines Date: Fri, 29 Sep 2017 20:52:28 +0200 Subject: [PATCH 2/8] Always compare lowercase package names Otherwise, is_package will return False if model name contains uppercase characters. See this issue: https://support.prodi.gy/t/saving-a-trained-ner-model-as-a-loadable-modu le/46/6 --- spacy/util.py | 4 +- website/usage/spacy-101.jade | 300 +++++++++++++++++++++++++++++++++++ 2 files changed, 303 insertions(+), 1 deletion(-) create mode 100644 website/usage/spacy-101.jade diff --git a/spacy/util.py b/spacy/util.py index 429d9bae5..911970831 100644 --- a/spacy/util.py +++ b/spacy/util.py @@ -181,9 +181,10 @@ def is_package(name): name (unicode): Name of package. RETURNS (bool): True if installed package, False if not. """ + name = name.lower() # compare package name against lowercase name packages = pkg_resources.working_set.by_key.keys() for package in packages: - if package.replace('-', '_') == name: + if package.lower().replace('-', '_') == name: return True return False @@ -194,6 +195,7 @@ def get_package_path(name): name (unicode): Package name. RETURNS (Path): Path to installed package. """ + name = name.lower() # use lowercase version to be safe # Here we're importing the module just to find it. This is worryingly # indirect, but it's otherwise very difficult to find the package. pkg = importlib.import_module(name) diff --git a/website/usage/spacy-101.jade b/website/usage/spacy-101.jade new file mode 100644 index 000000000..a57137674 --- /dev/null +++ b/website/usage/spacy-101.jade @@ -0,0 +1,300 @@ +//- 💫 DOCS > USAGE > SPACY 101 + +include ../_includes/_mixins + +p + | Whether you're new to spaCy, or just want to brush up on some + | NLP basics and implementation details – this page should have you covered. + | Each section will explain one of spaCy's features in simple terms and + | with examples or illustrations. Some sections will also reappear across + | the usage guides as a quick introduction. + ++aside("Help us improve the docs") + | Did you spot a mistake or come across explanations that + | are unclear? We always appreciate improvement + | #[+a(gh("spaCy") + "/issues") suggestions] or + | #[+a(gh("spaCy") + "/pulls") pull requests]. You can find a "Suggest + | edits" link at the bottom of each page that points you to the source. + ++h(2, "whats-spacy") What's spaCy? + ++grid.o-no-block + +grid-col("half") + p + | spaCy is a #[strong free, open-source library] for advanced + | #[strong Natural Language Processing] (NLP) in Python. + + p + | If you're working with a lot of text, you'll eventually want to + | know more about it. For example, what's it about? What do the + | words mean in context? Who is doing what to whom? What companies + | and products are mentioned? Which texts are similar to each other? + + p + | spaCy is designed specifically for #[strong production use] and + | helps you build applications that process and "understand" + | large volumes of text. It can be used to build + | #[strong information extraction] or + | #[strong natural language understanding] systems, or to + | pre-process text for #[strong deep learning]. + + +table-of-contents + +item #[+a("#features") Features] + +item #[+a("#annotations") Linguistic annotations] + +item #[+a("#annotations-token") Tokenization] + +item #[+a("#annotations-pos-deps") POS tags and dependencies] + +item #[+a("#annotations-ner") Named entities] + +item #[+a("#vectors-similarity") Word vectors and similarity] + +item #[+a("#pipelines") Pipelines] + +item #[+a("#vocab") Vocab, hashes and lexemes] + +item #[+a("#serialization") Serialization] + +item #[+a("#training") Training] + +item #[+a("#language-data") Language data] + +item #[+a("#lightning-tour") Lightning tour] + +item #[+a("#architecture") Architecture] + +item #[+a("#community") Community & FAQ] + ++h(3, "what-spacy-isnt") What spaCy isn't + ++list + +item #[strong spaCy is not a platform or "an API"]. + | Unlike a platform, spaCy does not provide a software as a service, or + | a web application. It's an open-source library designed to help you + | build NLP applications, not a consumable service. + +item #[strong spaCy is not an out-of-the-box chat bot engine]. + | While spaCy can be used to power conversational applications, it's + | not designed specifically for chat bots, and only provides the + | underlying text processing capabilities. + +item #[strong spaCy is not research software]. + | It's built on the latest research, but it's designed to get + | things done. This leads to fairly different design decisions than + | #[+a("https://github./nltk/nltk") NLTK] + | or #[+a("https://stanfordnlp.github.io/CoreNLP/") CoreNLP], which were + | created as platforms for teaching and research. The main difference + | is that spaCy is integrated and opinionated. spaCy tries to avoid asking + | the user to choose between multiple algorithms that deliver equivalent + | functionality. Keeping the menu small lets spaCy deliver generally better + | performance and developer experience. + +item #[strong spaCy is not a company]. + | It's an open-source library. Our company publishing spaCy and other + | software is called #[+a(COMPANY_URL, true) Explosion AI]. + ++section("features") + +h(2, "features") Features + + p + | In the documentation, you'll come across mentions of spaCy's + | features and capabilities. Some of them refer to linguistic concepts, + | while others are related to more general machine learning + | functionality. + + +aside + | If one of spaCy's functionalities #[strong needs a model], it means + | that you need to have one of the available + | #[+a("/models") statistical models] installed. Models are used + | to #[strong predict] linguistic annotations – for example, if a word + | is a verb or a noun. + + +table(["Name", "Description", "Needs model"]) + +row + +cell #[strong Tokenization] + +cell Segmenting text into words, punctuations marks etc. + +cell #[+procon("con")] + + +row + +cell #[strong Part-of-speech] (POS) #[strong Tagging] + +cell Assigning word types to tokens, like verb or noun. + +cell #[+procon("pro")] + + +row + +cell #[strong Dependency Parsing] + +cell + | Assigning syntactic dependency labels, describing the + | relations between individual tokens, like subject or object. + +cell #[+procon("pro")] + + +row + +cell #[strong Lemmatization] + +cell + | Assigning the base forms of words. For example, the lemma of + | "was" is "be", and the lemma of "rats" is "rat". + +cell #[+procon("pro")] + + +row + +cell #[strong Sentence Boundary Detection] (SBD) + +cell Finding and segmenting individual sentences. + +cell #[+procon("pro")] + + +row + +cell #[strong Named Entity Recongition] (NER) + +cell + | Labelling named "real-world" objects, like persons, companies + | or locations. + +cell #[+procon("pro")] + + +row + +cell #[strong Similarity] + +cell + | Comparing words, text spans and documents and how similar + | they are to each other. + +cell #[+procon("pro")] + + +row + +cell #[strong Text Classification] + +cell + | Assigning categories or labels to a whole document, or parts + | of a document. + +cell #[+procon("pro")] + + +row + +cell #[strong Rule-based Matching] + +cell + | Finding sequences of tokens based on their texts and + | linguistic annotations, similar to regular expressions. + +cell #[+procon("con")] + + +row + +cell #[strong Training] + +cell Updating and improving a statistical model's predictions. + +cell #[+procon("neutral")] + + +row + +cell #[strong Serialization] + +cell Saving objects to files or byte strings. + +cell #[+procon("neutral")] + + +h(2, "annotations") Linguistic annotations + + p + | spaCy provides a variety of linguistic annotations to give you + | #[strong insights into a text's grammatical structure]. This + | includes the word types, like the parts of speech, and how the words + | are related to each other. For example, if you're analysing text, it + | makes a huge difference whether a noun is the subject of a sentence, + | or the object – or whether "google" is used as a verb, or refers to + | the website or company in a specific context. + + p + | Once you've downloaded and installed a #[+a("/usage/models") model], + | you can load it via #[+api("spacy#load") #[code spacy.load()]]. This will + | return a #[code Language] object contaning all components and data needed + | to process text. We usually call it #[code nlp]. Calling the #[code nlp] + | object on a string of text will return a processed #[code Doc]: + + +code. + import spacy + + nlp = spacy.load('en') + doc = nlp(u'Apple is looking at buying U.K. startup for $1 billion') + + p + | Even though a #[code Doc] is processed – e.g. split into individual words + | and annotated – it still holds #[strong all information of the original text], + | like whitespace characters. You can always get the offset of a token into the + | original string, or reconstruct the original by joining the tokens and their + | trailing whitespace. This way, you'll never lose any information + | when processing text with spaCy. + + +h(3, "annotations-token") Tokenization + + include _spacy-101/_tokenization + + +infobox + | To learn more about how spaCy's tokenization rules work in detail, + | how to #[strong customise and replace] the default tokenizer and how to + | #[strong add language-specific data], see the usage guides on + | #[+a("/usage/adding-languages") adding languages] and + | #[+a("/usage/linguistic-features#tokenization") customising the tokenizer]. + + +h(3, "annotations-pos-deps") Part-of-speech tags and dependencies + +tag-model("dependency parse") + + include _spacy-101/_pos-deps + + +infobox + | To learn more about #[strong part-of-speech tagging] and rule-based + | morphology, and how to #[strong navigate and use the parse tree] + | effectively, see the usage guides on + | #[+a("/usage/linguistic-features#pos-tagging") part-of-speech tagging] and + | #[+a("/usage/linguistic-features#dependency-parse") using the dependency parse]. + + +h(3, "annotations-ner") Named Entities + +tag-model("named entities") + + include _spacy-101/_named-entities + + +infobox + | To learn more about entity recognition in spaCy, how to + | #[strong add your own entities] to a document and how to + | #[strong train and update] the entity predictions of a model, see the + | usage guides on + | #[+a("/usage/linguistic-features#named-entities") named entity recognition] and + | #[+a("/usage/training#ner") training the named entity recognizer]. + + +h(2, "vectors-similarity") Word vectors and similarity + +tag-model("vectors") + + include _spacy-101/_similarity + + include _spacy-101/_word-vectors + + +infobox + | To learn more about word vectors, how to #[strong customise them] and + | how to load #[strong your own vectors] into spaCy, see the usage + | guide on + | #[+a("/usage/word-vectors-similarities") using word vectors and semantic similarities]. + + +h(2, "pipelines") Pipelines + + include _spacy-101/_pipelines + + +infobox + | To learn more about #[strong how processing pipelines work] in detail, + | how to enable and disable their components, and how to + | #[strong create your own], see the usage guide on + | #[+a("/usage/processing-pipelines") language processing pipelines]. + + +h(2, "vocab") Vocab, hashes and lexemes + + include _spacy-101/_vocab + + +h(2, "serialization") Serialization + + include _spacy-101/_serialization + + +infobox + | To learn more about how to #[strong save and load your own models], + | see the usage guide on + | #[+a("/usage/training#saving-loading") saving and loading]. + + +h(2, "training") Training + + include _spacy-101/_training + + +infobox + | To learn more about #[strong training and updating] models, how to create + | training data and how to improve spaCy's named entity recognition models, + | see the usage guides on #[+a("/usage/training") training]. + + +h(2, "language-data") Language data + + include _spacy-101/_language-data + + +infobox + | To learn more about the individual components of the language data and + | how to #[strong add a new language] to spaCy in preparation for training + | a language model, see the usage guide on + | #[+a("/usage/adding-languages") adding languages]. + + ++section("lightning-tour") + +h(2, "lightning-tour") Lightning tour + include _spacy-101/_lightning-tour + ++section("architecture") + +h(2, "architecture") Architecture + include _spacy-101/_architecture + ++section("community-faq") + +h(2, "community") Community & FAQ + include _spacy-101/_community-faq From fd1a9225d80a667bfd88c5d21bdaeaf156003cf2 Mon Sep 17 00:00:00 2001 From: ines Date: Fri, 29 Sep 2017 20:52:56 +0200 Subject: [PATCH 3/8] Handle conversion of pipeline components correctly Allow both comma and comma + whitespace as separators --- spacy/cli/package.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/spacy/cli/package.py b/spacy/cli/package.py index 7019819a7..5ffc493c3 100644 --- a/spacy/cli/package.py +++ b/spacy/cli/package.py @@ -105,8 +105,11 @@ def generate_pipeline(): "parser, ner. For more information, see the docs on processing pipelines.", title="Enter your model's pipeline components") pipeline = util.get_raw_input("Pipeline components", True) - replace = {'True': True, 'False': False} - return replace[pipeline] if pipeline in replace else pipeline.split(', ') + subs = {'True': True, 'False': False} + if pipeline in subs: + return subs[pipeline] + else: + return [p.strip() for p in pipeline.split(',')] def validate_meta(meta, keys): From 153c2589d40a7dd127864b0e68efe20182d0941e Mon Sep 17 00:00:00 2001 From: ines Date: Fri, 29 Sep 2017 20:53:36 +0200 Subject: [PATCH 4/8] Revert "Always compare lowercase package names" This reverts commit 7d77dc490fb2f8cf5232690f3775e77cdadc59ee. --- spacy/util.py | 4 +- website/usage/spacy-101.jade | 300 ----------------------------------- 2 files changed, 1 insertion(+), 303 deletions(-) delete mode 100644 website/usage/spacy-101.jade diff --git a/spacy/util.py b/spacy/util.py index 911970831..429d9bae5 100644 --- a/spacy/util.py +++ b/spacy/util.py @@ -181,10 +181,9 @@ def is_package(name): name (unicode): Name of package. RETURNS (bool): True if installed package, False if not. """ - name = name.lower() # compare package name against lowercase name packages = pkg_resources.working_set.by_key.keys() for package in packages: - if package.lower().replace('-', '_') == name: + if package.replace('-', '_') == name: return True return False @@ -195,7 +194,6 @@ def get_package_path(name): name (unicode): Package name. RETURNS (Path): Path to installed package. """ - name = name.lower() # use lowercase version to be safe # Here we're importing the module just to find it. This is worryingly # indirect, but it's otherwise very difficult to find the package. pkg = importlib.import_module(name) diff --git a/website/usage/spacy-101.jade b/website/usage/spacy-101.jade deleted file mode 100644 index a57137674..000000000 --- a/website/usage/spacy-101.jade +++ /dev/null @@ -1,300 +0,0 @@ -//- 💫 DOCS > USAGE > SPACY 101 - -include ../_includes/_mixins - -p - | Whether you're new to spaCy, or just want to brush up on some - | NLP basics and implementation details – this page should have you covered. - | Each section will explain one of spaCy's features in simple terms and - | with examples or illustrations. Some sections will also reappear across - | the usage guides as a quick introduction. - -+aside("Help us improve the docs") - | Did you spot a mistake or come across explanations that - | are unclear? We always appreciate improvement - | #[+a(gh("spaCy") + "/issues") suggestions] or - | #[+a(gh("spaCy") + "/pulls") pull requests]. You can find a "Suggest - | edits" link at the bottom of each page that points you to the source. - -+h(2, "whats-spacy") What's spaCy? - -+grid.o-no-block - +grid-col("half") - p - | spaCy is a #[strong free, open-source library] for advanced - | #[strong Natural Language Processing] (NLP) in Python. - - p - | If you're working with a lot of text, you'll eventually want to - | know more about it. For example, what's it about? What do the - | words mean in context? Who is doing what to whom? What companies - | and products are mentioned? Which texts are similar to each other? - - p - | spaCy is designed specifically for #[strong production use] and - | helps you build applications that process and "understand" - | large volumes of text. It can be used to build - | #[strong information extraction] or - | #[strong natural language understanding] systems, or to - | pre-process text for #[strong deep learning]. - - +table-of-contents - +item #[+a("#features") Features] - +item #[+a("#annotations") Linguistic annotations] - +item #[+a("#annotations-token") Tokenization] - +item #[+a("#annotations-pos-deps") POS tags and dependencies] - +item #[+a("#annotations-ner") Named entities] - +item #[+a("#vectors-similarity") Word vectors and similarity] - +item #[+a("#pipelines") Pipelines] - +item #[+a("#vocab") Vocab, hashes and lexemes] - +item #[+a("#serialization") Serialization] - +item #[+a("#training") Training] - +item #[+a("#language-data") Language data] - +item #[+a("#lightning-tour") Lightning tour] - +item #[+a("#architecture") Architecture] - +item #[+a("#community") Community & FAQ] - -+h(3, "what-spacy-isnt") What spaCy isn't - -+list - +item #[strong spaCy is not a platform or "an API"]. - | Unlike a platform, spaCy does not provide a software as a service, or - | a web application. It's an open-source library designed to help you - | build NLP applications, not a consumable service. - +item #[strong spaCy is not an out-of-the-box chat bot engine]. - | While spaCy can be used to power conversational applications, it's - | not designed specifically for chat bots, and only provides the - | underlying text processing capabilities. - +item #[strong spaCy is not research software]. - | It's built on the latest research, but it's designed to get - | things done. This leads to fairly different design decisions than - | #[+a("https://github./nltk/nltk") NLTK] - | or #[+a("https://stanfordnlp.github.io/CoreNLP/") CoreNLP], which were - | created as platforms for teaching and research. The main difference - | is that spaCy is integrated and opinionated. spaCy tries to avoid asking - | the user to choose between multiple algorithms that deliver equivalent - | functionality. Keeping the menu small lets spaCy deliver generally better - | performance and developer experience. - +item #[strong spaCy is not a company]. - | It's an open-source library. Our company publishing spaCy and other - | software is called #[+a(COMPANY_URL, true) Explosion AI]. - -+section("features") - +h(2, "features") Features - - p - | In the documentation, you'll come across mentions of spaCy's - | features and capabilities. Some of them refer to linguistic concepts, - | while others are related to more general machine learning - | functionality. - - +aside - | If one of spaCy's functionalities #[strong needs a model], it means - | that you need to have one of the available - | #[+a("/models") statistical models] installed. Models are used - | to #[strong predict] linguistic annotations – for example, if a word - | is a verb or a noun. - - +table(["Name", "Description", "Needs model"]) - +row - +cell #[strong Tokenization] - +cell Segmenting text into words, punctuations marks etc. - +cell #[+procon("con")] - - +row - +cell #[strong Part-of-speech] (POS) #[strong Tagging] - +cell Assigning word types to tokens, like verb or noun. - +cell #[+procon("pro")] - - +row - +cell #[strong Dependency Parsing] - +cell - | Assigning syntactic dependency labels, describing the - | relations between individual tokens, like subject or object. - +cell #[+procon("pro")] - - +row - +cell #[strong Lemmatization] - +cell - | Assigning the base forms of words. For example, the lemma of - | "was" is "be", and the lemma of "rats" is "rat". - +cell #[+procon("pro")] - - +row - +cell #[strong Sentence Boundary Detection] (SBD) - +cell Finding and segmenting individual sentences. - +cell #[+procon("pro")] - - +row - +cell #[strong Named Entity Recongition] (NER) - +cell - | Labelling named "real-world" objects, like persons, companies - | or locations. - +cell #[+procon("pro")] - - +row - +cell #[strong Similarity] - +cell - | Comparing words, text spans and documents and how similar - | they are to each other. - +cell #[+procon("pro")] - - +row - +cell #[strong Text Classification] - +cell - | Assigning categories or labels to a whole document, or parts - | of a document. - +cell #[+procon("pro")] - - +row - +cell #[strong Rule-based Matching] - +cell - | Finding sequences of tokens based on their texts and - | linguistic annotations, similar to regular expressions. - +cell #[+procon("con")] - - +row - +cell #[strong Training] - +cell Updating and improving a statistical model's predictions. - +cell #[+procon("neutral")] - - +row - +cell #[strong Serialization] - +cell Saving objects to files or byte strings. - +cell #[+procon("neutral")] - - +h(2, "annotations") Linguistic annotations - - p - | spaCy provides a variety of linguistic annotations to give you - | #[strong insights into a text's grammatical structure]. This - | includes the word types, like the parts of speech, and how the words - | are related to each other. For example, if you're analysing text, it - | makes a huge difference whether a noun is the subject of a sentence, - | or the object – or whether "google" is used as a verb, or refers to - | the website or company in a specific context. - - p - | Once you've downloaded and installed a #[+a("/usage/models") model], - | you can load it via #[+api("spacy#load") #[code spacy.load()]]. This will - | return a #[code Language] object contaning all components and data needed - | to process text. We usually call it #[code nlp]. Calling the #[code nlp] - | object on a string of text will return a processed #[code Doc]: - - +code. - import spacy - - nlp = spacy.load('en') - doc = nlp(u'Apple is looking at buying U.K. startup for $1 billion') - - p - | Even though a #[code Doc] is processed – e.g. split into individual words - | and annotated – it still holds #[strong all information of the original text], - | like whitespace characters. You can always get the offset of a token into the - | original string, or reconstruct the original by joining the tokens and their - | trailing whitespace. This way, you'll never lose any information - | when processing text with spaCy. - - +h(3, "annotations-token") Tokenization - - include _spacy-101/_tokenization - - +infobox - | To learn more about how spaCy's tokenization rules work in detail, - | how to #[strong customise and replace] the default tokenizer and how to - | #[strong add language-specific data], see the usage guides on - | #[+a("/usage/adding-languages") adding languages] and - | #[+a("/usage/linguistic-features#tokenization") customising the tokenizer]. - - +h(3, "annotations-pos-deps") Part-of-speech tags and dependencies - +tag-model("dependency parse") - - include _spacy-101/_pos-deps - - +infobox - | To learn more about #[strong part-of-speech tagging] and rule-based - | morphology, and how to #[strong navigate and use the parse tree] - | effectively, see the usage guides on - | #[+a("/usage/linguistic-features#pos-tagging") part-of-speech tagging] and - | #[+a("/usage/linguistic-features#dependency-parse") using the dependency parse]. - - +h(3, "annotations-ner") Named Entities - +tag-model("named entities") - - include _spacy-101/_named-entities - - +infobox - | To learn more about entity recognition in spaCy, how to - | #[strong add your own entities] to a document and how to - | #[strong train and update] the entity predictions of a model, see the - | usage guides on - | #[+a("/usage/linguistic-features#named-entities") named entity recognition] and - | #[+a("/usage/training#ner") training the named entity recognizer]. - - +h(2, "vectors-similarity") Word vectors and similarity - +tag-model("vectors") - - include _spacy-101/_similarity - - include _spacy-101/_word-vectors - - +infobox - | To learn more about word vectors, how to #[strong customise them] and - | how to load #[strong your own vectors] into spaCy, see the usage - | guide on - | #[+a("/usage/word-vectors-similarities") using word vectors and semantic similarities]. - - +h(2, "pipelines") Pipelines - - include _spacy-101/_pipelines - - +infobox - | To learn more about #[strong how processing pipelines work] in detail, - | how to enable and disable their components, and how to - | #[strong create your own], see the usage guide on - | #[+a("/usage/processing-pipelines") language processing pipelines]. - - +h(2, "vocab") Vocab, hashes and lexemes - - include _spacy-101/_vocab - - +h(2, "serialization") Serialization - - include _spacy-101/_serialization - - +infobox - | To learn more about how to #[strong save and load your own models], - | see the usage guide on - | #[+a("/usage/training#saving-loading") saving and loading]. - - +h(2, "training") Training - - include _spacy-101/_training - - +infobox - | To learn more about #[strong training and updating] models, how to create - | training data and how to improve spaCy's named entity recognition models, - | see the usage guides on #[+a("/usage/training") training]. - - +h(2, "language-data") Language data - - include _spacy-101/_language-data - - +infobox - | To learn more about the individual components of the language data and - | how to #[strong add a new language] to spaCy in preparation for training - | a language model, see the usage guide on - | #[+a("/usage/adding-languages") adding languages]. - - -+section("lightning-tour") - +h(2, "lightning-tour") Lightning tour - include _spacy-101/_lightning-tour - -+section("architecture") - +h(2, "architecture") Architecture - include _spacy-101/_architecture - -+section("community-faq") - +h(2, "community") Community & FAQ - include _spacy-101/_community-faq From 8dbe49ecb8cfe2edd932a10d418e4be5466700ba Mon Sep 17 00:00:00 2001 From: ines Date: Fri, 29 Sep 2017 20:55:17 +0200 Subject: [PATCH 5/8] Always compare lowercase package names Otherwise, is_package will return False if model name contains uppercase characters. See this issue: https://support.prodi.gy/t/saving-a-trained-ner-model-as-a-loadable-modu le/46/6 --- spacy/util.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/spacy/util.py b/spacy/util.py index 429d9bae5..911970831 100644 --- a/spacy/util.py +++ b/spacy/util.py @@ -181,9 +181,10 @@ def is_package(name): name (unicode): Name of package. RETURNS (bool): True if installed package, False if not. """ + name = name.lower() # compare package name against lowercase name packages = pkg_resources.working_set.by_key.keys() for package in packages: - if package.replace('-', '_') == name: + if package.lower().replace('-', '_') == name: return True return False @@ -194,6 +195,7 @@ def get_package_path(name): name (unicode): Package name. RETURNS (Path): Path to installed package. """ + name = name.lower() # use lowercase version to be safe # Here we're importing the module just to find it. This is worryingly # indirect, but it's otherwise very difficult to find the package. pkg = importlib.import_module(name) From 69c7c642c2c3a9c51d0b7c1c1e5e67848f9b7953 Mon Sep 17 00:00:00 2001 From: Matthew Honnibal Date: Sun, 1 Oct 2017 14:04:32 -0500 Subject: [PATCH 6/8] Add spacy evaluate --- spacy/__main__.py | 3 +- spacy/cli/__init__.py | 1 + spacy/cli/evaluate.py | 93 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 spacy/cli/evaluate.py diff --git a/spacy/__main__.py b/spacy/__main__.py index d02242d68..0ec96e4a1 100644 --- a/spacy/__main__.py +++ b/spacy/__main__.py @@ -7,7 +7,7 @@ if __name__ == '__main__': import plac import sys from spacy.cli import download, link, info, package, train, convert, model - from spacy.cli import profile + from spacy.cli import profile, evaluate from spacy.util import prints commands = { @@ -15,6 +15,7 @@ if __name__ == '__main__': 'link': link, 'info': info, 'train': train, + 'evaluate': evaluate, 'convert': convert, 'package': package, 'model': model, diff --git a/spacy/cli/__init__.py b/spacy/cli/__init__.py index e58c94642..ebe185f24 100644 --- a/spacy/cli/__init__.py +++ b/spacy/cli/__init__.py @@ -4,5 +4,6 @@ from .link import link from .package import package from .profile import profile from .train import train +from .evaluate import evaluate from .convert import convert from .model import model diff --git a/spacy/cli/evaluate.py b/spacy/cli/evaluate.py new file mode 100644 index 000000000..209660529 --- /dev/null +++ b/spacy/cli/evaluate.py @@ -0,0 +1,93 @@ +# coding: utf8 +from __future__ import unicode_literals, division, print_function + +import plac +import json +from collections import defaultdict +import cytoolz +from pathlib import Path +import dill +import tqdm +from thinc.neural._classes.model import Model +from thinc.neural.optimizers import linear_decay +from timeit import default_timer as timer +import random +import numpy.random + +from ..tokens.doc import Doc +from ..scorer import Scorer +from ..gold import GoldParse, merge_sents +from ..gold import GoldCorpus, minibatch +from ..util import prints +from .. import util +from .. import about +from .. import displacy +from ..compat import json_dumps + +random.seed(0) +numpy.random.seed(0) + + +@plac.annotations( + model=("Model name or path", "positional", None, str), + data_path=("Location of JSON-formatted evaluation data", "positional", None, str), + gold_preproc=("Use gold preprocessing", "flag", "G", bool), +) +def evaluate(cmd, model, data_path, gold_preproc=False): + """ + Train a model. Expects data in spaCy's JSON format. + """ + util.set_env_log(True) + data_path = util.ensure_path(data_path) + if not data_path.exists(): + prints(data_path, title="Evaluation data not found", exits=1) + corpus = GoldCorpus(data_path, data_path) + nlp = util.load_model(model) + scorer = nlp.evaluate(list(corpus.dev_docs(nlp, gold_preproc=gold_preproc))) + print_results(scorer) + + +def _render_parses(i, to_render): + to_render[0].user_data['title'] = "Batch %d" % i + with Path('/tmp/entities.html').open('w') as file_: + html = displacy.render(to_render[:5], style='ent', page=True) + file_.write(html) + with Path('/tmp/parses.html').open('w') as file_: + html = displacy.render(to_render[:5], style='dep', page=True) + file_.write(html) + + +def print_progress(itn, losses, dev_scores, wps=0.0): + scores = {} + for col in ['dep_loss', 'tag_loss', 'uas', 'tags_acc', 'token_acc', + 'ents_p', 'ents_r', 'ents_f', 'wps']: + scores[col] = 0.0 + scores['dep_loss'] = losses.get('parser', 0.0) + scores['ner_loss'] = losses.get('ner', 0.0) + scores['tag_loss'] = losses.get('tagger', 0.0) + scores.update(dev_scores) + scores['wps'] = wps + tpl = '\t'.join(( + '{:d}', + '{dep_loss:.3f}', + '{ner_loss:.3f}', + '{uas:.3f}', + '{ents_p:.3f}', + '{ents_r:.3f}', + '{ents_f:.3f}', + '{tags_acc:.3f}', + '{token_acc:.3f}', + '{wps:.1f}')) + print(tpl.format(itn, **scores)) + + +def print_results(scorer): + results = { + 'TOK': '%.2f' % scorer.token_acc, + 'POS': '%.2f' % scorer.tags_acc, + 'UAS': '%.2f' % scorer.uas, + 'LAS': '%.2f' % scorer.las, + 'NER P': '%.2f' % scorer.ents_p, + 'NER R': '%.2f' % scorer.ents_r, + 'NER F': '%.2f' % scorer.ents_f} + util.print_table(results, title="Results") From 2cf0f4622fb5efc57c622b5d37c771e8042bed3d Mon Sep 17 00:00:00 2001 From: Matthew Honnibal Date: Sun, 1 Oct 2017 14:05:32 -0500 Subject: [PATCH 7/8] Fix loading of models with pre-trained vectors --- spacy/vocab.pyx | 1 + 1 file changed, 1 insertion(+) diff --git a/spacy/vocab.pyx b/spacy/vocab.pyx index 0a420849c..21c2a1165 100644 --- a/spacy/vocab.pyx +++ b/spacy/vocab.pyx @@ -324,6 +324,7 @@ cdef class Vocab: self.lexemes_from_bytes(file_.read()) if self.vectors is not None: self.vectors.from_disk(path, exclude='strings.json') + link_vectors_to_models(self) return self def to_bytes(self, **exclude): From b776f48e58586ee27d27cf8a1a8e316b8c73c42c Mon Sep 17 00:00:00 2001 From: ines Date: Sun, 1 Oct 2017 21:58:45 +0200 Subject: [PATCH 8/8] Fix typo --- spacy/vocab.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spacy/vocab.pyx b/spacy/vocab.pyx index 21c2a1165..a5f8bf6ad 100644 --- a/spacy/vocab.pyx +++ b/spacy/vocab.pyx @@ -262,7 +262,7 @@ cdef class Vocab: Words can be looked up by string or int ID. RETURNS: - A word vector. Size and shape determed by the + A word vector. Size and shape determined by the vocab.vectors instance. Usually, a numpy ndarray of shape (300,) and dtype float32.