From 59f05b714b712d8b092c8e944659bbcf466c58d0 Mon Sep 17 00:00:00 2001 From: rolczynski Date: Thu, 29 Oct 2020 12:42:43 +0100 Subject: [PATCH] Refactor basic pattern recognizer --- aspect_based_sentiment_analysis/aux_models.py | 26 +++++++++---------- tests/absa/test_aux_models.py | 7 +++-- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/aspect_based_sentiment_analysis/aux_models.py b/aspect_based_sentiment_analysis/aux_models.py index 6d16bff..bbc72ae 100755 --- a/aspect_based_sentiment_analysis/aux_models.py +++ b/aspect_based_sentiment_analysis/aux_models.py @@ -4,7 +4,6 @@ from typing import Set from typing import Tuple from dataclasses import dataclass -from dataclasses import field import numpy as np import tensorflow as tf @@ -52,27 +51,28 @@ class BasicReferenceRecognizer(ReferenceRecognizer, PretrainedConfig): """ The Basic Reference Recognizer predicts whether a text relates to an aspect or not. Briefly, it represents a text and an aspect as two - vectors, and predicts that a text relates to an aspect if the cosine - similarity is bigger than a threshold. It calculates text and aspect + vectors, measure cosine similarity between them, and then use the simple + logistic regression to make a prediction. It calculates text and aspect representations by summing their subtoken vectors, context-independent - embeddings that come from the embedding first layer. - - This model has only one parameter, nonetheless, we show how to take a use - of the methods `save_pretrained` and `load_pretrained`. They are useful - especially for more complex models. + embeddings that come from the embedding first layer. This model has two + parameter (β_0, β_1). Benefit from two useful methods `save_pretrained` + and `load_pretrained` (to persist the model for future use). """ - threshold: float - model_type: str = field(default='reference_recognizer') + weights: Tuple[float, float] + model_type: str = 'reference_recognizer' def __call__( self, example: TokenizedExample, output: Output ) -> bool: + β_0, β_1 = self.weights + n = len(example.subtokens) + hidden_states = output.hidden_states[:, :n, :] # Trim padded tokens. text_mask, aspect_mask = self.text_aspect_subtoken_masks(example) - similarity = self.transform(output.hidden_states, text_mask, aspect_mask) - is_reference = bool(similarity > self.threshold) - return is_reference + similarity = self.transform(hidden_states, text_mask, aspect_mask) + is_reference = β_0 + β_1 * similarity > 0 + return bool(is_reference) # Do not use the numpy bool object. @staticmethod def transform( diff --git a/tests/absa/test_aux_models.py b/tests/absa/test_aux_models.py index 22af821..691cf09 100644 --- a/tests/absa/test_aux_models.py +++ b/tests/absa/test_aux_models.py @@ -16,7 +16,7 @@ def test_basic_reference_recognizer(): text = 'the automobile is so cool and the service is prompt and curious.' examples = [Example(text, 'breakfast'), Example(text, 'service'), Example(text, 'car')] - recognizer = BasicReferenceRecognizer(threshold=0.08) + recognizer = BasicReferenceRecognizer(weights=(-0.025, 44)) nlp = absa.load('absa/classifier-rest-0.2', reference_recognizer=recognizer) predictions = nlp.transform(examples) prediction_1, prediction_2, prediction_3 = predictions @@ -28,7 +28,10 @@ def test_basic_reference_recognizer(): def test_basic_reference_recognizer_from_pretrained(): name = 'absa/basic_reference_recognizer-rest-0.1' recognizer = BasicReferenceRecognizer.from_pretrained(name) - assert recognizer.threshold == 0.08 + assert np.allclose(recognizer.weights, [-0.024, 44.443], atol=0.001) + name = 'absa/basic_reference_recognizer-lapt-0.1' + recognizer = BasicReferenceRecognizer.from_pretrained(name) + assert np.allclose(recognizer.weights, [-0.175, 40.165], atol=0.001) def test_basic_reference_recognizer_transform():