|
import streamlit as st |
|
import tensorflow as tf |
|
from tensorflow.keras.models import Sequential |
|
from tensorflow.keras.layers import Input, Embedding, Bidirectional, LSTM, Dropout, Dense |
|
from tensorflow.keras.preprocessing.text import Tokenizer |
|
from tensorflow.keras.preprocessing.sequence import pad_sequences |
|
import numpy as np |
|
import pickle |
|
|
|
|
|
max_sequence_length = 100 |
|
embedding_dim = 100 |
|
|
|
def create_model(vocab_size): |
|
""" |
|
Creates a Bidirectional LSTM model for sentiment analysis |
|
|
|
Args: |
|
vocab_size: Size of the vocabulary (number of unique words + 1) |
|
|
|
Returns: |
|
Compiled Keras model |
|
""" |
|
model = Sequential([ |
|
Input(shape=(max_sequence_length,)), |
|
Embedding(input_dim=vocab_size, output_dim=embedding_dim), |
|
Bidirectional(LSTM(128, return_sequences=False)), |
|
Dropout(0.5), |
|
Dense(64, activation='relu'), |
|
Dropout(0.5), |
|
Dense(3, activation='softmax') |
|
]) |
|
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy']) |
|
return model |
|
|
|
@st.cache_resource |
|
def load_model_and_tokenizer(): |
|
""" |
|
Loads the pretrained model and tokenizer |
|
|
|
Returns: |
|
tuple: (model, tokenizer) |
|
""" |
|
|
|
with open('tokenizer.pickle', 'rb') as handle: |
|
tokenizer = pickle.load(handle) |
|
|
|
|
|
vocab_size = len(tokenizer.word_index) + 1 |
|
model = create_model(vocab_size) |
|
model.load_weights('lstm.keras') |
|
return model, tokenizer |
|
|
|
def preprocess_text(text, tokenizer): |
|
""" |
|
Preprocesses input text for model prediction |
|
|
|
Args: |
|
text: Input text string |
|
tokenizer: Keras tokenizer object |
|
|
|
Returns: |
|
Padded sequence ready for model input |
|
""" |
|
sequences = tokenizer.texts_to_sequences([text]) |
|
return pad_sequences(sequences, maxlen=max_sequence_length) |
|
|
|
def main(): |
|
"""Main function for the Streamlit app""" |
|
st.title("Sentiment Analyzer") |
|
|
|
try: |
|
|
|
model, tokenizer = load_model_and_tokenizer() |
|
except Exception as e: |
|
st.error(f"Error loading model: {str(e)}") |
|
return |
|
|
|
|
|
text = st.text_area("Enter text to analyze:", height=150) |
|
|
|
if st.button("Analyze"): |
|
if text: |
|
|
|
processed_text = preprocess_text(text, tokenizer) |
|
prediction = model.predict(processed_text) |
|
sentiments = ['Negative', 'Neutral', 'Positive'] |
|
result = sentiments[np.argmax(prediction)] |
|
|
|
|
|
st.write(f"Detected sentiment: **{result}**") |
|
|
|
|
|
probabilities = prediction[0] |
|
for sent, prob in zip(sentiments, probabilities): |
|
st.progress(float(prob)) |
|
st.write(f"{sent}: {prob:.2%}") |
|
else: |
|
st.warning("Please enter text to analyze.") |
|
|
|
if __name__ == "__main__": |
|
main() |