mirror of
https://github.com/explosion/spaCy.git
synced 2024-12-25 17:36:30 +03:00
Update docs and formatting
This commit is contained in:
parent
aa27e3f1f2
commit
2e567a47c2
|
@ -293,7 +293,11 @@ context, the original parameters are restored.
|
||||||
|
|
||||||
## DependencyParser.add_label {#add_label tag="method"}
|
## DependencyParser.add_label {#add_label tag="method"}
|
||||||
|
|
||||||
Add a new label to the pipe.
|
Add a new label to the pipe. Note that you don't have to call this method if you
|
||||||
|
provide a **representative data sample** to the
|
||||||
|
[`begin_training`](#begin_training) method. In this case, all labels found in
|
||||||
|
the sample will be automatically added to the model, and the output dimension
|
||||||
|
will be [inferred](/usage/layers-architectures#shape-inference) automatically.
|
||||||
|
|
||||||
> #### Example
|
> #### Example
|
||||||
>
|
>
|
||||||
|
@ -307,17 +311,13 @@ Add a new label to the pipe.
|
||||||
| `label` | The label to add. ~~str~~ |
|
| `label` | The label to add. ~~str~~ |
|
||||||
| **RETURNS** | `0` if the label is already present, otherwise `1`. ~~int~~ |
|
| **RETURNS** | `0` if the label is already present, otherwise `1`. ~~int~~ |
|
||||||
|
|
||||||
Note that you don't have to call `pipe.add_label` if you provide a
|
|
||||||
representative data sample to the [`begin_training`](#begin_training) method. In
|
|
||||||
this case, all labels found in the sample will be automatically added to the
|
|
||||||
model, and the output dimension will be
|
|
||||||
[inferred](/usage/layers-architectures#shape-inference) automatically.
|
|
||||||
|
|
||||||
## DependencyParser.set_output {#set_output tag="method"}
|
## DependencyParser.set_output {#set_output tag="method"}
|
||||||
|
|
||||||
Change the output dimension of the component's model by calling the model's
|
Change the output dimension of the component's model by calling the model's
|
||||||
attribute `resize_output`. This is a function that takes the original model and
|
attribute `resize_output`. This is a function that takes the original model and
|
||||||
the new output dimension `nO`, and changes the model in place.
|
the new output dimension `nO`, and changes the model in place. When resizing an
|
||||||
|
already trained model, care should be taken to avoid the "catastrophic
|
||||||
|
forgetting" problem.
|
||||||
|
|
||||||
> #### Example
|
> #### Example
|
||||||
>
|
>
|
||||||
|
@ -330,9 +330,6 @@ the new output dimension `nO`, and changes the model in place.
|
||||||
| ---- | --------------------------------- |
|
| ---- | --------------------------------- |
|
||||||
| `nO` | The new output dimension. ~~int~~ |
|
| `nO` | The new output dimension. ~~int~~ |
|
||||||
|
|
||||||
When resizing an already trained model, care should be taken to avoid the
|
|
||||||
"catastrophic forgetting" problem.
|
|
||||||
|
|
||||||
## DependencyParser.to_disk {#to_disk tag="method"}
|
## DependencyParser.to_disk {#to_disk tag="method"}
|
||||||
|
|
||||||
Serialize the pipe to disk.
|
Serialize the pipe to disk.
|
||||||
|
|
|
@ -281,7 +281,11 @@ context, the original parameters are restored.
|
||||||
|
|
||||||
## EntityRecognizer.add_label {#add_label tag="method"}
|
## EntityRecognizer.add_label {#add_label tag="method"}
|
||||||
|
|
||||||
Add a new label to the pipe.
|
Add a new label to the pipe. Note that you don't have to call this method if you
|
||||||
|
provide a **representative data sample** to the
|
||||||
|
[`begin_training`](#begin_training) method. In this case, all labels found in
|
||||||
|
the sample will be automatically added to the model, and the output dimension
|
||||||
|
will be [inferred](/usage/layers-architectures#shape-inference) automatically.
|
||||||
|
|
||||||
> #### Example
|
> #### Example
|
||||||
>
|
>
|
||||||
|
@ -295,17 +299,13 @@ Add a new label to the pipe.
|
||||||
| `label` | The label to add. ~~str~~ |
|
| `label` | The label to add. ~~str~~ |
|
||||||
| **RETURNS** | `0` if the label is already present, otherwise `1`. ~~int~~ |
|
| **RETURNS** | `0` if the label is already present, otherwise `1`. ~~int~~ |
|
||||||
|
|
||||||
Note that you don't have to call `pipe.add_label` if you provide a
|
|
||||||
representative data sample to the [`begin_training`](#begin_training) method. In
|
|
||||||
this case, all labels found in the sample will be automatically added to the
|
|
||||||
model, and the output dimension will be
|
|
||||||
[inferred](/usage/layers-architectures#shape-inference) automatically.
|
|
||||||
|
|
||||||
## EntityRecognizer.set_output {#set_output tag="method"}
|
## EntityRecognizer.set_output {#set_output tag="method"}
|
||||||
|
|
||||||
Change the output dimension of the component's model by calling the model's
|
Change the output dimension of the component's model by calling the model's
|
||||||
attribute `resize_output`. This is a function that takes the original model and
|
attribute `resize_output`. This is a function that takes the original model and
|
||||||
the new output dimension `nO`, and changes the model in place.
|
the new output dimension `nO`, and changes the model in place. When resizing an
|
||||||
|
already trained model, care should be taken to avoid the "catastrophic
|
||||||
|
forgetting" problem.
|
||||||
|
|
||||||
> #### Example
|
> #### Example
|
||||||
>
|
>
|
||||||
|
@ -318,9 +318,6 @@ the new output dimension `nO`, and changes the model in place.
|
||||||
| ---- | --------------------------------- |
|
| ---- | --------------------------------- |
|
||||||
| `nO` | The new output dimension. ~~int~~ |
|
| `nO` | The new output dimension. ~~int~~ |
|
||||||
|
|
||||||
When resizing an already trained model, care should be taken to avoid the
|
|
||||||
"catastrophic forgetting" problem.
|
|
||||||
|
|
||||||
## EntityRecognizer.to_disk {#to_disk tag="method"}
|
## EntityRecognizer.to_disk {#to_disk tag="method"}
|
||||||
|
|
||||||
Serialize the pipe to disk.
|
Serialize the pipe to disk.
|
||||||
|
|
|
@ -259,7 +259,11 @@ context, the original parameters are restored.
|
||||||
Add a new label to the pipe. If the `Morphologizer` should set annotations for
|
Add a new label to the pipe. If the `Morphologizer` should set annotations for
|
||||||
both `pos` and `morph`, the label should include the UPOS as the feature `POS`.
|
both `pos` and `morph`, the label should include the UPOS as the feature `POS`.
|
||||||
Raises an error if the output dimension is already set, or if the model has
|
Raises an error if the output dimension is already set, or if the model has
|
||||||
already been fully [initialized](#begin_training).
|
already been fully [initialized](#begin_training). Note that you don't have to
|
||||||
|
call this method if you provide a **representative data sample** to the
|
||||||
|
[`begin_training`](#begin_training) method. In this case, all labels found in
|
||||||
|
the sample will be automatically added to the model, and the output dimension
|
||||||
|
will be [inferred](/usage/layers-architectures#shape-inference) automatically.
|
||||||
|
|
||||||
> #### Example
|
> #### Example
|
||||||
>
|
>
|
||||||
|
@ -273,12 +277,6 @@ already been fully [initialized](#begin_training).
|
||||||
| `label` | The label to add. ~~str~~ |
|
| `label` | The label to add. ~~str~~ |
|
||||||
| **RETURNS** | `0` if the label is already present, otherwise `1`. ~~int~~ |
|
| **RETURNS** | `0` if the label is already present, otherwise `1`. ~~int~~ |
|
||||||
|
|
||||||
Note that you don't have to call `pipe.add_label` if you provide a
|
|
||||||
representative data sample to the [`begin_training`](#begin_training) method. In
|
|
||||||
this case, all labels found in the sample will be automatically added to the
|
|
||||||
model, and the output dimension will be
|
|
||||||
[inferred](/usage/layers-architectures#shape-inference) automatically.
|
|
||||||
|
|
||||||
## Morphologizer.to_disk {#to_disk tag="method"}
|
## Morphologizer.to_disk {#to_disk tag="method"}
|
||||||
|
|
||||||
Serialize the pipe to disk.
|
Serialize the pipe to disk.
|
||||||
|
|
|
@ -293,12 +293,6 @@ context, the original parameters are restored.
|
||||||
> pipe.add_label("MY_LABEL")
|
> pipe.add_label("MY_LABEL")
|
||||||
> ```
|
> ```
|
||||||
|
|
||||||
<Infobox variant="danger">
|
|
||||||
|
|
||||||
This method needs to be overwritten with your own custom `add_label` method.
|
|
||||||
|
|
||||||
</Infobox>
|
|
||||||
|
|
||||||
Add a new label to the pipe, to be predicted by the model. The actual
|
Add a new label to the pipe, to be predicted by the model. The actual
|
||||||
implementation depends on the specific component, but in general `add_label`
|
implementation depends on the specific component, but in general `add_label`
|
||||||
shouldn't be called if the output dimension is already set, or if the model has
|
shouldn't be called if the output dimension is already set, or if the model has
|
||||||
|
@ -308,6 +302,12 @@ the component is [resizable](#is_resizable), in which case
|
||||||
[`set_output`](#set_output) should be called to ensure that the model is
|
[`set_output`](#set_output) should be called to ensure that the model is
|
||||||
properly resized.
|
properly resized.
|
||||||
|
|
||||||
|
<Infobox variant="danger">
|
||||||
|
|
||||||
|
This method needs to be overwritten with your own custom `add_label` method.
|
||||||
|
|
||||||
|
</Infobox>
|
||||||
|
|
||||||
| Name | Description |
|
| Name | Description |
|
||||||
| ----------- | ------------------------------------------------------- |
|
| ----------- | ------------------------------------------------------- |
|
||||||
| `label` | The label to add. ~~str~~ |
|
| `label` | The label to add. ~~str~~ |
|
||||||
|
@ -326,41 +326,37 @@ model, and the output dimension will be
|
||||||
> ```python
|
> ```python
|
||||||
> can_resize = pipe.is_resizable()
|
> can_resize = pipe.is_resizable()
|
||||||
> ```
|
> ```
|
||||||
|
>
|
||||||
|
> ```python
|
||||||
|
> ### Custom resizing
|
||||||
|
> def custom_resize(model, new_nO):
|
||||||
|
> # adjust model
|
||||||
|
> return model
|
||||||
|
>
|
||||||
|
> custom_model.attrs["resize_output"] = custom_resize
|
||||||
|
> ```
|
||||||
|
|
||||||
Check whether or not the output dimension of the component's model can be
|
Check whether or not the output dimension of the component's model can be
|
||||||
resized. If this method returns `True`, [`set_output`](#set_output) can be
|
resized. If this method returns `True`, [`set_output`](#set_output) can be
|
||||||
called to change the model's output dimension.
|
called to change the model's output dimension.
|
||||||
|
|
||||||
|
For built-in components that are not resizable, you have to create and train a
|
||||||
|
new model from scratch with the appropriate architecture and output dimension.
|
||||||
|
For custom components, you can implement a `resize_output` function and add it
|
||||||
|
as an attribute to the component's model.
|
||||||
|
|
||||||
| Name | Description |
|
| Name | Description |
|
||||||
| ----------- | ---------------------------------------------------------------------------------------------- |
|
| ----------- | ---------------------------------------------------------------------------------------------- |
|
||||||
| **RETURNS** | Whether or not the output dimension of the model can be changed after initialization. ~~bool~~ |
|
| **RETURNS** | Whether or not the output dimension of the model can be changed after initialization. ~~bool~~ |
|
||||||
|
|
||||||
> #### Example
|
|
||||||
>
|
|
||||||
> ```python
|
|
||||||
> def custom_resize(model, new_nO):
|
|
||||||
> # adjust model
|
|
||||||
> return model
|
|
||||||
> custom_model.attrs["resize_output"] = custom_resize
|
|
||||||
> ```
|
|
||||||
|
|
||||||
For built-in components that are not resizable, you have to create and train a
|
|
||||||
new model from scratch with the appropriate architecture and output dimension.
|
|
||||||
|
|
||||||
For custom components, you can implement a `resize_output` function and add it
|
|
||||||
as an attribute to the component's model.
|
|
||||||
|
|
||||||
## Pipe.set_output {#set_output tag="method"}
|
## Pipe.set_output {#set_output tag="method"}
|
||||||
|
|
||||||
Change the output dimension of the component's model. If the component is not
|
Change the output dimension of the component's model. If the component is not
|
||||||
[resizable](#is_resizable), this method will throw a `NotImplementedError`.
|
[resizable](#is_resizable), this method will raise a `NotImplementedError`. If a
|
||||||
|
component is resizable, the model's attribute `resize_output` will be called.
|
||||||
If a component is resizable, the model's attribute `resize_output` will be
|
This is a function that takes the original model and the new output dimension
|
||||||
called. This is a function that takes the original model and the new output
|
`nO`, and changes the model in place. When resizing an already trained model,
|
||||||
dimension `nO`, and changes the model in place.
|
care should be taken to avoid the "catastrophic forgetting" problem.
|
||||||
|
|
||||||
When resizing an already trained model, care should be taken to avoid the
|
|
||||||
"catastrophic forgetting" problem.
|
|
||||||
|
|
||||||
> #### Example
|
> #### Example
|
||||||
>
|
>
|
||||||
|
|
|
@ -289,7 +289,12 @@ context, the original parameters are restored.
|
||||||
## Tagger.add_label {#add_label tag="method"}
|
## Tagger.add_label {#add_label tag="method"}
|
||||||
|
|
||||||
Add a new label to the pipe. Raises an error if the output dimension is already
|
Add a new label to the pipe. Raises an error if the output dimension is already
|
||||||
set, or if the model has already been fully [initialized](#begin_training).
|
set, or if the model has already been fully [initialized](#begin_training). Note
|
||||||
|
that you don't have to call this method if you provide a **representative data
|
||||||
|
sample** to the [`begin_training`](#begin_training) method. In this case, all
|
||||||
|
labels found in the sample will be automatically added to the model, and the
|
||||||
|
output dimension will be [inferred](/usage/layers-architectures#shape-inference)
|
||||||
|
automatically.
|
||||||
|
|
||||||
> #### Example
|
> #### Example
|
||||||
>
|
>
|
||||||
|
@ -303,12 +308,6 @@ set, or if the model has already been fully [initialized](#begin_training).
|
||||||
| `label` | The label to add. ~~str~~ |
|
| `label` | The label to add. ~~str~~ |
|
||||||
| **RETURNS** | `0` if the label is already present, otherwise `1`. ~~int~~ |
|
| **RETURNS** | `0` if the label is already present, otherwise `1`. ~~int~~ |
|
||||||
|
|
||||||
Note that you don't have to call `pipe.add_label` if you provide a
|
|
||||||
representative data sample to the [`begin_training`](#begin_training) method. In
|
|
||||||
this case, all labels found in the sample will be automatically added to the
|
|
||||||
model, and the output dimension will be
|
|
||||||
[inferred](/usage/layers-architectures#shape-inference) automatically.
|
|
||||||
|
|
||||||
## Tagger.to_disk {#to_disk tag="method"}
|
## Tagger.to_disk {#to_disk tag="method"}
|
||||||
|
|
||||||
Serialize the pipe to disk.
|
Serialize the pipe to disk.
|
||||||
|
|
|
@ -298,7 +298,12 @@ Modify the pipe's model, to use the given parameter values.
|
||||||
## TextCategorizer.add_label {#add_label tag="method"}
|
## TextCategorizer.add_label {#add_label tag="method"}
|
||||||
|
|
||||||
Add a new label to the pipe. Raises an error if the output dimension is already
|
Add a new label to the pipe. Raises an error if the output dimension is already
|
||||||
set, or if the model has already been fully [initialized](#begin_training).
|
set, or if the model has already been fully [initialized](#begin_training). Note
|
||||||
|
that you don't have to call this method if you provide a **representative data
|
||||||
|
sample** to the [`begin_training`](#begin_training) method. In this case, all
|
||||||
|
labels found in the sample will be automatically added to the model, and the
|
||||||
|
output dimension will be [inferred](/usage/layers-architectures#shape-inference)
|
||||||
|
automatically.
|
||||||
|
|
||||||
> #### Example
|
> #### Example
|
||||||
>
|
>
|
||||||
|
@ -312,12 +317,6 @@ set, or if the model has already been fully [initialized](#begin_training).
|
||||||
| `label` | The label to add. ~~str~~ |
|
| `label` | The label to add. ~~str~~ |
|
||||||
| **RETURNS** | `0` if the label is already present, otherwise `1`. ~~int~~ |
|
| **RETURNS** | `0` if the label is already present, otherwise `1`. ~~int~~ |
|
||||||
|
|
||||||
Note that you don't have to call `pipe.add_label` if you provide a
|
|
||||||
representative data sample to the [`begin_training`](#begin_training) method. In
|
|
||||||
this case, all labels found in the sample will be automatically added to the
|
|
||||||
model, and the output dimension will be
|
|
||||||
[inferred](/usage/layers-architectures#shape-inference) automatically.
|
|
||||||
|
|
||||||
## TextCategorizer.to_disk {#to_disk tag="method"}
|
## TextCategorizer.to_disk {#to_disk tag="method"}
|
||||||
|
|
||||||
Serialize the pipe to disk.
|
Serialize the pipe to disk.
|
||||||
|
|
|
@ -5,8 +5,7 @@ menu:
|
||||||
- ['Type Signatures', 'type-sigs']
|
- ['Type Signatures', 'type-sigs']
|
||||||
- ['Swapping Architectures', 'swap-architectures']
|
- ['Swapping Architectures', 'swap-architectures']
|
||||||
- ['PyTorch & TensorFlow', 'frameworks']
|
- ['PyTorch & TensorFlow', 'frameworks']
|
||||||
- ['Custom Models', 'custom-models']
|
- ['Custom Thinc Models', 'thinc']
|
||||||
- ['Thinc implementation', 'thinc']
|
|
||||||
- ['Trainable Components', 'components']
|
- ['Trainable Components', 'components']
|
||||||
next: /usage/projects
|
next: /usage/projects
|
||||||
---
|
---
|
||||||
|
@ -226,13 +225,24 @@ you'll be able to try it out in any of the spaCy components.
|
||||||
|
|
||||||
Thinc allows you to [wrap models](https://thinc.ai/docs/usage-frameworks)
|
Thinc allows you to [wrap models](https://thinc.ai/docs/usage-frameworks)
|
||||||
written in other machine learning frameworks like PyTorch, TensorFlow and MXNet
|
written in other machine learning frameworks like PyTorch, TensorFlow and MXNet
|
||||||
using a unified [`Model`](https://thinc.ai/docs/api-model) API.
|
using a unified [`Model`](https://thinc.ai/docs/api-model) API. This makes it
|
||||||
|
easy to use a model implemented in a different framework to power a component in
|
||||||
For example, let's use PyTorch to define a very simple Neural network consisting
|
your spaCy pipeline. For example, to wrap a PyTorch model as a Thinc `Model`,
|
||||||
of two hidden `Linear` layers with `ReLU` activation and dropout, and a
|
you can use Thinc's
|
||||||
softmax-activated output layer.
|
[`PyTorchWrapper`](https://thinc.ai/docs/api-layers#pytorchwrapper):
|
||||||
|
|
||||||
```python
|
```python
|
||||||
|
from thinc.api import PyTorchWrapper
|
||||||
|
|
||||||
|
wrapped_pt_model = PyTorchWrapper(torch_model)
|
||||||
|
```
|
||||||
|
|
||||||
|
Let's use PyTorch to define a very simple neural network consisting of two
|
||||||
|
hidden `Linear` layers with `ReLU` activation and dropout, and a
|
||||||
|
softmax-activated output layer:
|
||||||
|
|
||||||
|
```python
|
||||||
|
### PyTorch model
|
||||||
from torch import nn
|
from torch import nn
|
||||||
|
|
||||||
torch_model = nn.Sequential(
|
torch_model = nn.Sequential(
|
||||||
|
@ -246,15 +256,6 @@ torch_model = nn.Sequential(
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
This PyTorch model can be wrapped as a Thinc `Model` by using Thinc's
|
|
||||||
`PyTorchWrapper`:
|
|
||||||
|
|
||||||
```python
|
|
||||||
from thinc.api import PyTorchWrapper
|
|
||||||
|
|
||||||
wrapped_pt_model = PyTorchWrapper(torch_model)
|
|
||||||
```
|
|
||||||
|
|
||||||
The resulting wrapped `Model` can be used as a **custom architecture** as such,
|
The resulting wrapped `Model` can be used as a **custom architecture** as such,
|
||||||
or can be a **subcomponent of a larger model**. For instance, we can use Thinc's
|
or can be a **subcomponent of a larger model**. For instance, we can use Thinc's
|
||||||
[`chain`](https://thinc.ai/docs/api-layers#chain) combinator, which works like
|
[`chain`](https://thinc.ai/docs/api-layers#chain) combinator, which works like
|
||||||
|
@ -273,21 +274,26 @@ model = chain(char_embed, with_array(wrapped_pt_model))
|
||||||
In the above example, we have combined our custom PyTorch model with a character
|
In the above example, we have combined our custom PyTorch model with a character
|
||||||
embedding layer defined by spaCy.
|
embedding layer defined by spaCy.
|
||||||
[CharacterEmbed](/api/architectures#CharacterEmbed) returns a `Model` that takes
|
[CharacterEmbed](/api/architectures#CharacterEmbed) returns a `Model` that takes
|
||||||
a `List[Doc]` as input, and outputs a `List[Floats2d]`. To make sure that the
|
a ~~List[Doc]~~ as input, and outputs a ~~List[Floats2d]~~. To make sure that
|
||||||
wrapped PyTorch model receives valid inputs, we use Thinc's
|
the wrapped PyTorch model receives valid inputs, we use Thinc's
|
||||||
[`with_array`](https://thinc.ai/docs/api-layers#with_array) helper.
|
[`with_array`](https://thinc.ai/docs/api-layers#with_array) helper.
|
||||||
|
|
||||||
As another example, you could have a model where you use PyTorch just for the
|
You could also implement a model that only uses PyTorch for the transformer
|
||||||
transformer layers, and use "native" Thinc layers to do fiddly input and output
|
layers, and "native" Thinc layers to do fiddly input and output transformations
|
||||||
transformations and add on task-specific "heads", as efficiency is less of a
|
and add on task-specific "heads", as efficiency is less of a consideration for
|
||||||
consideration for those parts of the network.
|
those parts of the network.
|
||||||
|
|
||||||
## Custom models for trainable components {#custom-models}
|
### Using wrapped models {#frameworks-usage}
|
||||||
|
|
||||||
To use our custom model including the PyTorch subnetwork, all we need to do is
|
To use our custom model including the PyTorch subnetwork, all we need to do is
|
||||||
register the architecture. The full example then becomes:
|
register the architecture using the
|
||||||
|
[`architectures` registry](/api/top-level#registry). This will assign the
|
||||||
|
architecture a name so spaCy knows how to find it, and allows passing in
|
||||||
|
arguments like hyperparameters via the [config](/usage/training#config). The
|
||||||
|
full example then becomes:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
|
### Registering the architecture {highlight="9"}
|
||||||
from typing import List
|
from typing import List
|
||||||
from thinc.types import Floats2d
|
from thinc.types import Floats2d
|
||||||
from thinc.api import Model, PyTorchWrapper, chain, with_array
|
from thinc.api import Model, PyTorchWrapper, chain, with_array
|
||||||
|
@ -297,7 +303,7 @@ from spacy.ml import CharacterEmbed
|
||||||
from torch import nn
|
from torch import nn
|
||||||
|
|
||||||
@spacy.registry.architectures("CustomTorchModel.v1")
|
@spacy.registry.architectures("CustomTorchModel.v1")
|
||||||
def TorchModel(
|
def create_torch_model(
|
||||||
nO: int,
|
nO: int,
|
||||||
width: int,
|
width: int,
|
||||||
hidden_width: int,
|
hidden_width: int,
|
||||||
|
@ -321,8 +327,10 @@ def TorchModel(
|
||||||
return model
|
return model
|
||||||
```
|
```
|
||||||
|
|
||||||
Now you can use this model definition in any existing trainable spaCy component,
|
The model definition can now be used in any existing trainable spaCy component,
|
||||||
by specifying it in the config file:
|
by specifying it in the config file. In this configuration, all required
|
||||||
|
parameters for the various subcomponents of the custom architecture are passed
|
||||||
|
in as settings via the config.
|
||||||
|
|
||||||
```ini
|
```ini
|
||||||
### config.cfg (excerpt) {highlight="5-5"}
|
### config.cfg (excerpt) {highlight="5-5"}
|
||||||
|
@ -340,106 +348,124 @@ nC = 8
|
||||||
dropout = 0.2
|
dropout = 0.2
|
||||||
```
|
```
|
||||||
|
|
||||||
In this configuration, we pass all required parameters for the various
|
<Infobox variant="warning">
|
||||||
subcomponents of the custom architecture as settings in the training config
|
|
||||||
file. Remember that it is best not to rely on any (hidden) default values, to
|
|
||||||
ensure that training configs are complete and experiments fully reproducible.
|
|
||||||
|
|
||||||
## Thinc implemention details {#thinc}
|
Remember that it is best not to rely on any (hidden) default values, to ensure
|
||||||
|
that training configs are complete and experiments fully reproducible.
|
||||||
|
|
||||||
Ofcourse it's also possible to define the `Model` from the previous section
|
</Infobox>
|
||||||
|
|
||||||
|
## Custom models with Thinc {#thinc}
|
||||||
|
|
||||||
|
Of course it's also possible to define the `Model` from the previous section
|
||||||
entirely in Thinc. The Thinc documentation provides details on the
|
entirely in Thinc. The Thinc documentation provides details on the
|
||||||
[various layers](https://thinc.ai/docs/api-layers) and helper functions
|
[various layers](https://thinc.ai/docs/api-layers) and helper functions
|
||||||
available.
|
available. Combinators can also be used to
|
||||||
|
[overload operators](https://thinc.ai/docs/usage-models#operators) and a common
|
||||||
The combinators often used in Thinc can be used to
|
usage pattern is to bind `chain` to `>>`. The "native" Thinc version of our
|
||||||
[overload operators](https://thinc.ai/docs/usage-models#operators). A common
|
simple neural network would then become:
|
||||||
usage is to bind `chain` to `>>`. The "native" Thinc version of our simple
|
|
||||||
neural network would then become:
|
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from thinc.api import chain, with_array, Model, Relu, Dropout, Softmax
|
from thinc.api import chain, with_array, Model, Relu, Dropout, Softmax
|
||||||
from spacy.ml import CharacterEmbed
|
from spacy.ml import CharacterEmbed
|
||||||
|
|
||||||
char_embed = CharacterEmbed(width, embed_size, nM, nC)
|
char_embed = CharacterEmbed(width, embed_size, nM, nC)
|
||||||
|
|
||||||
with Model.define_operators({">>": chain}):
|
with Model.define_operators({">>": chain}):
|
||||||
layers = (
|
layers = (
|
||||||
Relu(hidden_width, width)
|
Relu(hidden_width, width)
|
||||||
>> Dropout(dropout)
|
>> Dropout(dropout)
|
||||||
>> Relu(hidden_width, hidden_width)
|
>> Relu(hidden_width, hidden_width)
|
||||||
>> Dropout(dropout)
|
>> Dropout(dropout)
|
||||||
>> Softmax(nO, hidden_width)
|
>> Softmax(nO, hidden_width)
|
||||||
)
|
)
|
||||||
model = char_embed >> with_array(layers)
|
model = char_embed >> with_array(layers)
|
||||||
```
|
```
|
||||||
|
|
||||||
**⚠️ Note that Thinc layers define the output dimension (`nO`) as the first
|
<Infobox variant="warning" title="Important note on inputs and outputs">
|
||||||
argument, followed (optionally) by the input dimension (`nI`). This is in
|
|
||||||
contrast to how the PyTorch layers are defined, where `in_features` precedes
|
|
||||||
`out_features`.**
|
|
||||||
|
|
||||||
### Shape inference in thinc {#shape-inference}
|
Note that Thinc layers define the output dimension (`nO`) as the first argument,
|
||||||
|
followed (optionally) by the input dimension (`nI`). This is in contrast to how
|
||||||
|
the PyTorch layers are defined, where `in_features` precedes `out_features`.
|
||||||
|
|
||||||
It is not strictly necessary to define all the input and output dimensions for
|
</Infobox>
|
||||||
each layer, as Thinc can perform
|
|
||||||
|
### Shape inference in Thinc {#thinc-shape-inference}
|
||||||
|
|
||||||
|
It is **not** strictly necessary to define all the input and output dimensions
|
||||||
|
for each layer, as Thinc can perform
|
||||||
[shape inference](https://thinc.ai/docs/usage-models#validation) between
|
[shape inference](https://thinc.ai/docs/usage-models#validation) between
|
||||||
sequential layers by matching up the output dimensionality of one layer to the
|
sequential layers by matching up the output dimensionality of one layer to the
|
||||||
input dimensionality of the next. This means that we can simplify the `layers`
|
input dimensionality of the next. This means that we can simplify the `layers`
|
||||||
definition:
|
definition:
|
||||||
|
|
||||||
|
> #### Diff
|
||||||
|
>
|
||||||
|
> ```diff
|
||||||
|
> layers = (
|
||||||
|
> Relu(hidden_width, width)
|
||||||
|
> >> Dropout(dropout)
|
||||||
|
> - >> Relu(hidden_width, hidden_width)
|
||||||
|
> + >> Relu(hidden_width)
|
||||||
|
> >> Dropout(dropout)
|
||||||
|
> - >> Softmax(nO, hidden_width)
|
||||||
|
> + >> Softmax(nO)
|
||||||
|
> )
|
||||||
|
> ```
|
||||||
|
|
||||||
```python
|
```python
|
||||||
with Model.define_operators({">>": chain}):
|
with Model.define_operators({">>": chain}):
|
||||||
layers = (
|
layers = (
|
||||||
Relu(hidden_width, width)
|
Relu(hidden_width, width)
|
||||||
>> Dropout(dropout)
|
>> Dropout(dropout)
|
||||||
>> Relu(hidden_width)
|
>> Relu(hidden_width)
|
||||||
>> Dropout(dropout)
|
>> Dropout(dropout)
|
||||||
>> Softmax(nO)
|
>> Softmax(nO)
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
Thinc can go one step further and deduce the correct input dimension of the
|
Thinc can even go one step further and **deduce the correct input dimension** of
|
||||||
first layer, and output dimension of the last. To enable this functionality, you
|
the first layer, and output dimension of the last. To enable this functionality,
|
||||||
have to call [`model.initialize`](https://thinc.ai/docs/api-model#initialize)
|
you have to call
|
||||||
with an input sample `X` and an output sample `Y` with the correct dimensions.
|
[`Model.initialize`](https://thinc.ai/docs/api-model#initialize) with an **input
|
||||||
|
sample** `X` and an **output sample** `Y` with the correct dimensions:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
|
### Shape inference with initialization {highlight="3,7,10"}
|
||||||
with Model.define_operators({">>": chain}):
|
with Model.define_operators({">>": chain}):
|
||||||
layers = (
|
layers = (
|
||||||
Relu(hidden_width)
|
Relu(hidden_width)
|
||||||
>> Dropout(dropout)
|
>> Dropout(dropout)
|
||||||
>> Relu(hidden_width)
|
>> Relu(hidden_width)
|
||||||
>> Dropout(dropout)
|
>> Dropout(dropout)
|
||||||
>> Softmax()
|
>> Softmax()
|
||||||
)
|
)
|
||||||
model = char_embed >> with_array(layers)
|
model = char_embed >> with_array(layers)
|
||||||
model.initialize(X=input_sample, Y=output_sample)
|
model.initialize(X=input_sample, Y=output_sample)
|
||||||
```
|
```
|
||||||
|
|
||||||
The built-in [pipeline components](/usage/processing-pipelines) in spaCy ensure
|
The built-in [pipeline components](/usage/processing-pipelines) in spaCy ensure
|
||||||
that their internal models are always initialized with appropriate sample data.
|
that their internal models are **always initialized** with appropriate sample
|
||||||
In this case, `X` is typically a `List` of `Doc` objects, while `Y` is a `List`
|
data. In this case, `X` is typically a ~~List[Doc]~~, while `Y` is typically a
|
||||||
of 1D or 2D arrays, depending on the specific task. This functionality is
|
~~List[Array1d]~~ or ~~List[Array2d]~~, depending on the specific task. This
|
||||||
triggered when [`nlp.begin_training`](/api/language#begin_training) is called.
|
functionality is triggered when
|
||||||
|
[`nlp.begin_training`](/api/language#begin_training) is called.
|
||||||
|
|
||||||
### Dropout and normalization {#drop-norm}
|
### Dropout and normalization in Thinc {#thinc-dropout-norm}
|
||||||
|
|
||||||
Many of the `Thinc` layers allow you to define a `dropout` argument that will
|
Many of the available Thinc [layers](https://thinc.ai/docs/api-layers) allow you
|
||||||
result in "chaining" an additional
|
to define a `dropout` argument that will result in "chaining" an additional
|
||||||
[`Dropout`](https://thinc.ai/docs/api-layers#dropout) layer. Optionally, you can
|
[`Dropout`](https://thinc.ai/docs/api-layers#dropout) layer. Optionally, you can
|
||||||
often specify whether or not you want to add layer normalization, which would
|
often specify whether or not you want to add layer normalization, which would
|
||||||
result in an additional
|
result in an additional
|
||||||
[`LayerNorm`](https://thinc.ai/docs/api-layers#layernorm) layer.
|
[`LayerNorm`](https://thinc.ai/docs/api-layers#layernorm) layer. That means that
|
||||||
|
the following `layers` definition is equivalent to the previous:
|
||||||
That means that the following `layers` definition is equivalent to the previous:
|
|
||||||
|
|
||||||
```python
|
```python
|
||||||
with Model.define_operators({">>": chain}):
|
with Model.define_operators({">>": chain}):
|
||||||
layers = (
|
layers = (
|
||||||
Relu(hidden_width, dropout=dropout, normalize=False)
|
Relu(hidden_width, dropout=dropout, normalize=False)
|
||||||
>> Relu(hidden_width, dropout=dropout, normalize=False)
|
>> Relu(hidden_width, dropout=dropout, normalize=False)
|
||||||
>> Softmax()
|
>> Softmax()
|
||||||
)
|
)
|
||||||
model = char_embed >> with_array(layers)
|
model = char_embed >> with_array(layers)
|
||||||
model.initialize(X=input_sample, Y=output_sample)
|
model.initialize(X=input_sample, Y=output_sample)
|
||||||
|
|
|
@ -34,6 +34,8 @@
|
||||||
"Floats2d": "https://thinc.ai/docs/api-types#types",
|
"Floats2d": "https://thinc.ai/docs/api-types#types",
|
||||||
"Floats3d": "https://thinc.ai/docs/api-types#types",
|
"Floats3d": "https://thinc.ai/docs/api-types#types",
|
||||||
"FloatsXd": "https://thinc.ai/docs/api-types#types",
|
"FloatsXd": "https://thinc.ai/docs/api-types#types",
|
||||||
|
"Array1d": "https://thinc.ai/docs/api-types#types",
|
||||||
|
"Array2d": "https://thinc.ai/docs/api-types#types",
|
||||||
"Ops": "https://thinc.ai/docs/api-backends#ops",
|
"Ops": "https://thinc.ai/docs/api-backends#ops",
|
||||||
"cymem.Pool": "https://github.com/explosion/cymem",
|
"cymem.Pool": "https://github.com/explosion/cymem",
|
||||||
"preshed.BloomFilter": "https://github.com/explosion/preshed",
|
"preshed.BloomFilter": "https://github.com/explosion/preshed",
|
||||||
|
|
Loading…
Reference in New Issue
Block a user