Capítulo 13: Proyecto: Panel de Análisis de Sentimientos
13.4 Desarrollo de la Interfaz del Panel
Desarrollar una interfaz de panel intuitiva e interactiva es crucial para permitir que los usuarios interactúen con los modelos de análisis de sentimientos, suban datos textuales y visualicen los resultados. En esta sección, discutiremos cómo construir una interfaz de panel web utilizando Flask, un marco web ligero para Python, junto con HTML, CSS y JavaScript para el frontend. También integraremos bibliotecas de visualización de datos como Plotly para crear gráficos interactivos.
13.4.1 Configuración de Flask
Primero, asegúrate de que Flask esté instalado si aún no lo está:
pip install Flask
A continuación, configuremos la estructura básica de nuestra aplicación Flask.
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)
En este script, definimos las rutas básicas para nuestra aplicación Flask:
- La ruta
home
renderiza la página de inicio. - La ruta
analyze
procesa la entrada de texto, utiliza el modelo seleccionado para predecir el sentimiento y devuelve el resultado en formato JSON.
13.4.2 Creación de Plantillas HTML
A continuación, crearemos plantillas HTML para renderizar las páginas web. Usaremos Bootstrap para el estilo y así crear una interfaz receptiva y visualmente atractiva.
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>
En esta plantilla HTML, creamos un formulario simple para ingresar texto y seleccionar el tipo de modelo. Cuando se envía el formulario, se envía una solicitud AJAX al endpoint /analyze
, y el resultado se muestra en la página.
13.4.3 Agregar Visualización de Datos
La visualización de datos ayuda a los usuarios a comprender los resultados del análisis de sentimiento de manera más efectiva. Usaremos Plotly, una biblioteca de gráficos, para crear gráficos interactivos.
app.py (continuación):
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>
En este ejemplo, creamos una ruta /visualize
que genera un histograma simple de la distribución de sentimiento usando Plotly. El gráfico generado se renderiza en la plantilla visualize.html
.
13.4.4 Subiendo Datos de Texto
Permitir a los usuarios subir datos de texto para el análisis de sentimientos mejora la funcionalidad del tablero. Añadiremos una opción para que los usuarios suban archivos CSV que contengan datos de texto.
app.py (continuado):
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>
En este ejemplo, creamos una ruta /upload
que maneja las cargas de archivos. El archivo CSV subido se guarda en el directorio data/uploads
. También creamos una plantilla HTML upload.html
con un formulario para cargar el archivo.
13.4.5 Integrando Todos los Componentes
Finalmente, integramos todos los componentes para crear una interfaz de tablero completa que permita a los usuarios analizar datos de texto, visualizar resultados y cargar nuevos datos.
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)
Hasta ahora, hemos desarrollado la interfaz del tablero para el proyecto de análisis de sentimiento. Usamos Flask para crear una interfaz web e integrados HTML, CSS y JavaScript para el frontend. También agregamos visualización de datos usando Plotly y habilitamos la carga de archivos para datos de texto generados por el usuario.
Al seguir estos pasos, creamos un tablero integral que permite a los usuarios interactuar con los modelos de análisis de sentimiento, cargar datos y visualizar los resultados de una manera intuitiva e interactiva.
13.4 Desarrollo de la Interfaz del Panel
Desarrollar una interfaz de panel intuitiva e interactiva es crucial para permitir que los usuarios interactúen con los modelos de análisis de sentimientos, suban datos textuales y visualicen los resultados. En esta sección, discutiremos cómo construir una interfaz de panel web utilizando Flask, un marco web ligero para Python, junto con HTML, CSS y JavaScript para el frontend. También integraremos bibliotecas de visualización de datos como Plotly para crear gráficos interactivos.
13.4.1 Configuración de Flask
Primero, asegúrate de que Flask esté instalado si aún no lo está:
pip install Flask
A continuación, configuremos la estructura básica de nuestra aplicación Flask.
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)
En este script, definimos las rutas básicas para nuestra aplicación Flask:
- La ruta
home
renderiza la página de inicio. - La ruta
analyze
procesa la entrada de texto, utiliza el modelo seleccionado para predecir el sentimiento y devuelve el resultado en formato JSON.
13.4.2 Creación de Plantillas HTML
A continuación, crearemos plantillas HTML para renderizar las páginas web. Usaremos Bootstrap para el estilo y así crear una interfaz receptiva y visualmente atractiva.
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>
En esta plantilla HTML, creamos un formulario simple para ingresar texto y seleccionar el tipo de modelo. Cuando se envía el formulario, se envía una solicitud AJAX al endpoint /analyze
, y el resultado se muestra en la página.
13.4.3 Agregar Visualización de Datos
La visualización de datos ayuda a los usuarios a comprender los resultados del análisis de sentimiento de manera más efectiva. Usaremos Plotly, una biblioteca de gráficos, para crear gráficos interactivos.
app.py (continuación):
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>
En este ejemplo, creamos una ruta /visualize
que genera un histograma simple de la distribución de sentimiento usando Plotly. El gráfico generado se renderiza en la plantilla visualize.html
.
13.4.4 Subiendo Datos de Texto
Permitir a los usuarios subir datos de texto para el análisis de sentimientos mejora la funcionalidad del tablero. Añadiremos una opción para que los usuarios suban archivos CSV que contengan datos de texto.
app.py (continuado):
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>
En este ejemplo, creamos una ruta /upload
que maneja las cargas de archivos. El archivo CSV subido se guarda en el directorio data/uploads
. También creamos una plantilla HTML upload.html
con un formulario para cargar el archivo.
13.4.5 Integrando Todos los Componentes
Finalmente, integramos todos los componentes para crear una interfaz de tablero completa que permita a los usuarios analizar datos de texto, visualizar resultados y cargar nuevos datos.
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)
Hasta ahora, hemos desarrollado la interfaz del tablero para el proyecto de análisis de sentimiento. Usamos Flask para crear una interfaz web e integrados HTML, CSS y JavaScript para el frontend. También agregamos visualización de datos usando Plotly y habilitamos la carga de archivos para datos de texto generados por el usuario.
Al seguir estos pasos, creamos un tablero integral que permite a los usuarios interactuar con los modelos de análisis de sentimiento, cargar datos y visualizar los resultados de una manera intuitiva e interactiva.
13.4 Desarrollo de la Interfaz del Panel
Desarrollar una interfaz de panel intuitiva e interactiva es crucial para permitir que los usuarios interactúen con los modelos de análisis de sentimientos, suban datos textuales y visualicen los resultados. En esta sección, discutiremos cómo construir una interfaz de panel web utilizando Flask, un marco web ligero para Python, junto con HTML, CSS y JavaScript para el frontend. También integraremos bibliotecas de visualización de datos como Plotly para crear gráficos interactivos.
13.4.1 Configuración de Flask
Primero, asegúrate de que Flask esté instalado si aún no lo está:
pip install Flask
A continuación, configuremos la estructura básica de nuestra aplicación Flask.
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)
En este script, definimos las rutas básicas para nuestra aplicación Flask:
- La ruta
home
renderiza la página de inicio. - La ruta
analyze
procesa la entrada de texto, utiliza el modelo seleccionado para predecir el sentimiento y devuelve el resultado en formato JSON.
13.4.2 Creación de Plantillas HTML
A continuación, crearemos plantillas HTML para renderizar las páginas web. Usaremos Bootstrap para el estilo y así crear una interfaz receptiva y visualmente atractiva.
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>
En esta plantilla HTML, creamos un formulario simple para ingresar texto y seleccionar el tipo de modelo. Cuando se envía el formulario, se envía una solicitud AJAX al endpoint /analyze
, y el resultado se muestra en la página.
13.4.3 Agregar Visualización de Datos
La visualización de datos ayuda a los usuarios a comprender los resultados del análisis de sentimiento de manera más efectiva. Usaremos Plotly, una biblioteca de gráficos, para crear gráficos interactivos.
app.py (continuación):
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>
En este ejemplo, creamos una ruta /visualize
que genera un histograma simple de la distribución de sentimiento usando Plotly. El gráfico generado se renderiza en la plantilla visualize.html
.
13.4.4 Subiendo Datos de Texto
Permitir a los usuarios subir datos de texto para el análisis de sentimientos mejora la funcionalidad del tablero. Añadiremos una opción para que los usuarios suban archivos CSV que contengan datos de texto.
app.py (continuado):
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>
En este ejemplo, creamos una ruta /upload
que maneja las cargas de archivos. El archivo CSV subido se guarda en el directorio data/uploads
. También creamos una plantilla HTML upload.html
con un formulario para cargar el archivo.
13.4.5 Integrando Todos los Componentes
Finalmente, integramos todos los componentes para crear una interfaz de tablero completa que permita a los usuarios analizar datos de texto, visualizar resultados y cargar nuevos datos.
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)
Hasta ahora, hemos desarrollado la interfaz del tablero para el proyecto de análisis de sentimiento. Usamos Flask para crear una interfaz web e integrados HTML, CSS y JavaScript para el frontend. También agregamos visualización de datos usando Plotly y habilitamos la carga de archivos para datos de texto generados por el usuario.
Al seguir estos pasos, creamos un tablero integral que permite a los usuarios interactuar con los modelos de análisis de sentimiento, cargar datos y visualizar los resultados de una manera intuitiva e interactiva.
13.4 Desarrollo de la Interfaz del Panel
Desarrollar una interfaz de panel intuitiva e interactiva es crucial para permitir que los usuarios interactúen con los modelos de análisis de sentimientos, suban datos textuales y visualicen los resultados. En esta sección, discutiremos cómo construir una interfaz de panel web utilizando Flask, un marco web ligero para Python, junto con HTML, CSS y JavaScript para el frontend. También integraremos bibliotecas de visualización de datos como Plotly para crear gráficos interactivos.
13.4.1 Configuración de Flask
Primero, asegúrate de que Flask esté instalado si aún no lo está:
pip install Flask
A continuación, configuremos la estructura básica de nuestra aplicación Flask.
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)
En este script, definimos las rutas básicas para nuestra aplicación Flask:
- La ruta
home
renderiza la página de inicio. - La ruta
analyze
procesa la entrada de texto, utiliza el modelo seleccionado para predecir el sentimiento y devuelve el resultado en formato JSON.
13.4.2 Creación de Plantillas HTML
A continuación, crearemos plantillas HTML para renderizar las páginas web. Usaremos Bootstrap para el estilo y así crear una interfaz receptiva y visualmente atractiva.
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>
En esta plantilla HTML, creamos un formulario simple para ingresar texto y seleccionar el tipo de modelo. Cuando se envía el formulario, se envía una solicitud AJAX al endpoint /analyze
, y el resultado se muestra en la página.
13.4.3 Agregar Visualización de Datos
La visualización de datos ayuda a los usuarios a comprender los resultados del análisis de sentimiento de manera más efectiva. Usaremos Plotly, una biblioteca de gráficos, para crear gráficos interactivos.
app.py (continuación):
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>
En este ejemplo, creamos una ruta /visualize
que genera un histograma simple de la distribución de sentimiento usando Plotly. El gráfico generado se renderiza en la plantilla visualize.html
.
13.4.4 Subiendo Datos de Texto
Permitir a los usuarios subir datos de texto para el análisis de sentimientos mejora la funcionalidad del tablero. Añadiremos una opción para que los usuarios suban archivos CSV que contengan datos de texto.
app.py (continuado):
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>
En este ejemplo, creamos una ruta /upload
que maneja las cargas de archivos. El archivo CSV subido se guarda en el directorio data/uploads
. También creamos una plantilla HTML upload.html
con un formulario para cargar el archivo.
13.4.5 Integrando Todos los Componentes
Finalmente, integramos todos los componentes para crear una interfaz de tablero completa que permita a los usuarios analizar datos de texto, visualizar resultados y cargar nuevos datos.
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)
Hasta ahora, hemos desarrollado la interfaz del tablero para el proyecto de análisis de sentimiento. Usamos Flask para crear una interfaz web e integrados HTML, CSS y JavaScript para el frontend. También agregamos visualización de datos usando Plotly y habilitamos la carga de archivos para datos de texto generados por el usuario.
Al seguir estos pasos, creamos un tablero integral que permite a los usuarios interactuar con los modelos de análisis de sentimiento, cargar datos y visualizar los resultados de una manera intuitiva e interactiva.