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 synset да се държи?


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 отговори ли някой от отговорите на въпроса ви?   -  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 притежаващ желани или положителни качества, особено тези, които са подходящи за определено нещо great.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

Това е моментът, в който също се отказвам да отговоря на широкия и отворен въпрос, който OP е публикувал, защото има МНОГО направено в клъстерирането, което е автоматична магия за обикновените смъртни като мен =)

person alvas    schedule 07.01.2014

Ти каза (курсивът е добавен):

В идеалния случай обаче бих искал алгоритъм, който може да определи, че доброто и страхотното са подобни в моя корпус (може би в съвместен смисъл)

Можете да измерите сходството на думите, като измерите колко често тези думи се появяват в едно и също изречение с други думи (т.е. съвместно срещане). За да уловите по-голяма семантична свързаност, вероятно можете да заснемете и колокациите, тоест колко често думата се появява в същия прозорец от думи в близост до думата.

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

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

Общата идея ще бъде в следната линия:

  1. Вземете чифт биграми, които искате да проверите за сходство
  2. Използвайки вашия корпус, генерирайте функциите за съвместно намиране и съвместно срещане за всяка биграма
  3. Обучете SVM, за да научите характеристиките на първата биграма
  4. Стартирайте SVM при появяванията на другите биграми (получавате известен резултат тук)
  5. Възможно е да използвате резултатите, за да определите дали двете биграми са подобни една на друга
person justhalf    schedule 07.01.2014