Spaces:
Sleeping
Sleeping
update app.py
Browse files- app.py +104 -14
- sample_reviews.txt +12 -0
app.py
CHANGED
@@ -1,38 +1,128 @@
|
|
|
|
|
|
1 |
import gradio as gr
|
|
|
2 |
import numpy
|
3 |
from scipy.special import softmax
|
4 |
|
|
|
|
|
5 |
from transformers import (
|
6 |
AutoTokenizer,
|
7 |
AutoConfig,
|
8 |
AutoModelForSequenceClassification
|
9 |
)
|
10 |
|
|
|
|
|
11 |
model_path = "EmotiScan/amazon-comments-bert"
|
12 |
|
13 |
tokenizer = AutoTokenizer.from_pretrained(model_path)
|
14 |
model = AutoModelForSequenceClassification.from_pretrained(model_path)
|
15 |
|
16 |
-
def get_sentiments(text):
|
17 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
encoded_input = tokenizer(text, return_tensors='pt')
|
19 |
-
|
|
|
20 |
|
21 |
-
|
22 |
-
|
|
|
23 |
|
24 |
-
|
25 |
-
scores = {l:float(s) for (l,s) in zip(
|
26 |
|
27 |
return scores
|
28 |
|
29 |
-
|
30 |
-
fn
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
36 |
|
37 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
38 |
|
|
|
|
1 |
+
from pathlib import Path
|
2 |
+
from collections import Counter
|
3 |
import gradio as gr
|
4 |
+
import pandas as pd
|
5 |
import numpy
|
6 |
from scipy.special import softmax
|
7 |
|
8 |
+
import torch
|
9 |
+
from transformers import pipeline, TextClassificationPipeline
|
10 |
from transformers import (
|
11 |
AutoTokenizer,
|
12 |
AutoConfig,
|
13 |
AutoModelForSequenceClassification
|
14 |
)
|
15 |
|
16 |
+
# model_path = "EmotiScan/amazon-comments-bert" # To use your model, on line 55, you'll have to change i to i+1
|
17 |
+
# model_path = "nlptown/bert-base-multilingual-uncased-sentiment"
|
18 |
model_path = "EmotiScan/amazon-comments-bert"
|
19 |
|
20 |
tokenizer = AutoTokenizer.from_pretrained(model_path)
|
21 |
model = AutoModelForSequenceClassification.from_pretrained(model_path)
|
22 |
|
|
|
23 |
|
24 |
+
description = f"""# <h2 style="text-align: center;"> EmotiScan Amazon Products Review</h2>
|
25 |
+
<p style="text-align: center;font-size:15px;"> (Placeholder description) Analysing Amazon product reviews...
|
26 |
+
Input a single review to predict sentiment or multiple from a text file.</p>
|
27 |
+
"""
|
28 |
+
|
29 |
+
sample_reviews = [
|
30 |
+
"A comfortable pair of boots, but a little difficult to \
|
31 |
+
remove without unlacing. So be prepared to unlace before \
|
32 |
+
removing. Takes a few seconds to get them on and off, but \
|
33 |
+
otherwise a very comfortable, sturdy product.",
|
34 |
+
"Very nice boot, it's narrow whc I wasn't expecting, more \
|
35 |
+
for a not so wide of a foot. My foot is not that wide, but \
|
36 |
+
with socks on it will feel a little tight in the middle and back \
|
37 |
+
of the heel, I would go a half or whole size up.",
|
38 |
+
"If you like to continue having dry skin AND to smell like \
|
39 |
+
the inside of a Shoppers Drug Mart then this product is for you!! \
|
40 |
+
Sadly, I don't care for either of those things. I will continue \
|
41 |
+
to hunt for a moisturizer/shower oil",
|
42 |
+
"I really dislike this product.",
|
43 |
+
"This is the best product ever!."
|
44 |
+
]
|
45 |
+
|
46 |
+
def upload_file(file):
|
47 |
+
return file.name
|
48 |
+
|
49 |
+
def get_sentiments(text):
|
50 |
encoded_input = tokenizer(text, return_tensors='pt')
|
51 |
+
with torch.no_grad():
|
52 |
+
logits = model(**encoded_input).logits
|
53 |
|
54 |
+
logits_list = logits[0].tolist()
|
55 |
+
logits_labels = [model.config.id2label[i]
|
56 |
+
for i in range(0, len(logits_list))]
|
57 |
|
58 |
+
probs = softmax(logits_list)
|
59 |
+
scores = {l:float(s) for (l,s) in zip(logits_labels, probs)}
|
60 |
|
61 |
return scores
|
62 |
|
63 |
+
def get_multiple_sentiments(input_file):
|
64 |
+
with open(input_file) as fn:
|
65 |
+
reviews = fn.readlines()
|
66 |
+
reviews = [review.strip() for review in reviews]
|
67 |
+
|
68 |
+
classifier = pipeline('text-classification',
|
69 |
+
model=model_path)
|
70 |
+
scores = classifier(reviews)
|
71 |
+
scores = [pred['label'] for pred in scores]
|
72 |
+
|
73 |
+
preds = dict(Counter(scores))
|
74 |
+
labels = preds.keys()
|
75 |
+
counts = preds.values()
|
76 |
+
review_counts = pd.DataFrame(
|
77 |
+
{
|
78 |
+
"labels": labels,
|
79 |
+
"counts": counts,
|
80 |
+
}
|
81 |
+
)
|
82 |
+
total = len(scores)
|
83 |
+
|
84 |
+
return gr.BarPlot(
|
85 |
+
review_counts,
|
86 |
+
x="labels",
|
87 |
+
y="counts",
|
88 |
+
title=f"# of Reviews: {total}",
|
89 |
+
tooltip=["labels", "counts"],
|
90 |
+
y_lim=[0, total + 10],
|
91 |
+
min_width=500
|
92 |
+
)
|
93 |
+
|
94 |
+
with gr.Blocks() as demo:
|
95 |
+
with gr.Row():
|
96 |
+
gr.Markdown(value=description)
|
97 |
+
|
98 |
+
with gr.Row():
|
99 |
+
with gr.Column():
|
100 |
+
with gr.Tab("Single Input"):
|
101 |
+
single = True
|
102 |
+
input_text = gr.Textbox(label="Input Text",
|
103 |
+
placeholder="Input the product review...")
|
104 |
+
predict_btn = gr.Button("Get Sentiment")
|
105 |
+
with gr.Accordion("Here are some sample reviews!"):
|
106 |
+
examples = gr.Examples(examples=sample_reviews,
|
107 |
+
inputs=[input_text])
|
108 |
+
with gr.Tab("File Upload"):
|
109 |
+
multiple = True
|
110 |
+
file_output = gr.File()
|
111 |
+
upload_button = gr.UploadButton("Upload a .txt file with each review on a line.",
|
112 |
+
file_types=["text"])
|
113 |
+
upload_button.upload(upload_file, upload_button, file_output)
|
114 |
+
file_predict_btn = gr.Button("Get Sentiments")
|
115 |
+
|
116 |
+
with gr.Column():
|
117 |
+
output = gr.Label(label="Single Prediction")
|
118 |
+
plots = gr.BarPlot(label="Plot Multiple Reviews")
|
119 |
|
120 |
+
predict_btn.click(fn=get_sentiments,
|
121 |
+
inputs=input_text,
|
122 |
+
outputs=output,)
|
123 |
+
# api_name="product_review")
|
124 |
+
file_predict_btn.click(fn=get_multiple_sentiments,
|
125 |
+
inputs=file_output,
|
126 |
+
outputs=plots)
|
127 |
|
128 |
+
demo.launch(share=True)
|
sample_reviews.txt
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Who doesn’t want to be able to roll over in bed and still have their phone charging? Lol
|
2 |
+
Needed the charger urgently and I found a good deal. I was hoping it wouldn’t happen when I bought these, but it did. One of them doesn’t work at all!! The other one is working but it makes the phone hot. What a waste of money. Just buy the original one, people. Very disappointed
|
3 |
+
Best cables you can buy! I will purchase again in the future.
|
4 |
+
Just received Friday and does not charge. Waste my time need to print label and go ninja Van to drop off!
|
5 |
+
Ordered these for their durability and length. I LOVE them because I can now charge my phone by my bed with outlet across the room because of extra cord length. The cord is very strong and constructed of durable fabric that should last for many years...probably longer than the phone. The vulnerable plug connection that often breaks on my devices, is not going to wear over time. These cords are reasonably priced, and exactly what I needed for around the house. They arrived on time and intact. Undoubtedly, each would make a great iPhone user gift. Yay!!!
|
6 |
+
Very well made and work extremely well with all my apple products.
|
7 |
+
Just received Friday and does not charge. Waste my time need to print label and go ninja Van to drop off!
|
8 |
+
Couldn’t use the product.
|
9 |
+
Recharge très rapide.
|
10 |
+
I am very picky about material and these pajamas are amazing and very soft and feel nice on the skin. I paid triple the price for the same pajamas at Knix- and these are 100 times better and a great price.
|
11 |
+
They looked great and my mom said she loved them. Soft nice purple colour. Correct sizing.
|
12 |
+
Very soft and decent quality
|