Update app.py
Browse files
app.py
CHANGED
@@ -124,19 +124,32 @@ class SpeechAnalyzer:
|
|
124 |
|
125 |
return aggregated_scores
|
126 |
|
127 |
-
def analyze_emotional_trajectory(self, text, window_size=5):
|
128 |
-
"""
|
129 |
-
|
|
|
|
|
130 |
|
|
|
131 |
sentiment_scores = []
|
132 |
-
for
|
133 |
-
result = self.sentiment_pipeline(
|
134 |
-
|
135 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
136 |
|
|
|
137 |
smoothed_scores = (savgol_filter(sentiment_scores, window_length=window_size, polyorder=2)
|
138 |
-
|
139 |
-
|
140 |
return smoothed_scores
|
141 |
|
142 |
def detect_named_entities(self, text):
|
@@ -287,28 +300,19 @@ def main():
|
|
287 |
|
288 |
with tab2:
|
289 |
st.subheader("Speech Trajectory Analysis")
|
290 |
-
|
291 |
col1, col2 = st.columns(2)
|
292 |
|
293 |
with col1:
|
294 |
st.write("### Emotional Flow")
|
295 |
-
#
|
296 |
-
|
297 |
-
sentiment_results = []
|
298 |
-
|
299 |
-
for segment in segments:
|
300 |
-
result = analyzer.sentiment_pipeline(segment[:512])[0]
|
301 |
-
# Convert score to a more granular value instead of binary
|
302 |
-
sentiment_value = result['score'] if result['label'] == 'POSITIVE' else -result['score']
|
303 |
-
sentiment_results.append(sentiment_value)
|
304 |
|
305 |
-
# Create segment labels
|
306 |
-
|
307 |
-
segment_labels = [f"{i+1}" for i in range(num_segments)]
|
308 |
|
309 |
trajectory_fig = go.Figure(data=go.Scatter(
|
310 |
x=segment_labels,
|
311 |
-
y=
|
312 |
mode='lines+markers',
|
313 |
line=dict(
|
314 |
color='#1f77b4',
|
@@ -318,15 +322,16 @@ def main():
|
|
318 |
size=8,
|
319 |
color='#1f77b4',
|
320 |
symbol='circle'
|
321 |
-
)
|
|
|
322 |
))
|
323 |
|
324 |
trajectory_fig.update_layout(
|
325 |
title='Emotional Flow Throughout the Speech',
|
326 |
xaxis_title='Speech Segments',
|
327 |
-
yaxis_title='Emotional Tone',
|
328 |
yaxis=dict(
|
329 |
-
ticktext=['
|
330 |
tickvals=[-1, 0, 1],
|
331 |
range=[-1.1, 1.1],
|
332 |
gridcolor='lightgray'
|
@@ -345,7 +350,6 @@ def main():
|
|
345 |
moral_trajectories = {foundation: [] for foundation in MORAL_FOUNDATIONS}
|
346 |
|
347 |
for segment in segments:
|
348 |
-
segment = segment[:512]
|
349 |
segment_scores = analyzer.analyze_moral_foundations(segment)
|
350 |
for foundation, score in segment_scores.items():
|
351 |
moral_trajectories[foundation].append(score)
|
|
|
124 |
|
125 |
return aggregated_scores
|
126 |
|
127 |
+
def analyze_emotional_trajectory(self, text, window_size=5, ngram_size=3):
|
128 |
+
"""Enhanced emotional trajectory analysis using n-grams and relative scoring"""
|
129 |
+
# Create overlapping n-grams
|
130 |
+
words = text.split()
|
131 |
+
ngrams = [' '.join(words[i:i+ngram_size]) for i in range(0, len(words)-ngram_size+1)]
|
132 |
|
133 |
+
# Get raw sentiment scores
|
134 |
sentiment_scores = []
|
135 |
+
for ngram in ngrams:
|
136 |
+
result = self.sentiment_pipeline(ngram)[0]
|
137 |
+
# Use confidence score directly without binary transformation
|
138 |
+
raw_score = result['score']
|
139 |
+
sentiment_scores.append(raw_score)
|
140 |
+
|
141 |
+
# Normalize scores to show relative variations
|
142 |
+
if sentiment_scores:
|
143 |
+
min_score = min(sentiment_scores)
|
144 |
+
max_score = max(sentiment_scores)
|
145 |
+
score_range = max_score - min_score
|
146 |
+
if score_range > 0:
|
147 |
+
sentiment_scores = [(s - min_score) / score_range * 2 - 1 for s in sentiment_scores]
|
148 |
|
149 |
+
# Apply smoothing for cleaner visualization
|
150 |
smoothed_scores = (savgol_filter(sentiment_scores, window_length=window_size, polyorder=2)
|
151 |
+
if len(sentiment_scores) > window_size else sentiment_scores)
|
152 |
+
|
153 |
return smoothed_scores
|
154 |
|
155 |
def detect_named_entities(self, text):
|
|
|
300 |
|
301 |
with tab2:
|
302 |
st.subheader("Speech Trajectory Analysis")
|
|
|
303 |
col1, col2 = st.columns(2)
|
304 |
|
305 |
with col1:
|
306 |
st.write("### Emotional Flow")
|
307 |
+
# Get enhanced sentiment trajectory with n-grams
|
308 |
+
sentiment_scores = analyzer.analyze_emotional_trajectory(text, window_size=5, ngram_size=3)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
309 |
|
310 |
+
# Create segment labels based on n-gram windows
|
311 |
+
segment_labels = [f"{i+1}" for i in range(len(sentiment_scores))]
|
|
|
312 |
|
313 |
trajectory_fig = go.Figure(data=go.Scatter(
|
314 |
x=segment_labels,
|
315 |
+
y=sentiment_scores,
|
316 |
mode='lines+markers',
|
317 |
line=dict(
|
318 |
color='#1f77b4',
|
|
|
322 |
size=8,
|
323 |
color='#1f77b4',
|
324 |
symbol='circle'
|
325 |
+
),
|
326 |
+
hovertemplate='Segment %{x}<br>Score: %{y:.2f}<extra></extra>'
|
327 |
))
|
328 |
|
329 |
trajectory_fig.update_layout(
|
330 |
title='Emotional Flow Throughout the Speech',
|
331 |
xaxis_title='Speech Segments',
|
332 |
+
yaxis_title='Relative Emotional Tone',
|
333 |
yaxis=dict(
|
334 |
+
ticktext=['Most Negative', 'Neutral', 'Most Positive'],
|
335 |
tickvals=[-1, 0, 1],
|
336 |
range=[-1.1, 1.1],
|
337 |
gridcolor='lightgray'
|
|
|
350 |
moral_trajectories = {foundation: [] for foundation in MORAL_FOUNDATIONS}
|
351 |
|
352 |
for segment in segments:
|
|
|
353 |
segment_scores = analyzer.analyze_moral_foundations(segment)
|
354 |
for foundation, score in segment_scores.items():
|
355 |
moral_trajectories[foundation].append(score)
|