Skip to content
This repository was archived by the owner on Nov 8, 2022. It is now read-only.

Commit 30172ad

Browse files
author
Peter Izsak
authored
Merge branch 'master' into add-non-.py-files-to-MANIFEST
2 parents 4806bc0 + 7d7ece4 commit 30172ad

File tree

12 files changed

+66
-106
lines changed

12 files changed

+66
-106
lines changed

doc/source/absa.rst

+3-3
Original file line numberDiff line numberDiff line change
@@ -153,8 +153,8 @@ Arguments:
153153
References
154154
==========
155155

156-
.. [1] `Simple and Accurate Dependency Parsing Using Bidirectional LSTM Feature Representations <https://transacl.org/ojs/index.php/tacl/article/view/885/198>`__, Kiperwasser, E., & Goldberg, Y, Transactions Of The Association For Computational Linguistics (2106), 4, 313-327.
157-
.. [2] `Opinion word expansion and target extraction through double propagation <https://dl.acm.org/citation.cfm?id=1970422>`__, Guang Qiu, Bing Liu, Jiajun Bu, and Chun Chen, In Computational Linguistics, volume 37(1).
158-
.. [3] `Mining and Summarizing Customer Reviews <http://dx.doi.org/10.1145/1014052.1014073>`__, Minqing Hu and Bing Liu, Proceedings of the tenth ACM SIGKDD International Conference on Knowledge Discovery and Data Mining (KDD-2004), pp. 168-177, 2004.
156+
.. [1] `Simple and Accurate Dependency Parsing Using Bidirectional LSTM Feature Representations <https://transacl.org/ojs/index.php/tacl/article/view/885/198>`__, Eliyahu Kiperwasser and Yoav Goldberg. 2016. Transactions of the Association of Computational Linguistics, 4:313327.
157+
.. [2] `Opinion Word Expansion and Target Extraction through Double Propagation <https://dl.acm.org/citation.cfm?id=1970422>`__, Guang Qiu, Bing Liu, Jiajun Bu, and Chun Chen. 2011. Computational Linguistics, 37(1): 9–27.
158+
.. [3] `Mining and Summarizing Customer Reviews <http://dx.doi.org/10.1145/1014052.1014073>`__, Minqing Hu and Bing Liu. 2004. In Proceedings of the Tenth ACM SIGKDD International Conference on Knowledge Discovery and Data Mining, KDD ’04, pages 168177.
159159
160160
.. _Spacy: https://spacy.io

doc/source/absa_solution.rst

+11-10
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ a statistical analysis of sentiment towards specific aspects in the inference da
3131

3232
The solution uses the opinion and aspect lexicons that are generated using NLP Architect's ABSA
3333
training model (see blue blocks in 'flow' diagram below). For more details regarding the training step
34-
see :doc:`ABSA <absa>`
34+
see :doc:`ABSA <absa>`.
3535

3636
The solution encapsulates the ABSA inference model (green blocks) and adds on top of it a
3737
statistical analysis module (grey block) for calculating the amount of positive and negative sentiment
@@ -61,23 +61,24 @@ blue and opinion terms are colored in green/red:
6161
Solution execution
6262
==================
6363

64-
The solution execution is divided to two parts - training A and inference:
64+
The solution execution is divided to two parts - training and inference:
6565

6666
Training
6767
========
6868

69-
See training under :doc:`ABSA <absa>`
69+
See training under :doc:`ABSA <absa>`.
7070

7171

7272
Inference
7373
=========
7474

75+
7576
Full code example is available at ``examples/absa/solution/absa_solution.py``.
7677
There are two training modes:
7778

78-
1. Providing solution data in a raw text format. In this case the solution flow will
79-
apply the dependency parser to the data:
8079

80+
**1.** Providing solution data in a raw text format. In this case the solution flow will
81+
apply the dependency parser to the data:
8182

8283
.. code:: python
8384
@@ -86,7 +87,7 @@ apply the dependency parser to the data:
8687
data='/path/to/text/file/or/directory')
8788
8889
89-
Arguments:
90+
**Arguments:**
9091

9192
``aspect_lex'=/path/to/aspects.csv'`` - path to aspect lexicon (csv file) that was produced by the training phase.
9293
aspect.csv may be manually edited for grouping alias aspect names (e.g. 'drinks' and 'beverages')
@@ -98,7 +99,7 @@ together. Simply copy all alias names to the same line in the csv file.
9899
separated by newlines or a single csv file containing one doc per line or a directory containing one raw
99100
text file per document.
100101

101-
Notes:
102+
**Notes:**
102103

103104
a. For demonstration purposes we provide a sample of tripadvisor.co.uk
104105
restaurants reviews under the `Creative Commons Attribution-Share-Alike 3.0 License <https://creativecommons.org/licenses/by-sa/3.0/>`__ (Copyright 2018 Wikimedia Foundation).
@@ -107,8 +108,8 @@ The dataset can is located at ``datasets/absa/tripadvisor_co_uk-travel_restauran
107108
b. By default, when the execution terminates, a browser window is opened, displaying the
108109
visualization UI.
109110

110-
111-
2. Providing parsed training data. In this case the solution flow skips the parsing step:
111+
|
112+
| **2.** Providing parsed training data. In this case the solution flow skips the parsing step:
112113
113114
.. code:: python
114115
@@ -117,7 +118,7 @@ visualization UI.
117118
parsed_data='/path/to/parsed/directory',
118119
ui=False)
119120
120-
Note:
121+
**Note:**
121122

122123
Setting ``ui=False`` disables the UI and enables to get the sentiment statistics as dataframe. This
123124
enables the user to use those statistics as input to his own custom built visualization.

doc/source/index.rst

+3-9
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
.. toctree::
3333
:hidden:
3434
:maxdepth: 1
35-
:caption: NLP/NLU Components
35+
:caption: NLP/NLU Models
3636

3737
Aspect Based Sentiment Analysis <absa.rst>
3838
chunker.rst
@@ -43,20 +43,14 @@
4343
word_sense.rst
4444
np2vec.rst
4545
supervised_sentiment.rst
46+
reading_comprehension.rst
47+
memn2n.rst
4648
TCN Language Model <tcn.rst>
4749
Unsupervised Crosslingual Embeddings <crosslingual_emb.rst>
4850
Cross Document Co-Reference <cross_doc_coref.rst>
4951
Semantic Relation Identification <identifying_semantic_relation.rst>
5052
Sparse Neural Machine Translation <sparse_gnmt.rst>
5153

52-
.. toctree::
53-
:hidden:
54-
:maxdepth: 1
55-
:caption: End to End Models
56-
57-
reading_comprehension.rst
58-
memn2n.rst
59-
6054
.. toctree::
6155
:hidden:
6256
:maxdepth: 1

doc/source/main.rst

+1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ The library contains state-of-art and novel NLP and NLU models in a variety of t
4242
- Reading comprehension
4343
- Language modeling using Temporal Convolution Network
4444
- Unsupervised Crosslingual Word Embedding
45+
- Aspect Based Sentiment Analysis
4546
- Supervised sentiment analysis
4647
- Sparse and quantized neural machine translation
4748
- Relation Identification and cross document coreference

examples/ner/interactive.py

+1
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ def vectorize(doc, w_vocab, c_vocab):
8282
doc_vec = vectorize(text_arr, word_vocab, char_vocab)
8383
seq_len = np.array([len(text_arr)]).reshape(-1, 1)
8484
inputs = list(doc_vec)
85+
# pylint: disable=no-member
8586
if model.crf_mode == 'pad':
8687
inputs = list(doc_vec) + [seq_len]
8788
doc_ner = model.predict(inputs, batch_size=1).argmax(2).flatten()

examples/ner/train.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -108,13 +108,13 @@ def validate_input_args(input_args):
108108
y_train = keras.utils.to_categorical(y_train, num_y_labels)
109109

110110
ner_model = NERCRF(use_cudnn=args.use_cudnn)
111+
# pylint: disable=unexpected-keyword-arg
111112
ner_model.build(args.word_length,
112113
num_y_labels,
113114
vocabulary_size,
114115
char_vocabulary_size,
115116
word_embedding_dims=args.word_embedding_dims,
116117
char_embedding_dims=args.character_embedding_dims,
117-
word_lstm_dims=args.char_features_lstm_dims,
118118
tagger_lstm_dims=args.entity_tagger_lstm_dims,
119119
dropout=args.dropout)
120120

@@ -126,9 +126,9 @@ def validate_input_args(input_args):
126126

127127
train_inputs = [x_train, x_char_train]
128128
test_inputs = [x_test, x_char_test]
129-
if not args.use_cudnn:
130-
train_inputs.append(np.sum(np.not_equal(x_train, 0), axis=-1).reshape((-1, 1)))
131-
test_inputs.append(np.sum(np.not_equal(x_test, 0), axis=-1).reshape((-1, 1)))
129+
130+
train_inputs.append(np.sum(np.not_equal(x_train, 0), axis=-1).reshape((-1, 1)))
131+
test_inputs.append(np.sum(np.not_equal(x_test, 0), axis=-1).reshape((-1, 1)))
132132

133133
conll_cb = ConllCallback(test_inputs, y_test, dataset.y_labels.vocab,
134134
batch_size=args.b)

nlp_architect/api/ner_api.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ class NerApi(AbstractApi):
3131
NER model API
3232
"""
3333
model_dir = str(LIBRARY_OUT / 'ner-pretrained')
34-
pretrained_model = path.join(model_dir, 'model.h5')
35-
pretrained_model_info = path.join(model_dir, 'model_info.dat')
34+
pretrained_model = path.join(model_dir, 'model_v4.h5')
35+
pretrained_model_info = path.join(model_dir, 'model_info_v4.dat')
3636

3737
def __init__(self, prompt=True):
3838
self.model = None
@@ -71,10 +71,10 @@ def _download_pretrained_model(self, prompt=True):
7171
sys.exit(0)
7272
download_unlicensed_file('https://s3-us-west-2.amazonaws.com/nlp-architect-data'
7373
'/models/ner/',
74-
'model.h5', self.pretrained_model)
74+
'model_v4.h5', self.pretrained_model)
7575
download_unlicensed_file('https://s3-us-west-2.amazonaws.com/nlp-architect-data'
7676
'/models/ner/',
77-
'model_info.dat', self.pretrained_model_info)
77+
'model_info_v4.dat', self.pretrained_model_info)
7878
print('Done.')
7979

8080
def load_model(self):
@@ -129,8 +129,8 @@ def inference(self, doc):
129129
doc_vec = self.vectorize(text_arr, self.word_vocab, self.char_vocab)
130130
seq_len = np.array([len(text_arr)]).reshape(-1, 1)
131131
inputs = list(doc_vec)
132-
if self.model.crf_mode == 'pad':
133-
inputs = list(doc_vec) + [seq_len]
132+
# pylint: disable=no-member
133+
inputs = list(doc_vec) + [seq_len]
134134
doc_ner = self.model.predict(inputs, batch_size=1).argmax(2).flatten()
135135
tags = [self.y_vocab.get(n, None) for n in doc_ner]
136136
return self.pretty_print(text_arr, tags)

nlp_architect/contrib/tensorflow/python/keras/layers/crf.py

+27-46
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,9 @@
1414
# limitations under the License.
1515
# ******************************************************************************
1616
import tensorflow as tf
17-
from tensorflow import convert_to_tensor, keras
1817

1918

20-
class CRF(keras.layers.Layer):
19+
class CRF(tf.keras.layers.Layer):
2120
"""
2221
Conditional Random Field layer (tf.keras)
2322
`CRF` can be used as the last layer in a network (as a classifier). Input shape (features)
@@ -29,55 +28,36 @@ class CRF(keras.layers.Layer):
2928
3029
Args:
3130
num_labels (int): the number of labels to tag each temporal input.
32-
mode (string, optional): operation mode, 'reg' for regular full sequence learning (all
33-
sequences have equal length), or 'pad' for using with supplied sequence lengths (useful
34-
for padded sequences)
3531
3632
Input shape:
37-
'reg' mode - nD tensor with shape `(batch_size, sentence length, num_classes)`.
38-
'pad' mode - tuple of `(batch_size, sentence length, num_classes)`, `(batch_size, 1)`
33+
nD tensor with shape `(batch_size, sentence length, num_classes)`.
3934
4035
Output shape:
4136
nD tensor with shape: `(batch_size, sentence length, num_classes)`.
4237
"""
43-
def __init__(self, num_classes, mode='reg', **kwargs):
38+
39+
def __init__(self, num_classes, **kwargs):
4440
self.transitions = None
4541
super(CRF, self).__init__(**kwargs)
4642
# num of output labels
4743
self.output_dim = int(num_classes)
48-
self.mode = mode
49-
if self.mode == 'pad':
50-
self.input_spec = [keras.layers.InputSpec(min_ndim=3),
51-
keras.layers.InputSpec(min_ndim=2)]
52-
elif self.mode == 'reg':
53-
self.input_spec = keras.layers.InputSpec(min_ndim=3)
54-
else:
55-
raise ValueError
56-
self.supports_masking = True
44+
self.input_spec = tf.keras.layers.InputSpec(min_ndim=3)
45+
self.supports_masking = False
5746
self.sequence_lengths = None
5847

5948
def get_config(self):
6049
config = {
6150
'output_dim': self.output_dim,
62-
'mode': self.mode,
6351
'supports_masking': self.supports_masking,
6452
'transitions': tf.keras.backend.eval(self.transitions)
6553
}
6654
base_config = super(CRF, self).get_config()
6755
return dict(list(base_config.items()) + list(config.items()))
6856

6957
def build(self, input_shape):
70-
if self.mode == 'pad':
71-
assert len(input_shape) == 2
72-
assert len(input_shape[0]) == 3
73-
assert len(input_shape[1]) == 2
74-
f_shape = tf.TensorShape(input_shape[0])
75-
input_spec = [keras.layers.InputSpec(min_ndim=3, axes={-1: f_shape[-1]}),
76-
keras.layers.InputSpec(min_ndim=2, axes={-1: 1}, dtype=tf.int32)]
77-
else:
78-
assert len(input_shape) == 3
79-
f_shape = tf.TensorShape(input_shape)
80-
input_spec = keras.layers.InputSpec(min_ndim=3, axes={-1: f_shape[-1]})
58+
assert len(input_shape) == 3
59+
f_shape = tf.TensorShape(input_shape)
60+
input_spec = tf.keras.layers.InputSpec(min_ndim=3, axes={-1: f_shape[-1]})
8161

8262
if f_shape[-1] is None:
8363
raise ValueError('The last dimension of the inputs to `CRF` '
@@ -92,21 +72,26 @@ def build(self, input_shape):
9272
trainable=True)
9373
self.built = True
9474

95-
def call(self, inputs, **kwargs):
96-
if self.mode == 'pad':
97-
sequences = convert_to_tensor(inputs[0], dtype=self.dtype)
98-
self.sequence_lengths = tf.keras.backend.flatten(inputs[-1])
75+
# pylint: disable=arguments-differ
76+
def call(self, inputs, sequence_lengths=None, **kwargs):
77+
sequences = tf.convert_to_tensor(inputs, dtype=self.dtype)
78+
if sequence_lengths is not None:
79+
assert len(sequence_lengths.shape) == 2
80+
assert tf.convert_to_tensor(sequence_lengths).dtype == 'int32'
81+
seq_len_shape = tf.convert_to_tensor(sequence_lengths).get_shape().as_list()
82+
assert seq_len_shape[1] == 1
83+
self.sequence_lengths = tf.keras.backend.flatten(sequence_lengths)
9984
else:
100-
sequences = convert_to_tensor(inputs, dtype=self.dtype)
101-
shape = tf.shape(inputs)
102-
self.sequence_lengths = tf.ones(shape[0], dtype=tf.int32) * (shape[1])
85+
self.sequence_lengths = tf.ones(tf.shape(inputs)[0], dtype=tf.int32) * \
86+
(tf.shape(inputs)[1])
87+
10388
viterbi_sequence, _ = tf.contrib.crf.crf_decode(sequences, self.transitions,
10489
self.sequence_lengths)
105-
output = keras.backend.one_hot(viterbi_sequence, self.output_dim)
106-
return keras.backend.in_train_phase(sequences, output)
90+
output = tf.keras.backend.one_hot(viterbi_sequence, self.output_dim)
91+
return tf.keras.backend.in_train_phase(sequences, output)
10792

10893
def loss(self, y_true, y_pred):
109-
y_pred = convert_to_tensor(y_pred, dtype=self.dtype)
94+
y_pred = tf.convert_to_tensor(y_pred, dtype=self.dtype)
11095
log_likelihood, self.transitions = \
11196
tf.contrib.crf.crf_log_likelihood(y_pred,
11297
tf.cast(tf.keras.backend.argmax(y_true),
@@ -116,12 +101,8 @@ def loss(self, y_true, y_pred):
116101
return tf.reduce_mean(-log_likelihood)
117102

118103
def compute_output_shape(self, input_shape):
119-
if self.mode == 'pad':
120-
data_shape = input_shape[0]
121-
else:
122-
data_shape = input_shape
123-
tf.TensorShape(data_shape).assert_has_rank(3)
124-
return data_shape[:2] + (self.output_dim,)
104+
tf.TensorShape(input_shape).assert_has_rank(3)
105+
return input_shape[:2] + (self.output_dim,)
125106

126107
@property
127108
def viterbi_accuracy(self):
@@ -130,7 +111,7 @@ def accuracy(y_true, y_pred):
130111
sequence_lengths = tf.ones(shape[0], dtype=tf.int32) * (shape[1])
131112
viterbi_sequence, _ = tf.contrib.crf.crf_decode(y_pred, self.transitions,
132113
sequence_lengths)
133-
output = keras.backend.one_hot(viterbi_sequence, self.output_dim)
114+
output = tf.keras.backend.one_hot(viterbi_sequence, self.output_dim)
134115
return tf.keras.metrics.categorical_accuracy(y_true, output)
135116
accuracy.func_name = 'viterbi_accuracy'
136117
return accuracy

nlp_architect/data/sequential_tagging.py

-1
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,6 @@ def _read_file(self, filepath):
119119
with open(filepath, encoding='utf-8') as fp:
120120
data = fp.readlines()
121121
data = [d.strip() for d in data]
122-
data = [d for d in data if 'DOCSTART' not in d]
123122
sentences = self._split_into_sentences(data)
124123
parsed_sentences = [self._parse_sentence(s) for s in sentences if len(s) > 0]
125124
return parsed_sentences

nlp_architect/models/chunker.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ def build(self,
134134

135135
model = tf.keras.Model(input_src, [pos_out, chunks_out])
136136
if optimizer is None:
137-
self.optimizer = tf.train.AdamOptimizer()
137+
self.optimizer = tf.keras.optimizers.Adam(0.001, clipnorm=5.)
138138
else:
139139
self.optimizer = optimizer
140140
model.compile(optimizer=self.optimizer,

0 commit comments

Comments
 (0)