Текст-майнинг с пандами, облаками и яблоками

Представьте ситуацию: вас назначили спикером на мероприятии, и вы даже знаете, о чем хотите рассказать аудитории. Но будет ли публикой воспринят ваш доклад так, как вы себе это представляли? Давайте посмотрим, что может пойти не так и как это исправить.

Как часто нам приходится выступать с докладом, презентацией, проводить обучение, быть спикером на конференции? Если деятельность напрямую не связана с человеческим общением, навык грамотно доносить свою точку зрения теряется естественным образом. Друзья и близкие зачастую воспринимают нас “как есть”, исключая обратную связь для сохранения отношений. Несмотря на лояльность друзей и коллег, практика публичных выступлений важна и необходима для поддержания способности передавать свои мысли и чувства.

Данное исследование поможет разобраться с нашими вербальными привычками и подсветит зоны роста. К её созданию меня подтолкнул спикер одного из youtube каналов it-направленности. Его речь, наполненная идиомами и вводными словами, мешала восприятию основного полезного контента. Впоследствии родилась идея перевести аудиозаписи роликов в текст и выяснить, какие выражения чаще других перегружают речь. Первой задачей стала транскрибация целевой аудиодорожки, второй – анализ текста, третьей - выводы и работа над ошибками.

Детали исследования с полным кодом я выложил на GitHub.

Транскрибация

Поиск качественного инструмента для анализа аудио свелся к выбору между облачными сервисами. Решения, доступные 'for free' в открытых репозиториях не соответствовали моим ожиданиям по качеству результата. Адекватное решение, способное обрабатывать длинные записи, нашлось только у тындекса. После нетривиальных настроек облака стал доступен API асинхронного распознавания. Настройки сервиса описаны здесь: cloud.yandex.ru/docs/speechkit/. Для теста была записана аудиодорожка с моими впечатлениями за текущий год. Далее в коде используется именно она.

Обработка mp3-файла

import pandas as pd import requests import time import json from collections import Counter

Подключаемся к cloud.yandex.ru , проходим все стартовые настройки сервера и рабочего пространства.

Заливаем аудиозапись в выделенное хранилище облака, назначаем права на чтение сервису Speech_Kit, копируем ссылку на файл, вставляем её в POST-запрос:

# параметры запроса key = 'ваш API - key yc’ # путь к файлу в бакете YC filelink = 'https://storage.yandexcloud.net/bucket0011/test_audio.mp3' body ={ "config": { "specification": { "languageCode": "ru-RU" , "audioEncoding": "MP3" } }, "audio": { "uri": filelink } } header = {'Authorization': 'Api-Key {}'.format(key)} POST = "https://transcribe.api.cloud.yandex.net/speech/stt/v2/longRunningRecognize" # структура POST - запроса согласно инструкции API req = requests.post(POST, headers=header, json=body) #Получаем ответ от сервера, из которого забирам ID задачи на обработку аудиозаписи. data = req.json() id_ = data['id'] print(id_)

Запрашиваем на сервере статус операции раз в 10 секунд и ожидаем окончания процесса распознавания:

for i in range(1000): # проверяем распознано ли аудио GET = "https://operation.api.cloud.yandex.net/operations/{id}" req = requests.get(GET.format(id=id_), headers=header) req = req.json() # если распознано — выходим из цикла if req['done']: break # если нет — выводим сообщение print("файл в обработке") # ждём 10 секунд time.sleep(10) #создаем временные хранилища all_sentenses = [] sentenses_dic = {} all_text ='' for id,chunk in enumerate(req['response']['chunks']): # if id%2==1: #актуально только для двухканального аудио chnk = chunk['alternatives'][0]['text'].lower() all_text = all_text+chnk+' ' print("Часть распознанного текста: ",all_text[:55])

Переводим весь текст в нижний регистр, чистим от знаков пунктуации:

all_text = all_text.lower() all_text = all_text.replace('.','').replace(',','').replace(' - ','')

Анализ текста

Ищем уникальные идиомы из двух слов, не подпадающие под стандартные речевые обороты:

def get_word_pairs_dic(data): dic_words_order1 = {} counter=0 for num, word in enumerate(data.split()): dic_words_order1[num] = word all_p =[] all_p2 =[] pair=[] pair2=[] p='' p2='' cnt2=0 for word in dic_words_order1.items(): pair.append(word[1]) # сочетания двух слов pair2.append(word[1]) if int(word[0])%2==0: try: p = pair[0]+' '+pair[1] except: pass all_p.append(p) pair=[] # сочетания двух слов со смещением на 1 слово if int(word[0])%2==1: try: p2 = pair2[0]+' '+pair2[1] except: pass all_p2.append(p2) pair2=[] # ------------ чистим списки от пробелов ----------------- try: all_p.pop(all_p.index('')) except: pass try: all_p2.pop(all_p2.index('')) except: pass # -------------- удаляем дубликаты ------------------ all_p = list(set(all_p)) all_p2 = list(set(all_p2)) return all_p ,all_p2 all_pairs1 ,all_pairs2 = get_word_pairs_dic(all_text)

Считаем количество повторений пар из 2 слов в тексте:

def pair_counter(pair_list,text): phrase_dic = dict(zip(pair_list,[text.count(k) for k in pair_list ])) df_phrase = pd.DataFrame.from_dict(phrase_dic, orient='index') df_phrase = df_phrase.reset_index().rename(columns={'index': 'word_pair', 0: 'count'}) df_phrase.where(df_phrase['word_pair'].str.len()>5).sort_values(by='count', ascending = False) return df_phrase def combine_pairs_count_results(pair_list, pair_list2, text): df_pairs = pair_counter(pair_list, text) df_pairs2 = pair_counter(pair_list2, text) combine_df = pd.concat([df_pairs,df_pairs2]) combine_df = combine_df.where(combine_df['word_pair'].str.len()>5).drop_duplicates() .sort_values(by='count', ascending = False) return combine_df

Объединяем результаты и оставляем уникальные:

combine_df = combine_pairs_count_results(all_pairs1, all_pairs2,all_text) combine_df[:5] word_pair count 105 это был 6.0 28 в общем 4.0 55 и потом 3.0 81 22 год 3.0 71 был еще 3.0

Промежуточные выводы:

most_popular_phrase = combine_df.iloc[0]['word_pair'] print(f'В тексте часто повторяется фраза "{most_popular_phrase}"') В тексте часто повторяется фраза "это был"

Если мы ищем конкретные речевые обороты, можно упростить процесс перебора, задав их в явном виде:

bad_word_dic = {} bad_words = ['то есть','по моему','по-моему','честно говоря','как бы','так сказать','по сути','собственно говоря','как бы' ,'таким образом','как говорится','так далее','как его','так вот','как сказать','на самом деле','в общем-то' ,'в общем','в некотором роде','в принципе','типа того','в самом деле','всё такое','в целом','то есть' ,'это самое','ну вот','ну это','так сказать','да ладно', 'можно сказать', 'как-то','не вопрос','без проблем' ,'как-то так','ничего себе','соответственно']

Создаем словарь повторений выбранных фраз в тексте:

def bad_phrase_counter(text): dic = dict(zip(bad_words,[text.count(k) for k in bad_words ])) df = pd.DataFrame.from_dict(dic, orient='index') df = df.reset_index().rename(columns={'index': 'word', 0: 'count'}) return df

Считаем повторения слов-паразитов в тексте:

df = bad_phrase_counter(all_text) df.sort_values(by='count', ascending = False)[:5] word count 16 в общем 4 1 по моему 1 18 в принципе 0 19 типа того 0 20 в самом деле 0

Считаем количество повторений отдельных слов в тексте:

def word_counter(all_sentenses): all_words = [] for sentance in all_sentenses: for word in sentance.split(sep=' '): word = word.lower() if len(word)>=2: all_words.append(word) unique = dict(zip(all_words,[all_words.count(i) for i in all_words])) df = pd.DataFrame.from_dict(unique, orient='index') df2 =df.reset_index().rename(columns={'index': 'word', 0: 'count'}) return df2 all_sentenses = all_text.split() df_words = word_counter(all_sentenses) df_words.sort_values(by='count', ascending = False)[:5] word count 71 это 14 12 на 10 33 что 10 56 не 10 22 так 10

Находим самую "вредную" фразу из всего текста, даем рекомендации:

bad_word = str(combine_df.iloc[0]['word_pair']) bad_word2 = str(combine_df.iloc[1]['word_pair']) print(f'Самые популярные выражения в вашей речи - "{bad_word}" и "{bad_word2}".') word_to_post = bad_word.replace(' ','%20') word_to_post2 = bad_word2.replace(' ','%20') print(f'Ознакомьтесь, пожалуйста, с их синонимами: \nhttps://sinonim.org/s/ {word_to_post} \nhttps://sinonim.org/s/{word_to_post2}') Самые популярные выражения в вашей речи - "это был" и "в общем". Ознакомьтесь, пожалуйста, с их синонимами: https://sinonim.org/s/это%20был https://sinonim.org/s/в%20общем

Историческое отступление. Стив Джобс

Давайте немного отвлечемся и для проверки работы скрипта возьмем текст презентации компании Apple 2007 года, где исполнительный директор анонсировал первый мобильный телефон компании с сенсорным дисплеем и функцией геолокации. Анализ текста позволит нам понять, какие фразы Стив Джобс использовал для представления своего нового творения общественности.

Для упрощения процесса загружаем речь спискеров с сайта https://singjupost.com/ по ссылке: https://singjupost.com/wp-content/uploads/2014/07/Steve-Jobs-iPhone-2007-Presentation-Full-Transcript.pdf

Оставляем только речь Стива:

with open ('apple2007_.txt','r') as file: presentation_text = file.read() presentation_text = presentation_text.replace('.','').replace(',','').replace(' - ','') presentation_text = presentation_text.lower() print(presentation_text[:211]) this is the day i’ve been looking forward to for two and a half years every once in a while a revolutionary product comes along that changes everything and apple has been – well first of all one’s very fortunate

Разбиваем текст на пары рядом стоящих слов:

all_p ,all_p2 = get_word_pairs_dic(presentation_text) all_p[:5] ['completely automatically', 'hold on', 'wide screen', 'mail this', 'are calling']

Считаем количество повторений пар слов:

combine_df2 = combine_pairs_count_results(all_p, all_p2,presentation_text) combine_df2[:10].sort_values(by='count', ascending = False) word_pair count 1456 going to 68.0 1375 want to 57.0 2436 i want 47.0 2139 this i 44.0 2444 here a 42.0 2942 this is 40.0 3069 here and 39.0 930 in the 38.0 2777 here i 35.0 2473 you can 33.0

Из приведенного результата видно, что речь Cтива наполнена фразами про намерение, желание и простоту. Этот посыл передается аудитории и то, как он вдохновленно рассказывает о новом устройстве и то, как умело использует его в своих руках. Любой человек подсознательно проникнется такой подачей.

Подводя итог, можно сказать, что речь - сильный инструмент, способный убеждать, если вы используете верные слова и честны с аудиторией.

Данное исследование позволяет легко проанализировать аудиозапись или готовый текст. Получив самые популярные фразы в речи, можно понять на сколько они ценны или наоборот бесполезны. Проанализировав результаты, можно улучшить качество высказываний для нашего слушателя, а значит стать приятным собеседником или успешным спикером.

22
Начать дискуссию