Machine learning
NewTechAudit
82

Три шага для экспресс-обработки и разметки текста​

Сегодня мы поговорим об анализе текста. Нередко перед нами стоит задача обработать большой массив однотипного текста и выбрать/подсветить определенные фрагменты, которые будут использованы в аудиторском проекте.

В закладки

Рассмотрим стандартную ситуацию, когда надо сделать и обработать подборку негатива СМИ по контрагентам. Если эта задача разовая, количество контрагентов не велико и анализируемый период достаточно короткий, то не стоит нагружать себя и готовить автоматизированное решение не имеет смысла. Поэтому данная информация будет интересна тем, кто планирует регулярно обрабатывать большие массивы информации.

Для успешного решения данной задачи необходимо выполнить 3 шага:

1 шаг. Получить информацию.
2 шаг. Убрать лишнее.
3 шаг. Сделать разметку.

Рассмотрим каждый из этих шагов более подробно.

1 шаг. Получить информацию

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

  • результаты запросов в поисковых системах (практически бесплатный, но наиболее трудозатратный вариант);
  • выгрузки данных с помощью новостных агрегаторов (наиболее удобный и простой в применении, но достаточно дорогой способ, при этом для разовых работ можно воспользоваться тестовым доступом);
  • внутренние источники в организации.

Для тестирования нашего алгоритма мы оформили тестовый доступ к новостному агрегатору, с помощью которого создали подборку СМИ из 6000 новостей за год по 300 компаниям, находящимся в фокусе внимания федеральных, региональных СМИ.

2 шаг. Убрать лишнее

На этом шаге нам требуется качественно очистить выгруженную информацию от «мусора» или шумов.

На примере задачи с негативом СМИ по контрагентам можно выделить следующие виды шумов:

  • информация, которая не соответствует контрагенту;
  • информация дублируется;
  • информация не является негативной.

Для решения задачи по очистке шумов мы применяли последовательно 4 алгоритма.

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

Алгоритм 1. Удаление дублей с использованием библиотеки Pandas, метод класса DataFrame – drop_duplicates()

Использование данной библиотеки позволяет удалить полные дубли по большому массиву информации менее чем за секунду, поэтому мы использовали ее в первую очередь.

На нашей тестовой выборке мы сократили объем информации подлежащей обработке почти в 2 раза за 16 мсек.

Пример кода:

data.drop_duplicates(subset='Выдержки из текста', inplace = True) data.drop_duplicates(subset='Заголовок', inplace = True)

Переменные:

  • data – массив новостей;
  • subset – колонка DataFrame, по которой метод определяет дубликаты.

Алгоритм 2. Удаление шумов не относящуюся к контрагенту.

В данном случае требуется использовать доступную информацию, полученную в ходе сотрудничества с контрагентом.

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

После чего написали процедуру, которая удаляет новости по региональному признаку. На выходе у нас остались новости только всех федеральных СМИ и части региональных СМИ, в которых контрагент ведет деятельность.

Алгоритм работал чуть менее полминуты и сократил нашу подборку на 1000 новостей.

Для удаления шумов по территориальному признаку мы использовали стандартные процедуры циклов и ветвления. В цикле просматриваем регионы новостей и проверяем, ведет ли контрагент деятельность в этом регионе. На выходе получаем массив «флагов», по которому мы в дальнейшем фильтруем данные и избавимся от дубликатов.

Пример кода:

ter_data = pd.read_excel('Данные_о_территориальной_принадлежности_контрагента.xlsx') #создадим список флагов not_in_terr_flag = [] for row in range(data.shape[0]): # id контрагента в массиве новостей id_ka = data['id'].iloc[row] # флаг "соответствия" региона новости региону контрагента local_flag = 0 # далее идет сравнение if data['Регион источника'].iloc[row] not in re.split('\\.| |,|\"|\)|\)',str(ter_data[ter_data.id == id_ka][['Регион', 'id']]).groupby('INN').sum().iloc[0,0]): not_in_terr_flag.append(1) continue else: not_in_terr_flag.append(0)

Алгоритм 3. Удаление дублей побитовым методом.

Учитывая практику некоторых СМИ перепечатывать другие источники, внося незначительные изменения в текст, мы решили удалить дубли путем побитового сравнения текстов.

Наша тестовая процедура удаляет дублирующие новости, совпадающие побитово на 70 и более процентов при условии, что новости опубликованные в одну дату по одному контрагенту.

На тестовой выборке этот алгоритм работает чуть более 35 сек. и удаляет 174 дубля или 9% от своего входа.

В итоге наша исходная выборка сократилась до 1 139 новостей.

Для побитового метода были разработаны 2 функции:

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

Пример кода:

# битовый поиск дубликатов def word_duplicate(slovo_a, slovo_b, tolerance = .7): local_match_counts = 0 for x, y in zip(bytearray(slovo_a, encoding='utf-8'), bytearray(slovo_b, encoding='utf-8')): if x == y: local_match_counts+=1 if min(len(slovo_a),len(slovo_b)) > 0 and local_match_counts/min(len(slovo_a),len(slovo_b)) > tolerance: return True else: return False # битовый поиск дубликатов по текстам def text_duplicate(text_a, text_b, tolerance = .7, w_tolerance = .7): predlojenie_a = re.split('\\.| |,|\"|\)|\)', text_a) predlojenie_b = re.split('\\.| |,|\"|\)|\)', text_b) if len(predlojenie_a) > len(predlojenie_b): predlojenie_a, predlojenie_b = predlojenie_b, predlojenie_a counter = 0 for word_a in predlojenie_a: for word_b in predlojenie_b: if word_duplicate(word_a, word_b, w_tolerance): counter += 1 break else: continue if counter/len(predlojenie_a) > tolerance: return True else: return False

Параметры tolerance и w_tolerance позволяют регулировать «толерантность» к неполным дубликатам (в данном случае установлено значение 0.7, т.е. слова и предложения признаются дубликатами в случае совпадение на 70 и более процентов)

Алгоритм 4. Удаление дублей с использованием PyMorphy2.

Морфологический анализатор PyMorphy2 позволяет нормализовать формы слов и провести их последующее сравнение. Это наиболее медленный алгоритм в нашем арсенале, поэтому мы использовали его на последнем этапе. Логика нашей процедуры была такой – удаляем дублирующие новости, которые пословно совпадают на 70 и более процентов при условии, что они опубликованные в одну дату по одному контрагенту.

Работа этого алгоритма заняла более 8 часов и позволила удалить еще 363 дубля.

Основной продукт этого этапа — нормализованные формы слов, которые используются нами на этапе разметки.

Суть алгоритма предельно похожа на предыдущий, за исключением использования класса MorphAnalyzer() библиотеки PyMorpy2.

Пример кода:

from pymorphy2 import MorphAnalyzer mor_an = MorphAnalyzer() # поиск дубликатов с помощью pymorphy def morphy_word(first, second): p = mor_an.parse(first)[0] q = mor_an.parse(second)[0] # учитываются только потенциально информативные части речи if p.tag.POS in ['VERB','NOUN', 'ADJF','ADJS','PRTF','PRTS','INFN']\ and q.tag.POS in ['VERB','NOUN', 'ADJF','ADJS','PRTF','PRTS','INFN']: if p.normal_form == q.normal_form: return True else: return False else: return False # поиск дубликатов текстов с помощью pymorphy def morphy_text(first_sent, second_sent, tolerance = .7): predlojenie_a = re.split('\\.| |,|\"|\)|\)', first_sent) predlojenie_b = re.split('\\.| |,|\"|\)|\)', second_sent) if len(predlojenie_a) > len(predlojenie_b): predlojenie_a, predlojenie_b = predlojenie_b, predlojenie_a counter = 0 len_sent = 1 for word_a in predlojenie_a: p_new = mor_an.parse(word_a)[0] if p_new.tag.POS in ['VERB','NOUN','ADJF','ADJS','PRTF','PRTS', 'INFN']: len_sent += 1 for word_b in predlojenie_b: dupl_word = morphy_word(word_a, word_b) if dupl_word: counter += 1 break else: continue if counter/len_sent > tolerance: return True else: return False

3 шаг. Сделать разметку

На данном этапе необходимо создать «Мешок слов» и разработать пул правил для разметки текста.

Наполнить «Мешок слов» вы можете на свое усмотрение, в качестве примера рисковых событий могут быть выбраны фразы «Банкротство», «Ликвидация», «Долги», «Иски», «Акционерный конфликт».

Наш тестовый «Мешок слов» состоял из 90 слов, а алгоритм разметки позволял разметить новости по компаниям по 12 типам событий. Как я уже ранее писал, алгоритм разметки использует полученную на предыдущем этапе нормализованные тексты, на выходе мы получаем статьи, в которых упомянуты слова и/или словосочетания из «Мешка слов».

Из 1498 новостей, поступивших на обработку, на выходе осталось 136, соответствующих 12-ти выбранным типам событий.

Для алгоритма разметки мы использовали стандартные процедуры циклов и ветвления. Функция получает на вход предложение, ищет в нем слова из «Мешка» и возвращает их или сообщение об их отсутствии.

Пример кода:

def trouble_criteria(sentence): data = re.split('\\.| |,|"', sentence) target_words = [] for word_a in data: p_new = mor_an.parse(word_a)[0] if p_new.tag.POS in ['VERB', 'NOUN', 'ADJF', 'ADJS', 'PRTF', 'PRTS', 'INFN']: for word_b in bag_of_words: dupl_word = morphy_word(word_a, word_b) if dupl_word: target_words.append(word_b) else: continue if target_words: return set(target_words) else: return 'Критериев проблемности не обнаружено'

Правильная последовательность применения алгоритмов для удаления дублей и шумов, грамотно составленный «Мешок слов» – вот залог успеха экспресс-обработки и разметки текста! Это позволит Вам существенно сократить количество часов монотонной работы высокооплачиваемых специалистов. Желаем Вам успехов на практике!

Лайфхаки IT, проверенные AI-решения для стандартных задач
{ "author_name": "NewTechAudit", "author_type": "editor", "tags": ["\u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c"], "comments": 0, "likes": 2, "favorites": 4, "is_advertisement": false, "subsite_label": "ml", "id": 116128, "is_wide": true, "is_ugc": false, "date": "Mon, 30 Mar 2020 10:57:29 +0300", "is_special": false }
SEO
Контент — король: как мы с помощью SEO привели 400 тысяч англоязычных геймеров в блог, играя в PUBG
Подготовили кейс по работе с изначально незнакомой нам нишей, да еще и на англоязычную аудиторию. Вот некоторые…
Объявление на vc.ru
0
Комментариев нет
Популярные
По порядку

Прямой эфир