Chapter 13: Project: Sentiment Analysis Dashboard
13.4 Developing the Dashboard Interface
Developing an intuitive and interactive dashboard interface is crucial for allowing users to interact with the sentiment analysis models, upload text data, and visualize the results. In this section, we will discuss how to build a web-based dashboard interface using Flask, a lightweight web framework for Python, along with HTML, CSS, and JavaScript for the frontend. We will also integrate data visualization libraries such as Plotly to create interactive charts.
13.4.1 Setting Up Flask
First, ensure Flask is installed if it hasn't been already:
pip install Flask
Next, let's set up the basic structure of our Flask application.
from flask import Flask, request, render_template, jsonify
import pickle
import numpy as np
from tensorflow.keras.models import load_model
from tensorflow.keras.preprocessing.sequence import pad_sequences
app = Flask(__name__)
# Load the LSTM model and tokenizer
lstm_model = load_model('models/lstm_model.h5')
with open('models/tokenizer.pickle', 'rb') as file:
tokenizer = pickle.load(file)
# Load the Logistic Regression model
with open('models/best_logistic_regression_model.pickle', 'rb') as file:
logistic_regression_model = pickle.load(file)
# Define function to preprocess text
def preprocess_text(text):
max_length = 200
sequences = tokenizer.texts_to_sequences([text])
padded_sequences = pad_sequences(sequences, maxlen=max_length, padding='post', truncating='post')
return padded_sequences
@app.route('/')
def home():
return render_template('index.html')
@app.route('/analyze', methods=['POST'])
def analyze():
text = request.form['text']
model_type = request.form['model_type']
preprocessed_text = preprocess_text(text)
if model_type == 'lstm':
prediction_prob = lstm_model.predict(preprocessed_text)
prediction = (prediction_prob > 0.5).astype(int)
else:
prediction = logistic_regression_model.predict(preprocessed_text)
sentiment = 'Positive' if prediction[0] == 1 else 'Negative'
return jsonify({'sentiment': sentiment})
if __name__ == '__main__':
app.run(debug=True)
In this script, we define the basic routes for our Flask application:
- The
home
route renders the home page. - The
analyze
route processes the text input, uses the selected model to predict sentiment, and returns the result as JSON.
13.4.2 Creating HTML Templates
Next, we will create HTML templates to render the web pages. We will use Bootstrap for styling to create a responsive and visually appealing interface.
templates/index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sentiment Analysis Dashboard</title>
<link rel="stylesheet" href="<https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css>">
</head>
<body>
<div class="container">
<h1 class="mt-5">Sentiment Analysis Dashboard</h1>
<form id="analysis-form" class="mt-4">
<div class="form-group">
<label for="text">Enter Text</label>
<textarea class="form-control" id="text" name="text" rows="3" required></textarea>
</div>
<div class="form-group">
<label for="model_type">Select Model</label>
<select class="form-control" id="model_type" name="model_type" required>
<option value="logistic_regression">Logistic Regression</option>
<option value="lstm">LSTM</option>
</select>
</div>
<button type="submit" class="btn btn-primary">Analyze Sentiment</button>
</form>
<div id="result" class="mt-4"></div>
</div>
<script src="<https://code.jquery.com/jquery-3.5.1.min.js>"></script>
<script>
$(document).ready(function() {
$('#analysis-form').on('submit', function(event) {
event.preventDefault();
const formData = $(this).serialize();
$.post('/analyze', formData, function(data) {
$('#result').html(`<h3>Sentiment: ${data.sentiment}</h3>`);
});
});
});
</script>
</body>
</html>
In this HTML template, we create a simple form to enter text and select the model type. When the form is submitted, an AJAX request is sent to the /analyze
endpoint, and the result is displayed on the page.
13.4.3 Adding Data Visualization
Data visualization helps users understand the sentiment analysis results more effectively. We will use Plotly, a graphing library, to create interactive charts.
app.py (continued):
import plotly.express as px
import pandas as pd
@app.route('/visualize', methods=['GET'])
def visualize():
# Example data for visualization
data = {
'Text': ['I love this!', 'I hate this!', 'This is amazing!', 'This is terrible!'],
'Sentiment': ['Positive', 'Negative', 'Positive', 'Negative']
}
df = pd.DataFrame(data)
fig = px.histogram(df, x='Sentiment', title='Sentiment Distribution')
graph_html = fig.to_html(full_html=False)
return render_template('visualize.html', graph_html=graph_html)
# HTML template for visualization
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sentiment Analysis Visualization</title>
<link rel="stylesheet" href="<https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css>">
</head>
<body>
<div class="container">
<h1 class="mt-5">Sentiment Analysis Visualization</h1>
<div id="graph-container">
{{ graph_html | safe }}
</div>
</div>
</body>
</html>
In this example, we create a route /visualize
that generates a simple histogram of sentiment distribution using Plotly. The generated chart is rendered in the visualize.html
template.
13.4.4 Uploading Text Data
Allowing users to upload text data for sentiment analysis enhances the functionality of the dashboard. We will add an option for users to upload CSV files containing text data.
app.py (continued):
import os
from werkzeug.utils import secure_filename
UPLOAD_FOLDER = 'data/uploads'
ALLOWED_EXTENSIONS = {'csv'}
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
if 'file' not in request.files:
return jsonify({'message': 'No file part'})
file = request.files['file']
if file.filename == '':
return jsonify({'message': 'No selected file'})
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
return jsonify({'message': 'File uploaded successfully'})
return render_template('upload.html')
# HTML template for file upload
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Upload Text Data</title>
<link rel="stylesheet" href="<https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css>">
</head>
<body>
<div class="container">
<h1 class="mt-5">Upload Text Data for Sentiment Analysis</h1>
<form action="/upload" method="post" enctype="multipart/form-data" class="mt-4">
<div class="form-group">
<label for="file">Choose CSV File</label>
<input type="file" class="form-control-file" id="file" name="file" required>
</div>
<button type="submit" class="btn btn-primary">Upload</button>
</form>
</div>
</body>
</html>
In this example, we create a route /upload
that handles file uploads. The uploaded CSV file is saved in the data/uploads
directory. We also create an HTML template upload.html
with a form to upload the file.
13.4.5 Integrating All Components
Finally, we integrate all components to create a comprehensive dashboard interface that allows users to analyze text data, visualize results, and upload new data.
app.py (final):
from flask import Flask, request, render_template, jsonify
import pickle
import numpy as np
from tensorflow.keras.models import load_model
from tensorflow.keras.preprocessing.sequence import pad_sequences
import plotly.express as px
import pandas as pd
import os
from werkzeug.utils import secure_filename
app = Flask(__name__)
# Load models and tokenizer
lstm_model = load_model('models/lstm_model.h5')
with open('models/tokenizer.pickle', 'rb') as file:
tokenizer = pickle.load(file)
with open('models/best_logistic_regression_model.pickle', 'rb') as file:
logistic_regression_model = pickle.load(file)
# Set upload folder and allowed extensions
UPLOAD_FOLDER = 'data/uploads'
ALLOWED_EXTENSIONS = {'csv'}
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
# Preprocess text
def preprocess_text(text):
max_length = 200
sequences = tokenizer.texts_to_sequences([text])
padded_sequences = pad_sequences(sequences, maxlen=max_length, padding='post', truncating='post')
return padded_sequences
@app.route('/')
def home():
return render_template('index.html')
@app.route('/analyze', methods=['POST'])
def analyze():
text = request.form['text']
model_type = request.form['model_type']
preprocessed_text = preprocess_text(text)
if model_type == 'lstm':
prediction_prob = lstm_model.predict(preprocessed_text)
prediction = (prediction_prob > 0.5).astype(int)
else:
prediction = logistic_regression_model.predict(preprocessed_text)
sentiment = 'Positive' if prediction[0] == 1 else 'Negative'
return jsonify({'sentiment': sentiment})
@app.route('/visualize', methods=['GET'])
def visualize():
data = {
'Text': ['I love this!', 'I hate this!', 'This is amazing!', 'This is terrible!'],
'Sentiment': ['Positive', 'Negative', 'Positive', 'Negative']
}
df = pd.DataFrame(data)
fig = px.histogram(df, x='Sentiment', title='Sentiment Distribution')
graph_html = fig.to_html(full_html=False)
return render_template('visualize.html', graph_html=graph_html)
@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
if 'file' not in request.files:
return jsonify({'message': 'No file part'})
file = request.files['file']
if file.filename == '':
return jsonify({'message': 'No selected file'})
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
return jsonify({'message': 'File uploaded successfully'})
return render_template('upload.html')
if __name__ == '__main__':
app.run(debug=True)
So far, we have developed the dashboard interface for the sentiment analysis project. We used Flask to create a web-based interface and integrated HTML, CSS, and JavaScript for the frontend. We also added data visualization using Plotly and enabled file uploads for user-generated text data.
By following these steps, we created a comprehensive dashboard that allows users to interact with the sentiment analysis models, upload data, and visualize the results in an intuitive and interactive way.
13.4 Developing the Dashboard Interface
Developing an intuitive and interactive dashboard interface is crucial for allowing users to interact with the sentiment analysis models, upload text data, and visualize the results. In this section, we will discuss how to build a web-based dashboard interface using Flask, a lightweight web framework for Python, along with HTML, CSS, and JavaScript for the frontend. We will also integrate data visualization libraries such as Plotly to create interactive charts.
13.4.1 Setting Up Flask
First, ensure Flask is installed if it hasn't been already:
pip install Flask
Next, let's set up the basic structure of our Flask application.
from flask import Flask, request, render_template, jsonify
import pickle
import numpy as np
from tensorflow.keras.models import load_model
from tensorflow.keras.preprocessing.sequence import pad_sequences
app = Flask(__name__)
# Load the LSTM model and tokenizer
lstm_model = load_model('models/lstm_model.h5')
with open('models/tokenizer.pickle', 'rb') as file:
tokenizer = pickle.load(file)
# Load the Logistic Regression model
with open('models/best_logistic_regression_model.pickle', 'rb') as file:
logistic_regression_model = pickle.load(file)
# Define function to preprocess text
def preprocess_text(text):
max_length = 200
sequences = tokenizer.texts_to_sequences([text])
padded_sequences = pad_sequences(sequences, maxlen=max_length, padding='post', truncating='post')
return padded_sequences
@app.route('/')
def home():
return render_template('index.html')
@app.route('/analyze', methods=['POST'])
def analyze():
text = request.form['text']
model_type = request.form['model_type']
preprocessed_text = preprocess_text(text)
if model_type == 'lstm':
prediction_prob = lstm_model.predict(preprocessed_text)
prediction = (prediction_prob > 0.5).astype(int)
else:
prediction = logistic_regression_model.predict(preprocessed_text)
sentiment = 'Positive' if prediction[0] == 1 else 'Negative'
return jsonify({'sentiment': sentiment})
if __name__ == '__main__':
app.run(debug=True)
In this script, we define the basic routes for our Flask application:
- The
home
route renders the home page. - The
analyze
route processes the text input, uses the selected model to predict sentiment, and returns the result as JSON.
13.4.2 Creating HTML Templates
Next, we will create HTML templates to render the web pages. We will use Bootstrap for styling to create a responsive and visually appealing interface.
templates/index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sentiment Analysis Dashboard</title>
<link rel="stylesheet" href="<https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css>">
</head>
<body>
<div class="container">
<h1 class="mt-5">Sentiment Analysis Dashboard</h1>
<form id="analysis-form" class="mt-4">
<div class="form-group">
<label for="text">Enter Text</label>
<textarea class="form-control" id="text" name="text" rows="3" required></textarea>
</div>
<div class="form-group">
<label for="model_type">Select Model</label>
<select class="form-control" id="model_type" name="model_type" required>
<option value="logistic_regression">Logistic Regression</option>
<option value="lstm">LSTM</option>
</select>
</div>
<button type="submit" class="btn btn-primary">Analyze Sentiment</button>
</form>
<div id="result" class="mt-4"></div>
</div>
<script src="<https://code.jquery.com/jquery-3.5.1.min.js>"></script>
<script>
$(document).ready(function() {
$('#analysis-form').on('submit', function(event) {
event.preventDefault();
const formData = $(this).serialize();
$.post('/analyze', formData, function(data) {
$('#result').html(`<h3>Sentiment: ${data.sentiment}</h3>`);
});
});
});
</script>
</body>
</html>
In this HTML template, we create a simple form to enter text and select the model type. When the form is submitted, an AJAX request is sent to the /analyze
endpoint, and the result is displayed on the page.
13.4.3 Adding Data Visualization
Data visualization helps users understand the sentiment analysis results more effectively. We will use Plotly, a graphing library, to create interactive charts.
app.py (continued):
import plotly.express as px
import pandas as pd
@app.route('/visualize', methods=['GET'])
def visualize():
# Example data for visualization
data = {
'Text': ['I love this!', 'I hate this!', 'This is amazing!', 'This is terrible!'],
'Sentiment': ['Positive', 'Negative', 'Positive', 'Negative']
}
df = pd.DataFrame(data)
fig = px.histogram(df, x='Sentiment', title='Sentiment Distribution')
graph_html = fig.to_html(full_html=False)
return render_template('visualize.html', graph_html=graph_html)
# HTML template for visualization
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sentiment Analysis Visualization</title>
<link rel="stylesheet" href="<https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css>">
</head>
<body>
<div class="container">
<h1 class="mt-5">Sentiment Analysis Visualization</h1>
<div id="graph-container">
{{ graph_html | safe }}
</div>
</div>
</body>
</html>
In this example, we create a route /visualize
that generates a simple histogram of sentiment distribution using Plotly. The generated chart is rendered in the visualize.html
template.
13.4.4 Uploading Text Data
Allowing users to upload text data for sentiment analysis enhances the functionality of the dashboard. We will add an option for users to upload CSV files containing text data.
app.py (continued):
import os
from werkzeug.utils import secure_filename
UPLOAD_FOLDER = 'data/uploads'
ALLOWED_EXTENSIONS = {'csv'}
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
if 'file' not in request.files:
return jsonify({'message': 'No file part'})
file = request.files['file']
if file.filename == '':
return jsonify({'message': 'No selected file'})
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
return jsonify({'message': 'File uploaded successfully'})
return render_template('upload.html')
# HTML template for file upload
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Upload Text Data</title>
<link rel="stylesheet" href="<https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css>">
</head>
<body>
<div class="container">
<h1 class="mt-5">Upload Text Data for Sentiment Analysis</h1>
<form action="/upload" method="post" enctype="multipart/form-data" class="mt-4">
<div class="form-group">
<label for="file">Choose CSV File</label>
<input type="file" class="form-control-file" id="file" name="file" required>
</div>
<button type="submit" class="btn btn-primary">Upload</button>
</form>
</div>
</body>
</html>
In this example, we create a route /upload
that handles file uploads. The uploaded CSV file is saved in the data/uploads
directory. We also create an HTML template upload.html
with a form to upload the file.
13.4.5 Integrating All Components
Finally, we integrate all components to create a comprehensive dashboard interface that allows users to analyze text data, visualize results, and upload new data.
app.py (final):
from flask import Flask, request, render_template, jsonify
import pickle
import numpy as np
from tensorflow.keras.models import load_model
from tensorflow.keras.preprocessing.sequence import pad_sequences
import plotly.express as px
import pandas as pd
import os
from werkzeug.utils import secure_filename
app = Flask(__name__)
# Load models and tokenizer
lstm_model = load_model('models/lstm_model.h5')
with open('models/tokenizer.pickle', 'rb') as file:
tokenizer = pickle.load(file)
with open('models/best_logistic_regression_model.pickle', 'rb') as file:
logistic_regression_model = pickle.load(file)
# Set upload folder and allowed extensions
UPLOAD_FOLDER = 'data/uploads'
ALLOWED_EXTENSIONS = {'csv'}
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
# Preprocess text
def preprocess_text(text):
max_length = 200
sequences = tokenizer.texts_to_sequences([text])
padded_sequences = pad_sequences(sequences, maxlen=max_length, padding='post', truncating='post')
return padded_sequences
@app.route('/')
def home():
return render_template('index.html')
@app.route('/analyze', methods=['POST'])
def analyze():
text = request.form['text']
model_type = request.form['model_type']
preprocessed_text = preprocess_text(text)
if model_type == 'lstm':
prediction_prob = lstm_model.predict(preprocessed_text)
prediction = (prediction_prob > 0.5).astype(int)
else:
prediction = logistic_regression_model.predict(preprocessed_text)
sentiment = 'Positive' if prediction[0] == 1 else 'Negative'
return jsonify({'sentiment': sentiment})
@app.route('/visualize', methods=['GET'])
def visualize():
data = {
'Text': ['I love this!', 'I hate this!', 'This is amazing!', 'This is terrible!'],
'Sentiment': ['Positive', 'Negative', 'Positive', 'Negative']
}
df = pd.DataFrame(data)
fig = px.histogram(df, x='Sentiment', title='Sentiment Distribution')
graph_html = fig.to_html(full_html=False)
return render_template('visualize.html', graph_html=graph_html)
@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
if 'file' not in request.files:
return jsonify({'message': 'No file part'})
file = request.files['file']
if file.filename == '':
return jsonify({'message': 'No selected file'})
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
return jsonify({'message': 'File uploaded successfully'})
return render_template('upload.html')
if __name__ == '__main__':
app.run(debug=True)
So far, we have developed the dashboard interface for the sentiment analysis project. We used Flask to create a web-based interface and integrated HTML, CSS, and JavaScript for the frontend. We also added data visualization using Plotly and enabled file uploads for user-generated text data.
By following these steps, we created a comprehensive dashboard that allows users to interact with the sentiment analysis models, upload data, and visualize the results in an intuitive and interactive way.
13.4 Developing the Dashboard Interface
Developing an intuitive and interactive dashboard interface is crucial for allowing users to interact with the sentiment analysis models, upload text data, and visualize the results. In this section, we will discuss how to build a web-based dashboard interface using Flask, a lightweight web framework for Python, along with HTML, CSS, and JavaScript for the frontend. We will also integrate data visualization libraries such as Plotly to create interactive charts.
13.4.1 Setting Up Flask
First, ensure Flask is installed if it hasn't been already:
pip install Flask
Next, let's set up the basic structure of our Flask application.
from flask import Flask, request, render_template, jsonify
import pickle
import numpy as np
from tensorflow.keras.models import load_model
from tensorflow.keras.preprocessing.sequence import pad_sequences
app = Flask(__name__)
# Load the LSTM model and tokenizer
lstm_model = load_model('models/lstm_model.h5')
with open('models/tokenizer.pickle', 'rb') as file:
tokenizer = pickle.load(file)
# Load the Logistic Regression model
with open('models/best_logistic_regression_model.pickle', 'rb') as file:
logistic_regression_model = pickle.load(file)
# Define function to preprocess text
def preprocess_text(text):
max_length = 200
sequences = tokenizer.texts_to_sequences([text])
padded_sequences = pad_sequences(sequences, maxlen=max_length, padding='post', truncating='post')
return padded_sequences
@app.route('/')
def home():
return render_template('index.html')
@app.route('/analyze', methods=['POST'])
def analyze():
text = request.form['text']
model_type = request.form['model_type']
preprocessed_text = preprocess_text(text)
if model_type == 'lstm':
prediction_prob = lstm_model.predict(preprocessed_text)
prediction = (prediction_prob > 0.5).astype(int)
else:
prediction = logistic_regression_model.predict(preprocessed_text)
sentiment = 'Positive' if prediction[0] == 1 else 'Negative'
return jsonify({'sentiment': sentiment})
if __name__ == '__main__':
app.run(debug=True)
In this script, we define the basic routes for our Flask application:
- The
home
route renders the home page. - The
analyze
route processes the text input, uses the selected model to predict sentiment, and returns the result as JSON.
13.4.2 Creating HTML Templates
Next, we will create HTML templates to render the web pages. We will use Bootstrap for styling to create a responsive and visually appealing interface.
templates/index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sentiment Analysis Dashboard</title>
<link rel="stylesheet" href="<https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css>">
</head>
<body>
<div class="container">
<h1 class="mt-5">Sentiment Analysis Dashboard</h1>
<form id="analysis-form" class="mt-4">
<div class="form-group">
<label for="text">Enter Text</label>
<textarea class="form-control" id="text" name="text" rows="3" required></textarea>
</div>
<div class="form-group">
<label for="model_type">Select Model</label>
<select class="form-control" id="model_type" name="model_type" required>
<option value="logistic_regression">Logistic Regression</option>
<option value="lstm">LSTM</option>
</select>
</div>
<button type="submit" class="btn btn-primary">Analyze Sentiment</button>
</form>
<div id="result" class="mt-4"></div>
</div>
<script src="<https://code.jquery.com/jquery-3.5.1.min.js>"></script>
<script>
$(document).ready(function() {
$('#analysis-form').on('submit', function(event) {
event.preventDefault();
const formData = $(this).serialize();
$.post('/analyze', formData, function(data) {
$('#result').html(`<h3>Sentiment: ${data.sentiment}</h3>`);
});
});
});
</script>
</body>
</html>
In this HTML template, we create a simple form to enter text and select the model type. When the form is submitted, an AJAX request is sent to the /analyze
endpoint, and the result is displayed on the page.
13.4.3 Adding Data Visualization
Data visualization helps users understand the sentiment analysis results more effectively. We will use Plotly, a graphing library, to create interactive charts.
app.py (continued):
import plotly.express as px
import pandas as pd
@app.route('/visualize', methods=['GET'])
def visualize():
# Example data for visualization
data = {
'Text': ['I love this!', 'I hate this!', 'This is amazing!', 'This is terrible!'],
'Sentiment': ['Positive', 'Negative', 'Positive', 'Negative']
}
df = pd.DataFrame(data)
fig = px.histogram(df, x='Sentiment', title='Sentiment Distribution')
graph_html = fig.to_html(full_html=False)
return render_template('visualize.html', graph_html=graph_html)
# HTML template for visualization
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sentiment Analysis Visualization</title>
<link rel="stylesheet" href="<https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css>">
</head>
<body>
<div class="container">
<h1 class="mt-5">Sentiment Analysis Visualization</h1>
<div id="graph-container">
{{ graph_html | safe }}
</div>
</div>
</body>
</html>
In this example, we create a route /visualize
that generates a simple histogram of sentiment distribution using Plotly. The generated chart is rendered in the visualize.html
template.
13.4.4 Uploading Text Data
Allowing users to upload text data for sentiment analysis enhances the functionality of the dashboard. We will add an option for users to upload CSV files containing text data.
app.py (continued):
import os
from werkzeug.utils import secure_filename
UPLOAD_FOLDER = 'data/uploads'
ALLOWED_EXTENSIONS = {'csv'}
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
if 'file' not in request.files:
return jsonify({'message': 'No file part'})
file = request.files['file']
if file.filename == '':
return jsonify({'message': 'No selected file'})
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
return jsonify({'message': 'File uploaded successfully'})
return render_template('upload.html')
# HTML template for file upload
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Upload Text Data</title>
<link rel="stylesheet" href="<https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css>">
</head>
<body>
<div class="container">
<h1 class="mt-5">Upload Text Data for Sentiment Analysis</h1>
<form action="/upload" method="post" enctype="multipart/form-data" class="mt-4">
<div class="form-group">
<label for="file">Choose CSV File</label>
<input type="file" class="form-control-file" id="file" name="file" required>
</div>
<button type="submit" class="btn btn-primary">Upload</button>
</form>
</div>
</body>
</html>
In this example, we create a route /upload
that handles file uploads. The uploaded CSV file is saved in the data/uploads
directory. We also create an HTML template upload.html
with a form to upload the file.
13.4.5 Integrating All Components
Finally, we integrate all components to create a comprehensive dashboard interface that allows users to analyze text data, visualize results, and upload new data.
app.py (final):
from flask import Flask, request, render_template, jsonify
import pickle
import numpy as np
from tensorflow.keras.models import load_model
from tensorflow.keras.preprocessing.sequence import pad_sequences
import plotly.express as px
import pandas as pd
import os
from werkzeug.utils import secure_filename
app = Flask(__name__)
# Load models and tokenizer
lstm_model = load_model('models/lstm_model.h5')
with open('models/tokenizer.pickle', 'rb') as file:
tokenizer = pickle.load(file)
with open('models/best_logistic_regression_model.pickle', 'rb') as file:
logistic_regression_model = pickle.load(file)
# Set upload folder and allowed extensions
UPLOAD_FOLDER = 'data/uploads'
ALLOWED_EXTENSIONS = {'csv'}
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
# Preprocess text
def preprocess_text(text):
max_length = 200
sequences = tokenizer.texts_to_sequences([text])
padded_sequences = pad_sequences(sequences, maxlen=max_length, padding='post', truncating='post')
return padded_sequences
@app.route('/')
def home():
return render_template('index.html')
@app.route('/analyze', methods=['POST'])
def analyze():
text = request.form['text']
model_type = request.form['model_type']
preprocessed_text = preprocess_text(text)
if model_type == 'lstm':
prediction_prob = lstm_model.predict(preprocessed_text)
prediction = (prediction_prob > 0.5).astype(int)
else:
prediction = logistic_regression_model.predict(preprocessed_text)
sentiment = 'Positive' if prediction[0] == 1 else 'Negative'
return jsonify({'sentiment': sentiment})
@app.route('/visualize', methods=['GET'])
def visualize():
data = {
'Text': ['I love this!', 'I hate this!', 'This is amazing!', 'This is terrible!'],
'Sentiment': ['Positive', 'Negative', 'Positive', 'Negative']
}
df = pd.DataFrame(data)
fig = px.histogram(df, x='Sentiment', title='Sentiment Distribution')
graph_html = fig.to_html(full_html=False)
return render_template('visualize.html', graph_html=graph_html)
@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
if 'file' not in request.files:
return jsonify({'message': 'No file part'})
file = request.files['file']
if file.filename == '':
return jsonify({'message': 'No selected file'})
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
return jsonify({'message': 'File uploaded successfully'})
return render_template('upload.html')
if __name__ == '__main__':
app.run(debug=True)
So far, we have developed the dashboard interface for the sentiment analysis project. We used Flask to create a web-based interface and integrated HTML, CSS, and JavaScript for the frontend. We also added data visualization using Plotly and enabled file uploads for user-generated text data.
By following these steps, we created a comprehensive dashboard that allows users to interact with the sentiment analysis models, upload data, and visualize the results in an intuitive and interactive way.
13.4 Developing the Dashboard Interface
Developing an intuitive and interactive dashboard interface is crucial for allowing users to interact with the sentiment analysis models, upload text data, and visualize the results. In this section, we will discuss how to build a web-based dashboard interface using Flask, a lightweight web framework for Python, along with HTML, CSS, and JavaScript for the frontend. We will also integrate data visualization libraries such as Plotly to create interactive charts.
13.4.1 Setting Up Flask
First, ensure Flask is installed if it hasn't been already:
pip install Flask
Next, let's set up the basic structure of our Flask application.
from flask import Flask, request, render_template, jsonify
import pickle
import numpy as np
from tensorflow.keras.models import load_model
from tensorflow.keras.preprocessing.sequence import pad_sequences
app = Flask(__name__)
# Load the LSTM model and tokenizer
lstm_model = load_model('models/lstm_model.h5')
with open('models/tokenizer.pickle', 'rb') as file:
tokenizer = pickle.load(file)
# Load the Logistic Regression model
with open('models/best_logistic_regression_model.pickle', 'rb') as file:
logistic_regression_model = pickle.load(file)
# Define function to preprocess text
def preprocess_text(text):
max_length = 200
sequences = tokenizer.texts_to_sequences([text])
padded_sequences = pad_sequences(sequences, maxlen=max_length, padding='post', truncating='post')
return padded_sequences
@app.route('/')
def home():
return render_template('index.html')
@app.route('/analyze', methods=['POST'])
def analyze():
text = request.form['text']
model_type = request.form['model_type']
preprocessed_text = preprocess_text(text)
if model_type == 'lstm':
prediction_prob = lstm_model.predict(preprocessed_text)
prediction = (prediction_prob > 0.5).astype(int)
else:
prediction = logistic_regression_model.predict(preprocessed_text)
sentiment = 'Positive' if prediction[0] == 1 else 'Negative'
return jsonify({'sentiment': sentiment})
if __name__ == '__main__':
app.run(debug=True)
In this script, we define the basic routes for our Flask application:
- The
home
route renders the home page. - The
analyze
route processes the text input, uses the selected model to predict sentiment, and returns the result as JSON.
13.4.2 Creating HTML Templates
Next, we will create HTML templates to render the web pages. We will use Bootstrap for styling to create a responsive and visually appealing interface.
templates/index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sentiment Analysis Dashboard</title>
<link rel="stylesheet" href="<https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css>">
</head>
<body>
<div class="container">
<h1 class="mt-5">Sentiment Analysis Dashboard</h1>
<form id="analysis-form" class="mt-4">
<div class="form-group">
<label for="text">Enter Text</label>
<textarea class="form-control" id="text" name="text" rows="3" required></textarea>
</div>
<div class="form-group">
<label for="model_type">Select Model</label>
<select class="form-control" id="model_type" name="model_type" required>
<option value="logistic_regression">Logistic Regression</option>
<option value="lstm">LSTM</option>
</select>
</div>
<button type="submit" class="btn btn-primary">Analyze Sentiment</button>
</form>
<div id="result" class="mt-4"></div>
</div>
<script src="<https://code.jquery.com/jquery-3.5.1.min.js>"></script>
<script>
$(document).ready(function() {
$('#analysis-form').on('submit', function(event) {
event.preventDefault();
const formData = $(this).serialize();
$.post('/analyze', formData, function(data) {
$('#result').html(`<h3>Sentiment: ${data.sentiment}</h3>`);
});
});
});
</script>
</body>
</html>
In this HTML template, we create a simple form to enter text and select the model type. When the form is submitted, an AJAX request is sent to the /analyze
endpoint, and the result is displayed on the page.
13.4.3 Adding Data Visualization
Data visualization helps users understand the sentiment analysis results more effectively. We will use Plotly, a graphing library, to create interactive charts.
app.py (continued):
import plotly.express as px
import pandas as pd
@app.route('/visualize', methods=['GET'])
def visualize():
# Example data for visualization
data = {
'Text': ['I love this!', 'I hate this!', 'This is amazing!', 'This is terrible!'],
'Sentiment': ['Positive', 'Negative', 'Positive', 'Negative']
}
df = pd.DataFrame(data)
fig = px.histogram(df, x='Sentiment', title='Sentiment Distribution')
graph_html = fig.to_html(full_html=False)
return render_template('visualize.html', graph_html=graph_html)
# HTML template for visualization
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sentiment Analysis Visualization</title>
<link rel="stylesheet" href="<https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css>">
</head>
<body>
<div class="container">
<h1 class="mt-5">Sentiment Analysis Visualization</h1>
<div id="graph-container">
{{ graph_html | safe }}
</div>
</div>
</body>
</html>
In this example, we create a route /visualize
that generates a simple histogram of sentiment distribution using Plotly. The generated chart is rendered in the visualize.html
template.
13.4.4 Uploading Text Data
Allowing users to upload text data for sentiment analysis enhances the functionality of the dashboard. We will add an option for users to upload CSV files containing text data.
app.py (continued):
import os
from werkzeug.utils import secure_filename
UPLOAD_FOLDER = 'data/uploads'
ALLOWED_EXTENSIONS = {'csv'}
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
if 'file' not in request.files:
return jsonify({'message': 'No file part'})
file = request.files['file']
if file.filename == '':
return jsonify({'message': 'No selected file'})
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
return jsonify({'message': 'File uploaded successfully'})
return render_template('upload.html')
# HTML template for file upload
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Upload Text Data</title>
<link rel="stylesheet" href="<https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css>">
</head>
<body>
<div class="container">
<h1 class="mt-5">Upload Text Data for Sentiment Analysis</h1>
<form action="/upload" method="post" enctype="multipart/form-data" class="mt-4">
<div class="form-group">
<label for="file">Choose CSV File</label>
<input type="file" class="form-control-file" id="file" name="file" required>
</div>
<button type="submit" class="btn btn-primary">Upload</button>
</form>
</div>
</body>
</html>
In this example, we create a route /upload
that handles file uploads. The uploaded CSV file is saved in the data/uploads
directory. We also create an HTML template upload.html
with a form to upload the file.
13.4.5 Integrating All Components
Finally, we integrate all components to create a comprehensive dashboard interface that allows users to analyze text data, visualize results, and upload new data.
app.py (final):
from flask import Flask, request, render_template, jsonify
import pickle
import numpy as np
from tensorflow.keras.models import load_model
from tensorflow.keras.preprocessing.sequence import pad_sequences
import plotly.express as px
import pandas as pd
import os
from werkzeug.utils import secure_filename
app = Flask(__name__)
# Load models and tokenizer
lstm_model = load_model('models/lstm_model.h5')
with open('models/tokenizer.pickle', 'rb') as file:
tokenizer = pickle.load(file)
with open('models/best_logistic_regression_model.pickle', 'rb') as file:
logistic_regression_model = pickle.load(file)
# Set upload folder and allowed extensions
UPLOAD_FOLDER = 'data/uploads'
ALLOWED_EXTENSIONS = {'csv'}
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
# Preprocess text
def preprocess_text(text):
max_length = 200
sequences = tokenizer.texts_to_sequences([text])
padded_sequences = pad_sequences(sequences, maxlen=max_length, padding='post', truncating='post')
return padded_sequences
@app.route('/')
def home():
return render_template('index.html')
@app.route('/analyze', methods=['POST'])
def analyze():
text = request.form['text']
model_type = request.form['model_type']
preprocessed_text = preprocess_text(text)
if model_type == 'lstm':
prediction_prob = lstm_model.predict(preprocessed_text)
prediction = (prediction_prob > 0.5).astype(int)
else:
prediction = logistic_regression_model.predict(preprocessed_text)
sentiment = 'Positive' if prediction[0] == 1 else 'Negative'
return jsonify({'sentiment': sentiment})
@app.route('/visualize', methods=['GET'])
def visualize():
data = {
'Text': ['I love this!', 'I hate this!', 'This is amazing!', 'This is terrible!'],
'Sentiment': ['Positive', 'Negative', 'Positive', 'Negative']
}
df = pd.DataFrame(data)
fig = px.histogram(df, x='Sentiment', title='Sentiment Distribution')
graph_html = fig.to_html(full_html=False)
return render_template('visualize.html', graph_html=graph_html)
@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
if 'file' not in request.files:
return jsonify({'message': 'No file part'})
file = request.files['file']
if file.filename == '':
return jsonify({'message': 'No selected file'})
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
return jsonify({'message': 'File uploaded successfully'})
return render_template('upload.html')
if __name__ == '__main__':
app.run(debug=True)
So far, we have developed the dashboard interface for the sentiment analysis project. We used Flask to create a web-based interface and integrated HTML, CSS, and JavaScript for the frontend. We also added data visualization using Plotly and enabled file uploads for user-generated text data.
By following these steps, we created a comprehensive dashboard that allows users to interact with the sentiment analysis models, upload data, and visualize the results in an intuitive and interactive way.