Skip to content

Commit 7cfcf4a

Browse files
authored
Merge pull request #40 from JuliaText/fix/update_for_1_12
Fix explicit namespace usage
2 parents abeb384 + 3b96460 commit 7cfcf4a

File tree

14 files changed

+766
-682
lines changed

14 files changed

+766
-682
lines changed

Project.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name = "TextModels"
22
uuid = "77b9cbda-2a23-51df-82a3-24144d1cd378"
33
license = "MIT"
44
desc = "Practical Neural Network based models for Natural Language Processing"
5-
version = "0.2.0"
5+
version = "0.2.1"
66

77
[deps]
88
BSON = "fbb218c0-5317-5bc6-957e-2ee96dd4b1f0"
@@ -32,7 +32,7 @@ DataDeps = "0.7"
3232
DataStructures = "0.18, 0.19, 0.20"
3333
Flux = "0.16, 0.17"
3434
Functors = "0.4, 0.5, 0.6"
35-
JSON = "0.21, 0.22"
35+
JSON = "0.21, 1"
3636
Languages = "0.4"
3737
NNlib = "0.7, 0.8, 0.9, 0.10"
3838
StatsBase = "0.33, 0.34, 0.35"

docs/Project.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
[deps]
22
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
3+
Flux = "587475ba-b771-5e3f-ad9e-33799f191a9c"
34
TextAnalysis = "a2db99b7-8b79-58f8-94bf-bbc811eef33d"
45
TextModels = "77b9cbda-2a23-51df-82a3-24144d1cd378"
6+
WordTokenizers = "796a5d58-b03d-544a-977e-18100b691f6e"

docs/src/APIReference.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,10 @@
44
Modules = [TextModels, TextModels.ULMFiT]
55
Order = [:function, :type]
66
```
7+
8+
## Constructor Functions
9+
10+
```@docs
11+
NERTagger
12+
PoSTagger
13+
```

docs/src/ULMFiT.md

Lines changed: 64 additions & 93 deletions
Large diffs are not rendered by default.

docs/src/crf.md

Lines changed: 78 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -2,130 +2,128 @@
22

33
This package currently provides support for Linear Chain Conditional Random Fields.
44

5-
Let us first load the dependencies-
5+
Let us first load the dependencies:
66

7-
using Flux
8-
using Flux: onehot, LSTM, Dense, reset!
9-
using TextModels: CRF, viterbi_decode, crf_loss
10-
11-
Conditional Random Field layer is essentially like a softmax that operates on the top most layer.
7+
```@example crf
8+
using Flux
9+
using Flux: onehot, LSTM, Dense, reset!
10+
using TextModels: CRF, viterbi_decode, crf_loss
11+
nothing # hide
12+
```
1213

13-
Let us suppose the following input sequence to the CRF with `NUM_LABELS = 2`
14+
Conditional Random Field layer is essentially like a softmax layer that operates on the top-most layer.
1415

15-
```julia
16-
julia> NUM_LABELS = 2
17-
julia> SEQUENCE_LENGTH = 2 # CRFs can handle variable length inputs sequences
18-
julia> input_seq = [Float32.(rand(NUM_LABELS + 2)) for i in 1:SEQUENCE_LENGTH] # NUM_LABELS + 2, where two extra features correspond to the :START and :END label.
19-
2-element Vector{Vector{Float32}}:
20-
[0.5114323, 0.5355139, 0.4011792, 0.56359255]
21-
[0.22925346, 0.21232551, 0.77616125, 0.41560093]
16+
Let us suppose the following input sequence to the CRF with `NUM_LABELS = 2`:
2217

18+
```@example crf
19+
using Random
20+
Random.seed!(42) # For reproducible documentation
21+
NUM_LABELS = 2
22+
SEQUENCE_LENGTH = 3 # CRFs can handle variable length inputs sequences
23+
input_seq = [rand(NUM_LABELS + 2) for i in 1:SEQUENCE_LENGTH] # NUM_LABELS + 2, where two extra features correspond to the :START and :END label.
2324
```
2425

25-
We define our crf layer as -
26+
We define our CRF layer as:
2627

2728
CRF(NUM_LABELS::Integer)
2829

29-
```julia
30-
julia> c = CRF(NUM_LABELS) # The API internally append the START and END tags to NUM_LABELS.
31-
CRF with 4 distinct tags (including START and STOP tags).
30+
```@example crf
31+
c = CRF(NUM_LABELS) # The API internally append the START and END tags to NUM_LABELS.
3232
```
3333

34-
Now as for the initial variable in Viterbi Decode or Forward Algorithm,
35-
we define our input as
34+
Now for the initial variable in Viterbi Decode or Forward Algorithm,
35+
we define our input as:
3636

37-
```julia
38-
julia> init_α = fill(-10000, (c.n + 2, 1))
39-
julia> init_α[c.n + 1] = 0
37+
```@example crf
38+
init_α = fill(-10000, (c.n + 2, 1))
39+
init_α[c.n + 1] = 0
40+
init_α
4041
```
4142

4243
Optionally this could be shifted to GPU by `init_α = gpu(init_α)`,
43-
considering the input sequence to be CuArray in this case.
44-
To shift a CRF `c` to gpu, one can use `c = gpu(c)`.
44+
considering the input sequence to be a CuArray in this case.
45+
To shift a CRF `c` to GPU, one can use `c = gpu(c)`.
4546

46-
To find out the crf loss, we use the following function -
47+
To find the CRF loss, we use the following function:
4748

4849
crf_loss(c::CRF, input_seq, label_sequence, init_α)
4950

50-
```
51-
julia> label_seq1 = [onehot(1, 1:2), onehot(1, 1:2)]
52-
53-
julia> label_seq2 = [onehot(1, 1:2), onehot(2, 1:2)]
54-
55-
julia> label_seq3 = [onehot(2, 1:2), onehot(1, 1:2)]
51+
```@example crf
52+
using Flux: onehot
53+
label_seq1 = [onehot(1, 1:2), onehot(1, 1:2), onehot(1, 1:2)]
54+
label_seq2 = [onehot(1, 1:2), onehot(1, 1:2), onehot(2, 1:2)]
55+
label_seq3 = [onehot(2, 1:2), onehot(1, 1:2), onehot(1, 1:2)]
56+
label_seq4 = [onehot(2, 1:2), onehot(2, 1:2), onehot(2, 1:2)]
5657
57-
julia> label_seq4 = [onehot(2, 1:2), onehot(2, 1:2)]
58-
59-
julia> crf_loss(c, input_seq, label_seq1, init_α)
60-
1.33554f0
61-
62-
julia> crf_loss(c, input_seq, label_seq2, init_α)
63-
1.2327178f0
58+
crf_loss(c, input_seq, label_seq1, init_α)
59+
```
6460

65-
julia> crf_loss(c, input_seq, label_seq3, init_α)
66-
1.3454239f0
61+
```@example crf
62+
crf_loss(c, input_seq, label_seq2, init_α)
63+
```
6764

68-
julia> crf_loss(c, input_seq, label_seq4, init_α)
69-
1.6871009f0
65+
```@example crf
66+
crf_loss(c, input_seq, label_seq3, init_α)
67+
```
7068

69+
```@example crf
70+
crf_loss(c, input_seq, label_seq4, init_α)
7171
```
7272

73-
We can decode this using Viterbi Decode.
73+
We can decode this using Viterbi Decode:
7474

7575
viterbi_decode(c::CRF, input_seq, init_α)
7676

77-
```julia
78-
julia> viterbi_decode(c, input_seq, init_α) # Gives the label_sequence with least loss
79-
2-element Vector{Flux.OneHotArray{UInt32, 2, 0, 1, UInt32}}:
80-
[1, 0]
81-
[0, 1]
82-
77+
```@example crf
78+
viterbi_decode(c, input_seq, init_α) # Gives the label_sequence with least loss
8379
```
8480

85-
This algorithm decodes for the label sequence with lowest loss value in polynomial time.
81+
This algorithm decodes the label sequence with the lowest loss value in polynomial time.
8682

87-
Currently the Viterbi Decode only support cpu arrays.
88-
When working with GPU, use viterbi_decode as follows
83+
Currently the Viterbi Decode only supports CPU arrays.
84+
When working with GPU, use viterbi_decode as follows:
8985

9086
viterbi_decode(cpu(c), cpu.(input_seq), cpu(init_α))
9187

9288
### Working with Flux layers
9389

94-
CRFs smoothly work over Flux layers-
95-
96-
```julia
97-
julia> NUM_FEATURES = 20
98-
99-
julia> input_seq = [rand(NUM_FEATURES) for i in 1:SEQUENCE_LENGTH]
100-
2-element Vector{Vector{Float32}}:
101-
[0.948219, 0.719964, 0.352734, 0.0677656, 0.570564, 0.187673, 0.525125, 0.787807, 0.262452, 0.472472, 0.573259, 0.643369, 0.00592054, 0.945258, 0.951466, 0.323156, 0.679573, 0.663285, 0.218595, 0.152846]
102-
[0.433295, 0.11998, 0.99615, 0.530107, 0.188887, 0.897213, 0.993726, 0.0799431, 0.953333, 0.941808, 0.982638, 0.0919345, 0.27504, 0.894169, 0.66818, 0.449537, 0.93063, 0.384957, 0.415114, 0.212203]
103-
104-
julia> m1 = Dense(NUM_FEATURES, NUM_LABELS + 2)
105-
106-
julia> loss1(input_seq, label_seq) = crf_loss(c, m1.(input_seq), label_seq, init_α) # loss for model m1
90+
CRFs work smoothly with Flux layers:
10791

108-
julia> loss1(input_seq, [onehot(1, 1:2), onehot(1, 1:2)])
109-
4.6620379898687485
92+
```@example crf
93+
using Flux: Dense
94+
NUM_FEATURES = 20
11095
96+
# For working with Dense layers, we can use 1D vectors
97+
input_seq_dense = [rand(NUM_FEATURES) for i in 1:SEQUENCE_LENGTH]
11198
```
11299

100+
```@example crf
101+
m1 = Dense(NUM_FEATURES, NUM_LABELS + 2)
102+
loss1(input_seq, label_seq) = crf_loss(c, m1.(input_seq), label_seq, init_α) # loss for model m1
103+
loss1(input_seq_dense, [onehot(1, 1:2), onehot(1, 1:2), onehot(1, 1:2)])
104+
```
113105

114-
Here is an example of CRF with LSTM and Dense layer -
115-
116-
```julia
117-
julia> LSTM_SIZE = 10
118-
119-
julia> lstm = LSTM(NUM_FEATURES, LSTM_SIZE)
120106

121-
julia> dense_out = Dense(LSTM_SIZE, NUM_LABELS + 2)
107+
Here is an example of CRF with recurrent neural network layers:
122108

123-
julia> m2(x) = dense_out.(lstm.(x))
109+
```@example crf
110+
# For recurrent layers, we need 2D input matrices (features × sequence_position)
111+
# Let's create properly formatted 2D data
112+
input_2d = [Float32.(rand(2, 1)) for i in 1:SEQUENCE_LENGTH] # 2 features, 1 time step each
113+
input_2d
114+
```
124115

125-
julia> loss2(input_seq, label_seq) = crf_loss(c, m2(input_seq), label_seq, init_α) # loss for model m2
116+
```@example crf
117+
using Flux: RNN
118+
# Create a simple RNN model that works with 2D input
119+
rnn_model = RNN(2 => 5) # 2 input features → 5 hidden units
120+
dense_layer = Dense(5, NUM_LABELS + 2) # 5 hidden → 4 output (NUM_LABELS + 2)
126121
127-
julia> loss2(input_seq, [onehot(1, 1:2), onehot(1, 1:2)])
128-
1.6501050910529504
122+
# Forward pass through RNN then Dense layer
123+
rnn_outputs = rnn_model.(input_2d)
124+
final_outputs = dense_layer.(rnn_outputs)
129125
130-
julia> reset!(lstm)
126+
# Now we can use this with CRF
127+
loss_rnn(input_2d, label_seq) = crf_loss(c, dense_layer.(rnn_model.(input_2d)), label_seq, init_α)
128+
loss_rnn(input_2d, [onehot(1, 1:2), onehot(2, 1:2), onehot(1, 1:2)])
131129
```

docs/src/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
The TextModels package enhances the TextAnalysis package with end-user focussed, practical natural language models, typically based on neural networks (in this case, [Flux](https://fluxml.ai/))
44

5-
This package depends on the [TextAnalysis](https://github.com/JuliaText/TextAnalysis.jl) package, which contains basic algorithms to deal with textual documetns.
5+
This package depends on the [TextAnalysis](https://github.com/JuliaText/TextAnalysis.jl) package, which contains basic algorithms to deal with textual documents.
66

77
## Installation
88

0 commit comments

Comments
 (0)