ScalaConsultants / Aspect-Based-Sentiment-Analysis

💭 Aspect-Based-Sentiment-Analysis: Transformer & Explainable ML (TensorFlow)
Apache License 2.0
539 stars 91 forks source link

Extract Weights and scores from result #53

Open AymenBenk opened 3 years ago

AymenBenk commented 3 years ago

`import numpy as np import aspect_based_sentiment_analysis as absa from aspect_based_sentiment_analysis import alignment from aspect_based_sentiment_analysis import Example

text = "I love mascara" aspects = ['mascara']

recognizer = absa.aux_models.BasicPatternRecognizer() nlp = absa.load(pattern_recognizer=recognizer) task = nlp(text=text, aspects=aspects) slack = task.examples

print(slack)

[PredictedExample(text='I love mascara', aspect='mascara', sentiment=<Sentiment.positive: 2>, text_tokens=['i', 'love', 'mascara'], text_subtokens=['i', 'love', 'mascara'], aspect_tokens=['mascara'], aspect_subtokens=['mascara'], tokens=['[CLS]', 'i', 'love', 'mascara', '[SEP]', 'mascara', '[SEP]'], subtokens=['[CLS]', 'i', 'love', 'mascara', '[SEP]', 'mascara', '[SEP]'], alignment=[[0], [1], [2], [3], [4], [5], [6]], scores=[0.0005469007, 0.0009526035, 0.99850047], review=Review(is_reference=None, patterns=[Pattern(importance=1.0, tokens=['i', 'love', 'mascara'], weights=[0.28, 1.0, 0.71]), Pattern(importance=0.58, tokens=['i', 'love', 'mascara'], weights=[0.13, 0.58, 0.58]), Pattern(importance=0.25, tokens=['i', 'love', 'mascara'], weights=[0.25, 0.25, 0.17])]))] `

print("###########") print("Aspect :",slack.aspect) print("Sentiment :",slack.sentiment) print("Scores (neutral/negative/positive): ",slack.scores)

print("Tokens :",slack.text_subtokens)

print("Words weights related to the aspect :",slack.review.patterns[0].weights)

word = [] list_numbers = slack.review.patterns[0].weights g = [i for i, n in enumerate(list_numbers) if n > 0.5] # Generator expression for i in range(0,len(g)): word_indx = g[i] word.append(slack.text_subtokens[word_indx]) print(word)

########### Result

########### Aspect : price Sentiment : Sentiment.positive Scores (neutral/negative/positive): [0.0005469007, 0.0009526035, 0.99850047] ['love', 'mascara']

######### Problem Now I receive each time when I run it again:


AttributeError Traceback (most recent call last)

in 1 print("###########") ----> 2 print("Aspect :",slack.aspect) 3 print("Sentiment :",slack.sentiment) 4 print("Scores (neutral/negative/positive): ",slack.scores) 5 print("Tokens :",slack.text_subtokens) AttributeError: 'list' object has no attribute 'aspect' --------------------------------------------------------------------------- AttributeError Traceback (most recent call last) in ----> 1 absa.summary(skin) 2 absa.display(skin.scores) ~\Anaconda3\envs\asba_aymen_setup\lib\site-packages\aspect_based_sentiment_analysis\plots.py in summary(example) 64 65 def summary(example: PredictedExample): ---> 66 print(f'{str(example.sentiment)} for "{example.aspect}"') 67 rounded_scores = np.round(example.scores, decimals=3) 68 print(f'Scores (neutral/negative/positive): {rounded_scores}') AttributeError: 'list' object has no attribute 'sentiment' Can someone help me out please :)
satpalsr commented 2 years ago

Hi @AymenBenk

slack is a list containing a single element and hence you can't do slack.aspect.

One workaround to extract weights, scores and aspect could be as following:

# Convert slack from list to string.
slack = str(slack)

import re
# Replace suitable characters with new line characters.
wei = slack.replace(")", " \n ")
sco = slack.replace("]", " \n ")
asp = slack.replace(",", " \n ")

# Find out the weights, scores and aspect in the above 3 strings.
weights = re.findall(r"\bwei.*", wei)
scores = re.search(r"\bsco.*", sco)
scores = str(scores.group()) + "]"
aspec = re.search(r"\basp.*", asp)

print(weights)
print(scores)
print(aspec.group())

# Results are as following:
['weights=[0.28, 1.0, 0.71] ', 'weights=[0.13, 0.58, 0.58] ', 'weights=[0.25, 0.25, 0.17] ']
scores=[0.0005469012, 0.0009526044, 0.99850047 ]
aspect='mascara' 

The second better approach is:

an_string = str(slack)

# Extract aspect
aspect = an_string.split('aspect=')[1].split(',')[0]
print("aspect", aspect)

# Extract scores
scores = an_string.split("scores=[")[1].split("]")[0].split(",")
scores = [float(score) for score in scores]
print("scores", scores)

# Extract weights
def extract_weights(an_string,i):
    weights = an_string.split("weights=[")[i].split("]")[0].split(",")
    weights = [float(weight) for weight in weights]
    print(weights)

print("weights")
extract_weights(an_string,1)
extract_weights(an_string,2)
extract_weights(an_string,3)

# Results are as following:
aspect 'mascara'
scores [0.0005469007, 0.0009526035, 0.99850047]
weights
[0.28, 1.0, 0.71]
[0.13, 0.58, 0.58]
[0.25, 0.25, 0.17]