NLTK - Автоматический перевод похожих слов

Общая цель: я создаю LDA-модель обзоров продуктов на Python, используя NLTK и Gensim. Я хочу запустить это на разных n-граммах.

Проблема. С юниграммами все отлично, но когда я запускаю биграммы, то начинаю получать темы с повторяющейся информацией. Например, Тема 1 может содержать: ['good product', 'good value'], а Тема 4 может содержать: ['great product', 'great value']. Для человека они, очевидно, передают одну и ту же информацию, но очевидно, что 'good product' и 'great product' — разные биграммы. Как мне алгоритмически определить, что 'good product' и 'great product' достаточно похожи, чтобы я мог перевести все вхождения одного из них в другое (возможно, в то, которое чаще встречается в корпусе)?

Что я пробовал: я экспериментировал с деревом Synset WordNet, но безуспешно. Получается, что good — это «прилагательное», а great — это «прилагательное-спутник», поэтому возвращаем None для подобия пути. Мой мыслительный процесс заключался в следующем:

  1. Часть речи обозначить предложение
  2. Используйте эти POS, чтобы найти правильный Synset
  3. Вычислить сходство двух Synsets
  4. Если они выше некоторого порога, вычислить вхождения обоих слов
  5. Замените наименее встречающееся слово на наиболее часто встречающееся слово

В идеале, однако, мне нужен алгоритм, который может определить, что good и great похожи в моем корпусе (возможно, в смысле совпадения), чтобы его можно было распространить на слова, которые не t являются частью общего английского языка, но появляются в моем корпусе, и поэтому его можно расширить до n-грамм (возможно, Oracle и terrible являются синонимами в моем корпусе, или feature engineering и feature creation похожи).

Любые предложения по алгоритмам или предложения по настройке синсета WordNet?


person user2979931    schedule 06.01.2014    source источник
comment
Они не передают ту же информацию мне. Великое сильнее хорошего. Кроме того, хорошая ценность предполагает, что продукт имеет привлекательную цену для своего уровня качества. Хороший товар говорит о том, что товар качественный. Последний Mac Pro выглядит как отличный продукт, но я бы не назвал его очень выгодным. Один из подходов состоит в том, чтобы спросить, действительно ли замена отличного на хорошее или ценности на продукт меняет интересующий нас результат.   -  person ChrisP    schedule 06.01.2014
comment
@ChrisP - я понимаю твою точку зрения. Но вот пример двух тем, которые я получаю: Тема 1 — ['great service', 'good product', 'great price'], Тема 2 — ['good service', 'quality product', 'good price']. Ни один человек не назвал бы их двумя отдельными темами, и это бесполезно, когда есть другие темы, которые можно было бы рассмотреть. И good product, и great product описывают продукт в положительном ключе, и вы можете увидеть, насколько они больше похожи, скажем, на easy reference.   -  person user2979931    schedule 06.01.2014
comment
@user2979931 user2979931 ответил ли какой-нибудь из ответов на ваш вопрос?   -  person alvas    schedule 09.01.2014


Ответы (2)


Если вы собираетесь использовать WordNet, у вас есть

Проблема 1. Устранение неоднозначности словесного смысла (WSD), т. е. как автоматически определить, какой синсет использовать?

>>> for i in wn.synsets('good','a'):
...     print i.name, i.definition
... 
good.a.01 having desirable or positive qualities especially those suitable for a thing specified
full.s.06 having the normally expected amount
good.a.03 morally admirable
estimable.s.02 deserving of esteem and respect
beneficial.s.01 promoting or enhancing well-being
good.s.06 agreeable or pleasing
good.s.07 of moral excellence
adept.s.01 having or showing knowledge and skill and aptitude
good.s.09 thorough
dear.s.02 with or in a close or intimate relationship
dependable.s.04 financially sound
good.s.12 most suitable or right for a particular purpose
good.s.13 resulting favorably
effective.s.04 exerting force or influence
good.s.15 capable of pleasing
good.s.16 appealing to the mind
good.s.17 in excellent physical condition
good.s.18 tending to promote physical well-being; beneficial to health
good.s.19 not forged
good.s.20 not left to spoil
good.s.21 generally admired

>>> for i in wn.synsets('great','a'):
...     print i.name, i.definition
... 
great.s.01 relatively large in size or number or extent; larger than others of its kind
great.s.02 of major significance or importance
great.s.03 remarkable or out of the ordinary in degree or magnitude or effect
bang-up.s.01 very good
capital.s.03 uppercase
big.s.13 in an advanced stage of pregnancy

Допустим, вы каким-то образом уловили правильный смысл, возможно, вы пробовали что-то вроде этого (https://github.com/alvations/pywsd), и допустим, вы правильно поняли POS и synset:

товар.a.01, обладающий желательными или положительными качествами, особенно те, которые подходят для определенной вещи, большой.s.01 относительно большой по размеру, количеству или размеру; больше, чем другие в своем роде

Проблема 2. Как вы собираетесь сравнивать два синсета?

Давайте попробуем функции подобия, но вы поняли, что они не дают вам очков:

>>> good = wn.synsets('good','a')[0]
>>> great = wn.synsets('great','a')[0]
>>> print max(wn.path_similarity(good,great), wn.path_similarity(great, good))
None
>>> print max(wn.wup_similarity(good,great), wn.wup_similarity(great, good))

>>> print max(wn.res_similarity(good,great,semcor_ic), wn.res_similarity(great, good,semcor_ic))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/dist-packages/nltk/corpus/reader/wordnet.py", line 1312, in res_similarity
    return synset1.res_similarity(synset2, ic, verbose)
  File "/usr/local/lib/python2.7/dist-packages/nltk/corpus/reader/wordnet.py", line 738, in res_similarity
    ic1, ic2, lcs_ic = _lcs_ic(self, other, ic)
  File "/usr/local/lib/python2.7/dist-packages/nltk/corpus/reader/wordnet.py", line 1643, in _lcs_ic
    (synset1, synset2))
nltk.corpus.reader.wordnet.WordNetError: Computing the least common subsumer requires Synset('good.a.01') and Synset('great.s.01') to have the same part of speech.
>>> print max(wn.jcn_similarity(good,great,semcor_ic), wn.jcn_similarity(great, good,semcor_ic))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/dist-packages/nltk/corpus/reader/wordnet.py", line 1316, in jcn_similarity
    return synset1.jcn_similarity(synset2, ic, verbose)
  File "/usr/local/lib/python2.7/dist-packages/nltk/corpus/reader/wordnet.py", line 759, in jcn_similarity
    ic1, ic2, lcs_ic = _lcs_ic(self, other, ic)
  File "/usr/local/lib/python2.7/dist-packages/nltk/corpus/reader/wordnet.py", line 1643, in _lcs_ic
    (synset1, synset2))
nltk.corpus.reader.wordnet.WordNetError: Computing the least common subsumer requires Synset('good.a.01') and Synset('great.s.01') to have the same part of speech.
>>> print max(wn.lin_similarity(good,great,semcor_ic), wn.lin_similarity(great, good,semcor_ic))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/dist-packages/nltk/corpus/reader/wordnet.py", line 1320, in lin_similarity
    return synset1.lin_similarity(synset2, ic, verbose)
  File "/usr/local/lib/python2.7/dist-packages/nltk/corpus/reader/wordnet.py", line 789, in lin_similarity
    ic1, ic2, lcs_ic = _lcs_ic(self, other, ic)
  File "/usr/local/lib/python2.7/dist-packages/nltk/corpus/reader/wordnet.py", line 1643, in _lcs_ic
    (synset1, synset2))
nltk.corpus.reader.wordnet.WordNetError: Computing the least common subsumer requires Synset('good.a.01') and Synset('great.s.01') to have the same part of speech.
>>> print max(wn.lch_similarity(good,great), wn.lch_similarity(great, good))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/dist-packages/nltk/corpus/reader/wordnet.py", line 1304, in lch_similarity
    return synset1.lch_similarity(synset2, verbose, simulate_root)
  File "/usr/local/lib/python2.7/dist-packages/nltk/corpus/reader/wordnet.py", line 638, in lch_similarity
    (self, other))
nltk.corpus.reader.wordnet.WordNetError: Computing the lch similarity requires Synset('good.a.01') and Synset('great.s.01') to have the same part of speech.

Давайте попробуем другую пару синсетов, так как у good есть и satellite-adjective, и adjective, а у great есть только satellite, давайте пойдем с наименьшим общим знаменателем:

good.s.13 resulting favorably
great.s.01 relatively large in size or number or extent; larger than others of its kind

Вы понимаете, что до сих пор нет информации о сходстве для сравнения между satellite-adjective:

>>> print max(wn.lin_similarity(good,great,semcor_ic), wn.lin_similarity(great, good,semcor_ic))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/dist-packages/nltk/corpus/reader/wordnet.py", line 1320, in lin_similarity
    return synset1.lin_similarity(synset2, ic, verbose)
  File "/usr/local/lib/python2.7/dist-packages/nltk/corpus/reader/wordnet.py", line 789, in lin_similarity
    ic1, ic2, lcs_ic = _lcs_ic(self, other, ic)
  File "/usr/local/lib/python2.7/dist-packages/nltk/corpus/reader/wordnet.py", line 1645, in _lcs_ic
    ic1 = information_content(synset1, ic)
  File "/usr/local/lib/python2.7/dist-packages/nltk/corpus/reader/wordnet.py", line 1666, in information_content
    raise WordNetError(msg % synset.pos)
nltk.corpus.reader.wordnet.WordNetError: Information content file has no entries for part-of-speech: s
>>> print max(wn.path_similarity(good,great), wn.path_similarity(great, good))None
None

Теперь кажется, что WordNet создает больше проблем, чем решает что-либо здесь, давайте попробуем другое средство, давайте попробуем кластеризацию слов, см. http://en.wikipedia.org/wiki/Word-sense_induction

Это когда я также отказываюсь отвечать на широкий и открытый вопрос, который опубликовал ОП, потому что в кластеризации сделано МНОГО, что является автоматической магией для простых смертных, таких как я =)

person alvas    schedule 07.01.2014

Вы сказали (выделение добавлено):

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

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

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

В Python вы можете использовать sklearn, особенно вы можете посмотреть SVM (с примерами кода), чтобы помочь вам начать работу.

Общая идея будет примерно такой:

  1. Получите пару биграмм, которые вы хотите проверить на сходство
  2. Используя свой корпус, создайте функции словосочетания и совместной встречаемости для каждой биграммы.
  3. Обучите SVM изучению особенностей первой биграммы
  4. Запустите SVM для вхождений других биграмм (здесь вы получите очки)
  5. Можно использовать баллы, чтобы определить, похожи ли две биграммы друг на друга.
person justhalf    schedule 07.01.2014