Написание синонимайзера текста на языке Python

Мы продолжаем курс «Обработка данных: обработка естественных языков на языке Python».

В данной лекции мы напишем код для синонимайзера текста. Если вы не хотите писать код, а просто его просмотреть, вы можете перейти по адресу, зайти в папку nlp_class и найти файл article_spinner.py. Мы снова будем рассматривать отзывы на электронику на Amazon.

На этот раз нам понадобится библиотека NLTK, генератор случайных чисел для отыскания вероятностей слов и, поскольку обзоры Amazon находятся в формате XMS, парсер Beautiful Soup.

import nltk

import random

import numpy as np

from bs4 import BeautifulSoup

Из примера с анализом тональности скопируем код для загрузки положительных отзывов.

positive_reviews = BeautifulSoup(open(‘electronics/positive.review’).read())

positive_reviews = positive_reviews.findAll(‘review_text’)

Прежде всего соберём все триграммы. Создадим словарь с ключом в виде предыдущего и последующего слов. Значением же будет возможное значение среднего слова. Для этого пройдёмся по всем отзывам, при этом преобразуем все слова в нижний регистр, поскольку нам не нужны два варианта одного и того же слова. Для этой же цели используем токенайзер из библиотеки NLTK.

trigrams = {}

for review in positive_reviews:

s = review.text.lower()

tokens = nltk.tokenize.word_tokenize(s)

for i in xrange(len(tokens) – 2):

k = (tokens[i], tokens[i+2])

if k not in tragrams:

trigrams[k] = []

trigrams[k].append(tokens[i+1])

Следующее, что мы должны сделать, – преобразовать наши возможные средние слова в вектор вероятностей. Для этого создадим ещё один словарь и пройдёмся по всем триграммам. В данном случае неважно, существует ли только одно возможное среднее слово, поскольку оно всё равно будет заменяться.

trigrams_probabilities = {}

for k, words in trigrams.iteritems():

if len(set(words)) > 1:

d = {}

n = 0

for w in words:

if w not in d:

d[w] = 0

d[w] += 1

n += 1

for w, c in d.iteritems():

d[w] = float(c) / n

trigrams_probabilities[k] = d

Теперь нам необходимо написать функцию, которая бы делала случайную выборку из вероятностей триграмм. Назовём её random_sample. Аргументом её будет слово, а значением – вероятность этого слова.

def random_sample(d):

r = random.random()

cumulative = 0

for w, p in d.iteritems():

cumulative += p

if r < cumulative:

return w

Следующим делом напишем функцию test_spinner для проверки синонимайзера. Она будет случайным образом выбирать отзыв, а затем пытаться изменить её. Отзыв и его модификация будет выводиться на экран, чтобы мы могли сравнить их.

def test_spinner():

review = random.choise(positive_reviews)

s = review.text.lower()

print ‘’Original:’’, s

tokens = nltk.tokenize.word.tokenize(s)

for i in xrange(len(tokens) -2):

if random.random() < 0.2:

k = (tokens[i], tokens[i*2])

if k in trigrams_probabilities:

w = random_sample(trigrams_probabilities[k])

tokens[i+1] = w

print ‘’Spun:’’

Тут надо сказать, что я предварительно проверял синонимайзер, и оказалось, что для вывода изменённого предложения необходимо сделать кое-что ещё. NLTK почему-то любит токенизировать ещё и знаки препинания – это могут быть пробелы, апострофы, точки, запятые, знаки доллара и восклицательные знаки. Поэтому надо добавить ещё строку

print ‘’ ‘’.join(tokens).replace(‘’ .’’, ‘’.’’).replace(‘’ ‘‘’, ‘’‘’’).replace(‘’ ,’’, ‘’,’’).replace(‘’$ ‘’, ‘’$’’).replace(‘’ !’’, ‘’!’’)

Итак, давайте проверим наш синонимайзер.

Первое предложение «У меня была небольшая проблема с распознаванием моей системой, когда я устанавливал впервые…» – ничего не изменено. Вообще, из всего текста изменено выражение «превосходная чёткость и яркость» на «превосходная чёткость и профессионализм», что бессмысленно.

Попробуем ещё раз. Имеем: «Пятьдесят три являются преемниками принтеров HP» – бессмыслица. «Оба они принимают только несколько карт памяти Secure Digital ёмкостью 1 Гб», «Поскольку операционная система имеет только приблизительно 1-Гб адресное пространство файловой системы», «После примерно трёх флэш-карт Secure Digital»…

Я бы рекомендовал вам проверить работу синонимайзера ещё и самостоятельно, чтобы вы могли посмтотреть на различные получаемые результаты. В большинстве случаев они бессмысленные и довольно смешные.

Итак, о чём это нам говорит? Такой результат показыват со всей определённостью, что контекст должен учитываться в гораздо большей мере, чем лишь два соседних слова. Это также показывает, что наше марковское предположение не соответсвует действительности. Вполне вероятно, что мы проделали лишь 5% работы, необходимой для того, чтобы создать действительно хороший синонимайзер текста.

Из своего опыта и результатов, которые я вижу в топе Google, такой ещё не создан.

Андрей Никитенко
Андрей Никитенко
Задать вопрос эксперту
Понравилась статья? Поделить с друзьями:
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!:

Share via
Copy link