nlp / app.py
ElijahDi's picture
Update app.py
c48cffe verified
import streamlit as st
import numpy as np
import pandas as pd
import time
import torch
import torch.nn as nn
from torch import tensor
import joblib
from dataclasses import dataclass
from transformers import AutoTokenizer, AutoModel, AutoModelForSequenceClassification, GPT2LMHeadModel, GPT2Tokenizer, GPT2Config
import json
from preprocessing import predict_review, data_preprocessing_hard
from model_lstm import LSTMClassifier
# from BERT_inputs import BertInputs
device = 'cpu'
classifier_bag = joblib.load('classifier_bag.pkl')
classifier_tf = joblib.load('classifier_tf.pkl')
BERT_lin_cl = joblib.load('BERT_base_model.pkl')
selected_model = st.sidebar.radio("Зачем пришел?", ("Классифиция отзывов лечебных учреждений",
"Оценка степени токсичности пользовательского сообщения",
"Генерация текста GPT-моделью по пользовательскому prompt"))
# Классификация отзыва на поликлиники
if selected_model == "Классифиция отзывов лечебных учреждений":
st.title("""
Приложение классифицирует твой отзыв и подскажет, позитивный он или негативный
""")
st.write("""
Классификация происходит с использованием классических ML моделей, нейросетевой модели LSTM,
и, как вариант, с использованием нейросетевой модели Bert-basic-ru для векторизации и линейной
регрессии для классификации.
""")
vectorizer_1 = joblib.load('vectorizer_bag.joblib')
vectorizer_2 = joblib.load('vectorizer_tf.joblib')
# LSTM
with open('vocab_lstm.json', 'r') as file:
vocab_to_int = json.load(file)
@dataclass
class ConfigRNN:
vocab_size: int
device : str
n_layers : int
embedding_dim : int
hidden_size : int
seq_len : int
bidirectional : bool or int
net_config = ConfigRNN(
vocab_size = len(vocab_to_int)+1,
device='cpu',
n_layers=2,
embedding_dim=64,
hidden_size=32,
seq_len = 100,
bidirectional=False)
lstm = LSTMClassifier(net_config)
lstm.load_state_dict(torch.load('lstm_model.pth', map_location=device))
lstm.to(device)
# lstm.eval()
# BERT
tokenizer = AutoTokenizer.from_pretrained("Geotrend/bert-base-ru-cased")
model = AutoModel.from_pretrained("Geotrend/bert-base-ru-cased")
# model.eval()
MAX_LEN = 200
data = pd.DataFrame({
'Модель': ["BagOfWords", "TF-IDF", "LSTM", "BERT-based-ru"],
'f1_macro': [0.934, 0.939, 0.831, 0.845]
})
st.subheader("""
Немного информации о точности используемых моделей после обучения:
""")
# st.write(data)
st.table(data)
user_text_input = st.text_area('Введите ваш отзыв здесь:', '')
if st.button('Предсказать'):
start_time = time.time()
predictions = []
prediction_time = []
X = vectorizer_1.transform([data_preprocessing_hard(user_text_input)])
predictions.append(classifier_bag.predict(X))
end_time = time.time()
prediction_time.append(end_time - start_time)
start_time = time.time()
X1 = vectorizer_2.transform([data_preprocessing_hard(user_text_input)])
predictions.append(classifier_tf.predict(X1))
end_time = time.time()
prediction_time.append(end_time - start_time)
start_time = time.time()
predictions.append(predict_review(model=lstm, review_text=user_text_input, net_config=net_config,
vocab_to_int=vocab_to_int))
end_time = time.time()
prediction_time.append(end_time - start_time)
tokens = tokenizer.encode(user_text_input, add_special_tokens=True)
padded_tokens = tokens + [0] * (MAX_LEN - len(tokens))
input_tensor = tensor(padded_tokens).unsqueeze(0)
with torch.no_grad():
outputs = model(input_tensor)
X2 = outputs.last_hidden_state[:,0,:].detach().cpu().numpy()
predictions.append(BERT_lin_cl.predict(X2))
end_time = time.time()
prediction_time.append(end_time - start_time)
res = []
for i in predictions:
if i >= 0.5:
res.append('Позитивный комментарий')
else:
res.append('Негативный комментарий')
result = pd.DataFrame({
'Модель': ["BagOfWords", "TF-IDF", "LSTM", "BERT-based-ru"],
'Результат': res,
'Время предсказания' : prediction_time
})
st.table(result)
if len(result[result['Результат'] == 'Негативный комментарий']) >= 2:
gif_url = 'https://i.gifer.com/LdC3.gif'
st.image(gif_url, caption="Негативный коментарий")
else:
gif_url = 'https://media2.giphy.com/media/v1.Y2lkPTc5MGI3NjExOTdnYjJ1eTE0bjRuMGptcjhpdTk2YTYzeXEzMzlidWFsamY2bW8wZyZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/LUg1GEjapflW7Vg6B9/giphy.gif'
st.image(gif_url, caption="Позитивный коментарий")
# Оценка степени токсичности пользовательского сообщения
elif selected_model == "Оценка степени токсичности пользовательского сообщения":
st.title("""
Приложение классифицирует, токсичный комментарий или нет
""")
st.write("""
Классификация происходит с использованием нейросетевой модели rubert-tiny-toxicity.
""")
# Toxicity
model_t_checkpoint = 'cointegrated/rubert-tiny-toxicity'
tokenizer_t = AutoTokenizer.from_pretrained(model_t_checkpoint)
model_t = AutoModelForSequenceClassification.from_pretrained(model_t_checkpoint)
def text2toxicity(text, aggregate=True):
with torch.no_grad():
inputs = tokenizer_t(text, return_tensors='pt', truncation=True, padding=True).to(model_t.device)
proba = torch.sigmoid(model_t(**inputs).logits).cpu().numpy()
if isinstance(text, str):
proba = proba[0]
if aggregate:
return 1 - proba.T[0] * (1 - proba.T[-1])
return proba
user_text_input = st.text_area('Введите ваш отзыв здесь:')
if st.button('Предсказать'):
start_time = time.time()
proba = text2toxicity(user_text_input, True)
end_time = time.time()
prediction_time = end_time - start_time
model_message = f'Предсказание модели:'
if proba >= 0.5:
st.write(f'Степень токсичности комментария {round(proba, 2)*100}%')
gif_url = "https://media1.giphy.com/media/cInbau65cwPWUeGTIZ/giphy.gif?cid=6c09b952seqdtvky8yn2uq6bt3kvo1vu5sdzpkdznjvmtxsh&ep=v1_internal_gif_by_id&rid=giphy.gif&ct=s"
st.image(gif_url, caption="ТОКСИК")
else:
st.write(f'Степень токсичности комментария {round(proba, 2)*100}%')
gif_url = 'https://i.gifer.com/origin/51/518fbbf9cf32763122f9466d3c686bb3_w200.gif'
st.image(gif_url, caption="МИЛОТА")
st.write(f'Время предсказания: {prediction_time:.4f} секунд')
# Генерация текста GPT
elif selected_model == "Генерация текста GPT-моделью по пользовательскому prompt":
st.title("""
Нейросетевой гороскоп Якубовский-Дьяченко
""")
st.write("""
Для генерации текста используется предобученная сеть GPT2. Дообучение проходило на гороскопах.
Общая длина текста для обучения 37 001 887 слов.
""")
user_text_input = st.text_area('Введите текст для формиорования гороскопа:')
# GPT2
path = 'model_pretra/'
model = GPT2LMHeadModel.from_pretrained(path).to(device)
tokenizer = GPT2Tokenizer.from_pretrained(path)
temperature = st.slider('Градус дичи', 0.1, 2.0, 1.1, step=0.1)
max_gen_length = st.slider('Максимальная длина генерации', 10, 500, 100, step=10)
num_generations = st.slider('Количество генераций', 1, 10, 2, step=1)
if st.button('Сделать гороскоп'):
with st.spinner('Генерация текста...'):
start_time = time.time()
input_ids = tokenizer.encode(user_text_input, return_tensors="pt").to(device)
model.eval()
with torch.no_grad():
out = model.generate(
input_ids,
do_sample=True,
num_beams=num_generations,
temperature=temperature,
top_p=0.9,
max_length=max_gen_length,
)
generated_text = tokenizer.decode(out[0], skip_special_tokens=True)
end_time = time.time()
prediction_time = end_time - start_time
st.write(f'{generated_text}')