Skip to content

Commit

Permalink
TableQuestionAnsweringPipeline (#9145)
Browse files Browse the repository at this point in the history
* AutoModelForTableQuestionAnswering

* TableQuestionAnsweringPipeline

* Apply suggestions from Patrick's code review

Co-authored-by: Patrick von Platen <patrick.v.platen@gmail.com>

* Sylvain and Patrick comments

* Better PyTorch/TF error message

* Add integration tests

* Argument Handler naming

Co-authored-by: patrickvonplaten <patrick.v.platen@gmail.com>

* Fix docs to appease the documentation gods

Co-authored-by: Patrick von Platen <patrick.v.platen@gmail.com>
  • Loading branch information
LysandreJik and patrickvonplaten committed Dec 16, 2020
1 parent 07384ba commit 1c1a2ff
Show file tree
Hide file tree
Showing 8 changed files with 602 additions and 27 deletions.
8 changes: 8 additions & 0 deletions docs/source/main_classes/pipelines.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ There are two categories of pipeline abstractions to be aware about:
- :class:`~transformers.TranslationPipeline`
- :class:`~transformers.ZeroShotClassificationPipeline`
- :class:`~transformers.Text2TextGenerationPipeline`
- :class:`~transformers.TableQuestionAnsweringPipeline`

The pipeline abstraction
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down Expand Up @@ -91,6 +92,13 @@ SummarizationPipeline
:special-members: __call__
:members:

TableQuestionAnsweringPipeline
=======================================================================================================================

.. autoclass:: transformers.TableQuestionAnsweringPipeline
:special-members: __call__


TextClassificationPipeline
=======================================================================================================================

Expand Down
1 change: 1 addition & 0 deletions src/transformers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@
PipelineDataFormat,
QuestionAnsweringPipeline,
SummarizationPipeline,
TableQuestionAnsweringPipeline,
Text2TextGenerationPipeline,
TextClassificationPipeline,
TextGenerationPipeline,
Expand Down
13 changes: 13 additions & 0 deletions src/transformers/file_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,13 @@ def wrapper(*args, **kwargs):
"""


# docstyle-ignore
PANDAS_IMPORT_ERROR = """
{0} requires the pandas library but it was not found in your environment. You can install it with pip as
explained here: https://pandas.pydata.org/pandas-docs/stable/getting_started/install.html.
"""


def requires_datasets(obj):
name = obj.__name__ if hasattr(obj, "__name__") else obj.__class__.__name__
if not is_datasets_available():
Expand Down Expand Up @@ -522,6 +529,12 @@ def requires_protobuf(obj):
raise ImportError(PROTOBUF_IMPORT_ERROR.format(name))


def requires_pandas(obj):
name = obj.__name__ if hasattr(obj, "__name__") else obj.__class__.__name__
if not is_pandas_available():
raise ImportError(PANDAS_IMPORT_ERROR.format(name))


def requires_scatter(obj):
name = obj.__name__ if hasattr(obj, "__name__") else obj.__class__.__name__
if not is_scatter_available():
Expand Down
49 changes: 33 additions & 16 deletions src/transformers/models/tapas/configuration_tapas.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,41 +87,49 @@ class TapasConfig(PretrainedConfig):
Importance weight for the regression loss.
use_normalized_answer_loss (:obj:`bool`, `optional`, defaults to :obj:`False`):
Whether to normalize the answer loss by the maximum of the predicted and expected value.
huber_loss_delta: (:obj:`float`, `optional`):
huber_loss_delta (:obj:`float`, `optional`):
Delta parameter used to calculate the regression loss.
temperature: (:obj:`float`, `optional`, defaults to 1.0):
temperature (:obj:`float`, `optional`, defaults to 1.0):
Value used to control (OR change) the skewness of cell logits probabilities.
aggregation_temperature: (:obj:`float`, `optional`, defaults to 1.0):
aggregation_temperature (:obj:`float`, `optional`, defaults to 1.0):
Scales aggregation logits to control the skewness of probabilities.
use_gumbel_for_cells: (:obj:`bool`, `optional`, defaults to :obj:`False`):
use_gumbel_for_cells (:obj:`bool`, `optional`, defaults to :obj:`False`):
Whether to apply Gumbel-Softmax to cell selection.
use_gumbel_for_aggregation: (:obj:`bool`, `optional`, defaults to :obj:`False`):
use_gumbel_for_aggregation (:obj:`bool`, `optional`, defaults to :obj:`False`):
Whether to apply Gumbel-Softmax to aggregation selection.
average_approximation_function: (:obj:`string`, `optional`, defaults to :obj:`"ratio"`):
average_approximation_function (:obj:`string`, `optional`, defaults to :obj:`"ratio"`):
Method to calculate the expected average of cells in the weak supervision case. One of :obj:`"ratio"`,
:obj:`"first_order"` or :obj:`"second_order"`.
cell_selection_preference: (:obj:`float`, `optional`):
cell_selection_preference (:obj:`float`, `optional`):
Preference for cell selection in ambiguous cases. Only applicable in case of weak supervision for
aggregation (WTQ, WikiSQL). If the total mass of the aggregation probabilities (excluding the "NONE"
operator) is higher than this hyperparameter, then aggregation is predicted for an example.
answer_loss_cutoff: (:obj:`float`, `optional`):
answer_loss_cutoff (:obj:`float`, `optional`):
Ignore examples with answer loss larger than cutoff.
max_num_rows: (:obj:`int`, `optional`, defaults to 64):
max_num_rows (:obj:`int`, `optional`, defaults to 64):
Maximum number of rows.
max_num_columns: (:obj:`int`, `optional`, defaults to 32):
max_num_columns (:obj:`int`, `optional`, defaults to 32):
Maximum number of columns.
average_logits_per_cell: (:obj:`bool`, `optional`, defaults to :obj:`False`):
average_logits_per_cell (:obj:`bool`, `optional`, defaults to :obj:`False`):
Whether to average logits per cell.
select_one_column: (:obj:`bool`, `optional`, defaults to :obj:`True`):
select_one_column (:obj:`bool`, `optional`, defaults to :obj:`True`):
Whether to constrain the model to only select cells from a single column.
allow_empty_column_selection: (:obj:`bool`, `optional`, defaults to :obj:`False`):
allow_empty_column_selection (:obj:`bool`, `optional`, defaults to :obj:`False`):
Whether to allow not to select any column.
init_cell_selection_weights_to_zero: (:obj:`bool`, `optional`, defaults to :obj:`False`):
init_cell_selection_weights_to_zero (:obj:`bool`, `optional`, defaults to :obj:`False`):
Whether to initialize cell selection weights to 0 so that the initial probabilities are 50%.
reset_position_index_per_cell: (:obj:`bool`, `optional`, defaults to :obj:`True`):
reset_position_index_per_cell (:obj:`bool`, `optional`, defaults to :obj:`True`):
Whether to restart position indexes at every cell (i.e. use relative position embeddings).
disable_per_token_loss: (:obj:`bool`, `optional`, defaults to :obj:`False`):
disable_per_token_loss (:obj:`bool`, `optional`, defaults to :obj:`False`):
Whether to disable any (strong or weak) supervision on cells.
aggregation_labels (:obj:`Dict[int, label]`, `optional`):
The aggregation labels used to aggregate the results. For example, the WTQ models have the following
aggregation labels: :obj:`{0: "NONE", 1: "SUM", 2: "AVERAGE", 3: "COUNT"}`
no_aggregation_label_index (:obj:`int`, `optional`):
If the aggregation labels are defined and one of these labels represents "No aggregation", this should be
set to its index. For example, the WTQ models have the "NONE" aggregation label at index 0, so that value
should be set to 0 for these models.
Example::
Expand Down Expand Up @@ -174,6 +182,8 @@ def __init__(
init_cell_selection_weights_to_zero=False,
reset_position_index_per_cell=True,
disable_per_token_loss=False,
aggregation_labels=None,
no_aggregation_label_index=None,
**kwargs
):

Expand Down Expand Up @@ -217,3 +227,10 @@ def __init__(
self.init_cell_selection_weights_to_zero = init_cell_selection_weights_to_zero
self.reset_position_index_per_cell = reset_position_index_per_cell
self.disable_per_token_loss = disable_per_token_loss

# Aggregation hyperparameters
self.aggregation_labels = aggregation_labels
self.no_aggregation_label_index = no_aggregation_label_index

if isinstance(self.aggregation_labels, dict):
self.aggregation_labels = {int(k): v for k, v in aggregation_labels.items()}
18 changes: 10 additions & 8 deletions src/transformers/models/tapas/tokenization_tapas.py
Original file line number Diff line number Diff line change
Expand Up @@ -1905,12 +1905,14 @@ def convert_logits_to_predictions(self, data, logits, logits_agg=None, cell_clas
this threshold will be selected.
Returns:
:obj:`tuple` comprising various elements depending on the inputs: predicted_answer_coordinates
(``List[List[[tuple]]`` of length ``batch_size``): Predicted answer coordinates as a list of lists of
tuples. Each element in the list contains the predicted answer coordinates of a single example in the
batch, as a list of tuples. Each tuple is a cell, i.e. (row index, column index).
predicted_aggregation_indices (`optional`, returned when ``logits_aggregation`` is provided) ``List[int]``
of length ``batch_size``: Predicted aggregation operator indices of the aggregation head.
:obj:`tuple` comprising various elements depending on the inputs:
- predicted_answer_coordinates (``List[List[[tuple]]`` of length ``batch_size``): Predicted answer
coordinates as a list of lists of tuples. Each element in the list contains the predicted answer
coordinates of a single example in the batch, as a list of tuples. Each tuple is a cell, i.e. (row index,
column index).
- predicted_aggregation_indices (``List[int]``of length ``batch_size``, `optional`, returned when
``logits_aggregation`` is provided): Predicted aggregation operator indices of the aggregation head.
"""
# input data is of type float32
# np.log(np.finfo(np.float32).max) = 88.72284
Expand Down Expand Up @@ -1969,11 +1971,11 @@ def convert_logits_to_predictions(self, data, logits, logits_agg=None, cell_clas
answer_coordinates = sorted(answer_coordinates)
predicted_answer_coordinates.append(answer_coordinates)

output = predicted_answer_coordinates
output = (predicted_answer_coordinates,)

if logits_agg is not None:
predicted_aggregation_indices = logits_agg.argmax(dim=-1)
output = (output, predicted_aggregation_indices.tolist())
output = (predicted_answer_coordinates, predicted_aggregation_indices.tolist())

return output

Expand Down

0 comments on commit 1c1a2ff

Please sign in to comment.