Реферат: Міністерство освіти І науки, молоді та спорту україни національний університет «львівська політехніка» інститут комп’ютерних наук та інформаційних технологій



МІНІСТЕРСТВО ОСВІТИ І НАУКИ, МОЛОДІ ТА СПОРТУ УКРАЇНИ

НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ «ЛЬВІВСЬКА ПОЛІТЕХНІКА»

іНСТИТУТ КОМП’ютерних НАУК та ІНФОРМАЦІЙНИХ ТЕХНОЛОГІЙ


Кафедра систем автоматизованого проектування





ВИВЧЕННЯ БІБЛІОТЕКИ ПРИКЛАДНИХ ПРОГРАМ NLTK, ДЛЯ ОПРАЦЮВАННЯ ТЕКСТІВ ПРИРОДНОЮ МОВОЮ


ЗАСОБИ ДЛЯ РОБОТИ З ЛЕКСИЧНИМИ РЕСУРСАМИ.


Методичні вказівки до лабораторної роботи № 4

з дисципліни «Комп’ютерна лінгвістика»

для студентів спеціальності 7.02030303 «Прикладна лінгвістика»

денної та заочної форм навчання


Затверджено на засіданні кафедри

«Системи автоматизованого проектування»

Протокол № 16 від 17.05.2011 р.


Затверджено на засіданні методичної ради ІКНІ

Протокол № 9-10/11 від 18.05.2011 р.


Зареєстровано в НМУ НУ «ЛП»

№ 3521 від 2.06.2011


Львів-2011

^ ВИВЧЕННЯ БІБЛІОТЕКИ ПРИКЛАДНИХ ПРОГРАМ NLTK, ДЛЯ ОПРАЦЮВАННЯ ТЕКСТІВ ПРИРОДНОЮ МОВОЮ. ЗАСОБИ ДЛЯ РОБОТИ З ЛЕКСИЧНИМИ РЕСУРСАМИ. Методичні вказівки до лабораторної роботи № 4 з дисципліни «Комп’ютерна лінгвістика» для студентів спеціальності 7.02030303 денної та заочної форм навчання/Укл. А.Б.Романюк, І.Ю Юрчак. - Львів: Національний університет «Львівська політехніка», 2011. – 28 с.



Укладачі:

Романюк А. Б., канд. техн. наук, доцент

Юрчак І.Ю., канд. техн. наук, доцент



Відповідальна за випуск:

Юрчак І.Ю., канд. техн. наук, доцент



Рецензент:

Теслюк В.М., д.т.н., професор кафедри САПР
^ Мета робота
Вивчення основ програмування на мові Python.

Вивчення методів доступу та роботи з лексичним ресурсами.

Семантичний словник англійської мови WordNet.
^ Короткі теоретичні відомості 1. Поняття функції та модуля.
При програмуванні часто необхідно частину програми виконати (використати) декілька разів. Наприклад, потрібно написати програму, яка здійснює утворення множини з однини іменників і вона буде виконуватись в різних місцях програми. Швидше ніж повторювати той самий код декілька разів і більш ефективно і надійно організувати цю роботу через функцію. Функція - це програмна конструкція, яку можна викликати з одним або більше вхідними параметрами, і отримувати результат на виході. Визначаємо функцію, використовуючи ключове слово def далі потрібно дати назву функції і визначити вхідні параметри, після двокрапки записується тіло функції. Ключове слово return використовується для відображення значення, яке ми хочемо отримати на виході функції.

>>> def summa(a, b):

c=a+b

return c

>>> summa(3,9)

12

Розглянемо приклад. Функція plural () отримує на вході однину іменника і формує множину на виході.

def plural(word):

if word.endswith('y'):

return word[:-1] + 'ies'

elif word[-1] in 'sx' or word[-2:] in ['sh', 'ch']:

return word + 'es'

elif word.endswith('an'):

return word[:-2] + 'en'

else:

return word + 's'

>>> plural('fairy')

'fairies'

>>> plural('woman')

'women'
^ 1.1. Створення скриптів
Не дивлячись на зручність використання інтерактивного режиму роботи, часто потрібно зберегти початковий програмний код для подальшого використання. В такому разі готуються файли з програмним кодом, які передаються інтерпретатору на виконання. По відношенню до мов програмування, що інтерпретуються, часто початковий код називають скриптом. Файли з кодом на Python зазвичай мають розширення *.py.

Підготувати скрипти можна в середовищі IDLE. Для цього, після запуску середовища в меню потрібно вибрати команду File  New Window (Crtl + N), відкриється нове вікно.

Потім бажано відразу зберегти файл з розширенням *.py. командою FileSave As. За замовченням, файл буде збережено в корні C:\Python26. Після того, як код буде написано, слід знов зберегти файл.

Увага: якщо набирати код, не зберігши файл на початку, то не буде здійснюватися підсвічування синтаксису.

Для запуску скрипту потрібно виконати команду меню Run  Run Module (F5). Після цього в першому вікні (де "працює" інтерпретатор) з'явиться результат виконання коду.

Насправді скрипти можна писати в будь-якому текстовому редакторі (бажано, щоб він підтримував підсвічування синтаксису мови Python). Також існують спеціальні програми для розробки, що надають додаткові можливості і зручності.

Розробляючи ту чи іншу програму протягом довшого періоду додаючи до неї нові функції і змінюючи існуючі або розробляючи декілька версій однієї програми потрібно зберігати тексти програм в окремих файлах і організовувати доступ до відповідних функцій в цих програмах. Збережемо текст останньої функції plural () в окремому файлі textproc.py. тепер можна доступитися до цієї функції імпортувавши її з файлу.

>>> from textproc import plural

>>> plural('wish')

wishes

>>> plural('fan')

fen

Множина змінних і функцій збережених у файлі називаються в Python – модулем. Множина пов’язаних між собою модулів називають – пакетом. Програма обробки корпуса Brown це є приклад модуля, а множина програм для роботи зі всіма корпусами це є приклад пакету. NLTK це множина пакетів, яку називають бібліотекою.
^ 2. Генерація випадкового тексту за допомогою біграмів
Умовний частотний розподіл можна використати для побудови таблиці біграмів (пар слів). Функція NLTK bigrams() , як аргумент бере список слів і повертає список послідовних пар слів.

>>> sent = ['In', 'the', 'beginning', 'God', 'created', 'the', 'heaven', 'and', 'the', 'earth', '.']

>>> nltk.bigrams(sent)

[('In', 'the'), ('the', 'beginning'), ('beginning', 'God'), ('God', 'created'), ('created', 'the'), ('the', 'heaven'), ('heaven', 'and'), ('and', 'the'), ('the', 'earth'), ('earth', '.')]

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


>>> import nltk

>>> from nltk.corpus import genesis

>>> text = nltk.corpus.genesis.words('english-kjv.txt')

>>> bigrams = nltk.bigrams(text)

>>> cfd = nltk.ConditionalFreqDist(bigrams)

>>> print cfd['living']




Для перевірки вірності отриманого результату побудуємо конкорданс для слова living


>>> len(text)

44764

>>> text_concordance = nltk.Text(nltk.corpus.genesis.words('english-kjv.txt'))

>>> text_concordance.concordance("living")

Building index...

Displaying 16 of 16 matches:

od created great whales , and every living creature that moveth , which the wa

aid , Let the earth bring forth the living creature after his kind , cattle ,

he fowl of the air , and over every living thing that moveth upon the earth .

e breath of life ; and man became a living soul . And the LORD God planted a g

th and whatsoever Adam called every living creature , that was the name thereo

; because she was the mother of all living . Unto Adam also and to his wife di

ns ' wives with thee . And of every living thing of all flesh , two of every s

y days and forty nights ; and every living substance that I have made will I d

in the dry land , died . And every living substance was destroyed which was u

And God remembered Noah , and every living thing , and all the cattle that was

thee . Bring forth with thee every living thing that is with thee , of all fl

I again smite any more every thing living , as I have done . While the earth

our seed after you ; And with every living creature that is with you , of the

I make between me and you and every living creature that is with you , for per

ich is between me and you and every living creature of all flesh ; and the wat

ting covenant between God and every living creature of all flesh that is upon


Функція generate_model() містить простий цикл для генерації тексту. Коли ця функція викликається, то одним з її аргументів є слово – початковий контекст (у прикладі 'living') .

В циклі поточне значення змінної word виводиться на екран і її значення замінюється на слово, яке найчастіше є наступним словом (max()) . На наступному кроці циклу вже це слово буде наступним контекстом. Запропонований підхід генерації тексту швидко приводить до зациклювання, якого можна уникнути якщо вибирати наступні слова випадковим чином.

def generate_model(cfdist, word, num=15):

for i in range(num):

print word,

word = cfdist[word].max()

>>> generate_model(cfd, 'living')

living creature that he said , and the land of the land of the land
^ 3. Лексичні ресурси NLTK. Корпуси слів
Лексичний ресурс або просто словник це набір слів тa/або словосполучень, які асоціюються з такою інформацією, як частина мови та опис значення. Лексичні ресурси є вторинними по відношенню до текстів і зазвичай створюються і вдосконалюються з використанням текстів. Наприклад, якщо визначити текст my_text тоді vocab = sorted(set(my_text)) побудує словник тексту my_text, word_freq = FreqDist(my_text) визначить частоту кожного слова в тексті. vocab та word_freq – приклад простих лексичних ресурсів. Так само конкорданс дає інформацію про використання слів і ця інформація може бути використана при побудові словників. Стандартна термінологія для словників (англ. мова) представлена на Рис.1. Словникова стаття містить основне слово (лему), та відповідну інформацію (частина мови значення слова).
^ Рис.1. Термінологія англійської мови для записів словників.
Найпростіший словник це відсортований список слів. Досконаліші словники містять складну структуру записів та зв’язків між ними. В цій лабораторні роботі будуть розглянуті лексичні ресурси, які розповсюджуються разом з NLTK.
^ 3.1. Корпус words
NLTK розповсюджується з деякими корпусами, які насправді є списками слів. Корпус words це файл з Unix, який використовується для перевірки правопису.

>>> import nltk

>>> wordlist = nltk.corpus.words.words()

>>> len(wordlist)

235786

>>> wordlist[:100]

['A', 'a', 'aa', 'aal', 'aalii', 'aam', 'Aani', 'aardvark', 'aardwolf', 'Aaron', 'Aaronic', 'Aaronical', 'Aaronite', 'Aaronitic', 'Aaru', 'Ab', 'aba', 'Ababdeh', 'Ababua', 'abac', 'abaca', 'abacate', 'abacay', 'abacinate', 'abacination', 'abaciscus', 'abacist', 'aback', 'abactinal', 'abactinally', 'abaction', 'abactor', 'abaculus', 'abacus', 'Abadite', 'abaff', 'abaft', 'abaisance', 'abaiser', 'abaissed', 'abalienate', 'abalienation', 'abalone', 'Abama', 'abampere', 'abandon', 'abandonable', 'abandoned', 'abandonedly', 'abandonee', 'abandoner', 'abandonment', 'Abanic', 'Abantes', 'abaptiston', 'Abarambo', 'Abaris', 'abarthrosis', 'abarticular', 'abarticulation', 'abas', 'abase', 'abased', 'abasedly', 'abasedness', 'abasement', 'abaser', 'Abasgi', 'abash', 'abashed', 'abashedly', 'abashedness', 'abashless', 'abashlessly', 'abashment', 'abasia', 'abasic', 'abask', 'Abassin', 'abastardize', 'abatable', 'abate', 'abatement', 'abater', 'abatis', 'abatised', 'abaton', 'abator', 'abattoir', 'Abatua', 'abature', 'abave', 'abaxial', 'abaxile', 'abaze', 'abb', 'Abba', 'abbacomes', 'abbacy', 'Abbadide']

Цей список можна використати для знаходження незвичних та написаних з помилками слів в корпусі текстів, як показано в наступному прикладі:

def unusual_words(text):

text_vocab = set(w.lower() for w in text if w.isalpha())

english_vocab = set(w.lower() for w in nltk.corpus.words.words())

unusual = text_vocab.difference(english_vocab)

return sorted(unusual)

>>> unusual_words(nltk.corpus.gutenberg.words('austen-sense.txt'))

['abbeyland', 'abhorrence', 'abominably', 'abridgement', 'accordant', 'accustomary', 'adieus', 'affability', 'affectedly', 'aggrandizement', 'alighted', 'allenham', 'amiably', 'annamaria', 'annuities', 'apologising', 'arbour', 'archness', ...]

>>> unusual_words(nltk.corpus.nps_chat.words())

['aaaaaaaaaaaaaaaaa', 'aaahhhh', 'abou', 'abourted', 'abs', 'ack', 'acros', 'actualy', 'adduser', 'addy', 'adoted', 'adreniline', 'ae', 'afe', 'affari', 'afk', 'agaibn', 'agurlwithbigguns', 'ahah', 'ahahah', 'ahahh', 'ahahha', 'ahem', 'ahh', ...]

Ця програма працює за принципом фільтра. Спочатку створюється набір (словник) слів тексту, а далі з цього списку видаляються всі слова, які є в корпусі words.
^ Рис.2. Приклад головоломки
Список слів (корпус words) можна використати для розв’язування головоломки, що зображена на Рис.2. Наступна програма в циклі переглядає всі слова і перевіряє їх на відповідність умовам задачі. Перевірки чи є в слові обов’язкова літера #2 та обмеження довжини слова #1 реалізувати просто. Складніше перевірити інші літери слова, особливо з врахуванням що одна з них може зустрічатися два рази (v). Така задача вирішується використанням методу порівняння класу FreqDist #3. Частота букв у слові має бути менше або дорівнювати частоті букв з умови задачі.

>>> puzzle_letters = nltk.FreqDist('egivrvonl')

>>> obligatory = 'r'

>>> wordlist = nltk.corpus.words.words()

>>> [w for w in wordlist if len(w) >= 6 #1

... and obligatory in w #2

... and nltk.FreqDist(w) <= puzzle_letters] #3

['glover', 'gorlin', 'govern', 'grovel', 'ignore', 'involver', 'lienor', 'linger', 'longer', 'lovering', 'noiler', 'overling', 'region', 'renvoi', 'revolving', 'ringle', 'roving', 'violer', 'virole']
^ 3.2. Корпус стоп-слів
В NLTK також включений корпус стоп-слів (незначущі слова). Ці слова часто зустрічаються в текстах, але переважно не мають окремого лексичного значення і переважно видаляються з тексту при його подальшій обробці.

>>> from nltk.corpus import stopwords

>>> stopwords.words('english')

['a', "a's", 'able', 'about', 'above', 'according', 'accordingly', 'across', 'actually', 'after', 'afterwards', 'again', 'against', "ain't", 'all', 'allow', 'allows', 'almost', 'alone', 'along', 'already', 'also', 'although', 'always', ...]

Можна визначити функцію для визначення, який відсоток слів тексту не належить до незначущих слів.

>>> def content_fraction(text):

... stopwords = nltk.corpus.stopwords.words('english')

... content = [w for w in text if w.lower() not in stopwords]

... return len(content) / len(text)

...

>>> from __future__ import division

>>> content_fraction(nltk.corpus.inaugural.words())

0.45629395821182284

За допомогою списку стоп-слів відкинуто третину слів з тексту. Дана програма працює з двома видами корпусів: текстовим корпусом і лексичним ресурсом-словником.
^ 3.3. Корпус імен
Наступний корпус NLTK це корпус імен, об’ємом 8000 одиниць, які поділені на категорії за родами (чоловічим та жіночим). В наступному прикладі здійснюється пошук імен, які зустрічаються в обох категоріях, тобто імен, які належать і жінкам і чоловікам.

>>> names = nltk.corpus.names

>>> names.fileids()

['female.txt', 'male.txt']

>>> male_names = names.words('male.txt')

>>> female_names = names.words('female.txt')

>>> [w for w in male_names if w in female_names]

['Abbey', 'Abbie', 'Abby', 'Addie', 'Adrian', 'Adrien', 'Ajay', 'Alex', 'Alexis', 'Alfie', 'Ali', 'Alix', 'Allie', 'Allyn', 'Andie', 'Andrea', 'Andy', 'Angel', 'Angie', 'Ariel', 'Ashley', 'Aubrey', 'Augustine', 'Austin', 'Averil', ...]

Переважно імена, які закінчуються на букву «а» належать жінкам. Для перевірки цього твердження можна побудувати умовний частотний розподіл і переглянути графічне зображення цього розподілу Рис.3.

>>> cfd = nltk.ConditionalFreqDist(

... (fileid, name[-1])

... for fileid in names.fileids()

... for name in names.words(fileid))

>>> cfd.plot()
^ Рис.3. Умовний частотний розподіл останніх букв чоловічих та жіночих імен.
Можна також відобразити частотний розподіл жіночих та чоловічих імен за першою літерою

>>> cfd_1_litera = nltk.ConditionalFreqDist(

(fileid, name[0])

for fileid in names.fileids()

for name in names.words(fileid))

>>> cfd_1_litera.plot()
4. Словники
Інший тип даних Python - словники. Словники іноді можна зустріти в інших мовах програмування, як "асоціативні блоки пам'яті" або "асоціативні масиви". На відміну від послідовностей, які індексуються за допомогою діапазону чисел, словники індексуються ключами, які можуть бути будь-яким незмінним типом; рядки і числа можуть завжди бути використані як ключі. Кортежі можуть використовуватися як ключі, якщо вони містять лише стрічки, числа, або кортежі; якщо кортеж містить будь-який змінний об'єкт або безпосередньо чи побічно, то кортеж не може використовуватися як ключ. Ви не можете використовувати списки як ключі, оскільки списки можна змінити в словнику через методи, такі як append() і extend() або можна змінити зрізами чи індексованими призначеннями

Словник по суті є неврегульованим набором ключів: ключ завжди виконує вимогу унікальності (в межах одного словника). Пара фігурних дужок створює порожній словник: {. Розміщення відокремленого комами списку пар key:value в межах фігурних дужок додає початкові пари key:value до словника; описаний прийом також допустимий при виведенні словника на друк.

Основні операції над словником - збереження значення з деяким ключем і витягання значення, за вказаним ключем. Також можливо видалити пару key:value за допомогою del. Якщо Ви зберігаєте ключ, який знаходиться вже у використанні, про старе значення, що пов'язане з цим ключем, інтерпретатор забуває. При спробі звернеться до такого неіснуючого ключа - виникне помилка.

Метод keys() об'єкту словник повертає список всіх ключів, використовуваних в словнику, в довільному порядку (якщо Ви хочете сортувати ключі, слід застосувати метод sort() для списку ключів). Перевірка, чи знаходиться єдиний ключ в словнику, слід використовувати метод has_key() словника.

Тут приведений маленький приклад, використання словника:

>>> tel = {'jack': 4098, 'sape': 4139}

>>> type(tel)



>>> help(dict)

Help on class dict in module __builtin__:


class dict(object)


>>> tel['guido']= 4127

>>> tel

{'sape': 4139, 'guido': 4127, 'jack': 4098}

>>> tel['jack']

4098

>>> del tel['sape']

>>> tel['irv']= 4127

>>> tel

{'guido': 4127, 'irv': 4127, 'jack': 4098}

>>> tel.keys()

['guido', 'irv', 'jack']

>>> tel.has_key('guido')

True

>>> 'guido' in tel

True

dict() конструктор формує словник безпосередньо із списків пар "ключ:значення", збережених як кортежі. Коли пари формують шаблон, останній вноситься до списку для використання, шаблони можна стисло визначити із списками ключових значень.

>>> dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])

{'sape': 4139, 'jack': 4098, 'guido': 4127}

>>> dict([(x, x**2) for x in (2, 4, 6)]) # безпосереднє використання списку

{2: 4, 4: 16, 6: 36}

Коли ключі - прості стрічки, іноді простіше визначати такі пари, що використовують параметри з ключами:

>>> dict(sape=4139, guido=4127, jack=4098)

{'sape': 4139, 'jack': 4098, 'guido': 4127}
^ 4.1. Словник із позначенням вимови
Більш багатим лінгвістичним ресурсом може бути словник де кожному слову поставлена у відповідність певна інформація. NLTK включає CMU Pronouncing Dictionary американського варіанту англійської , який розроблений для використання в синтезаторах мови.

>>> entries = nltk.corpus.cmudict.entries()

>>> len(entries)

127012

>>> for entry in entries[39943:39951]:

... print entry

...

('fir', ['F', 'ER1'])

('fire', ['F', 'AY1', 'ER0'])

('fire', ['F', 'AY1', 'R'])

('firearm', ['F', 'AY1', 'ER0', 'AA2', 'R', 'M'])

('firearm', ['F', 'AY1', 'R', 'AA2', 'R', 'M'])

('firearms', ['F', 'AY1', 'ER0', 'AA2', 'R', 'M', 'Z'])

('firearms', ['F', 'AY1', 'R', 'AA2', 'R', 'M', 'Z'])

('fireball', ['F', 'AY1', 'ER0', 'B', 'AO2', 'L'])

Кожному слову в цьому словнику відповідає список фонетичних кодів – окремих позначень для кожного звуку(фон). Бачимо що слово “fire” в американській англійській має два варіанти вимови (односкладний та двоскладний). Позначення в CMU Pronouncing Dictionary детально описані у http://en.wikipedia.org/wiki/Arpabet.

Кожен запис у словнику складається з двох частин, кожна з яких може оброблятися індивідуально завдяки більш складному варіанту for оператора. Замість entry в операторі for entry in entries: записуємо дві змінні word, pron (#1) . В циклі на кожному кроці word відповідає першій частині запису а pron другій. Програма переглядає словник а пошуку записів, вимова яких містить три частини #2. Якщо ця умова справджується значення змінної pron присвоюється новим змінним ph1, ph2, ph3 #3.

>>> for word, pron in entries: #1

... if len(pron) == 3: #2

... ph1, ph2, ph3 = pron #3

... if ph1 == 'P' and ph3 == 'T':

... print word, ph2,

...

pait EY1 pat AE1 pate EY1 patt AE1 peart ER1 peat IY1 peet IY1 peete IY1 pert ER1 pet EH1 pete IY1 pett EH1 piet IY1 piette IY1 pit IH1 pitt IH1 pot AA1 pote OW1 pott AA1 pout AW1 puett UW1 purt ER1 put UH1 putt AH1

Наступний приклад показує використання аналогічного оператора for в спискових висловлюваннях. Ця програма шукає слова у вимові яких на кінці є звуки аналогічні до nicks. Таку програму можна використовувати для пошуку рим для заданих слів.

>>> syllable = ['N', 'IH0', 'K', 'S']

>>> [word for word, pron in entries if pron[-4:] == syllable]

["atlantic's", 'audiotronics', 'avionics', 'beatniks', 'calisthenics', 'centronics', 'chetniks', "clinic's", 'clinics', 'conics', 'cynics', 'diasonics', "dominic's", 'ebonics', 'electronics', "electronics'", 'endotronics', "endotronics'", 'enix', ...]

Результати роботи програми показують відмінності у написанні деяких закінчень з однаковою вимовою(nics, niks, nix, ntic's).
^ Виконати самостійно
Здійснити аналіз наступних прикладів.

>>> [w for w, pron in entries if pron[-1] == 'M' and w[-1] == 'n']

['autumn', 'column', 'condemn', 'damn', 'goddamn', 'hymn', solemn']

>>> sorted(set(w[:2] for w, pron in entries if pron[0] == 'N' and w[0] != 'n'))

['gn', 'kn', 'mn', 'pn']

В позначеннях звуків (фонах) використовуються цифри для позначення наголосів. Наступний приклад дозволяє доступитися до цифрових позначень і знайти у словнику слова за відповідними шаблонами наголосів. В цьому прикладі потрібно звернути увагу на подвійне використання оператора for.

>>> def stress(pron):

... return [char for phone in pron for char in phone if char.isdigit()]

>>> [w for w, pron in entries if stress(pron) == ['0', '1', '0', '2', '0']]

['abbreviated', 'abbreviating', 'accelerated', 'accelerating', 'accelerator', 'accentuated', 'accentuating', 'accommodated', 'accommodating', 'accommodative', 'accumulated', 'accumulating', 'accumulative', 'accumulator', 'accumulators', ...]

>>> [w for w, pron in entries if stress(pron) == ['0', '2', '0', '1', '0']]

['abbreviation', 'abbreviations', 'abomination', 'abortifacient', 'abortifacients', 'academicians', 'accommodation', 'accommodations', 'accreditation', 'accreditations', 'accumulation', 'accumulations', 'acetylcholine', 'acetylcholine', 'adjudication', ...]

Використовуючи умовний частотний розподіл можна знайти слова, які мають подібну вимову. Знайдемо слова перша буква яких Р , які складаються з трьох звуків #2 і згрупуємо їх за першим і останнім звуками #1.

>>> p3 = [(pron[0]+'-'+pron[2], word)

... for (word, pron) in entries

... if pron[0] == 'P' and len(pron) == 3]

>>> cfd = nltk.ConditionalFreqDist(p3)

>>> for template in cfd.conditions():

... if len(cfd[template]) > 10:

... words = cfd[template].keys()

... wordlist = ' '.join(words)

... print template, wordlist[:70] + "..."

...

P-CH perch puche poche peach petsche poach pietsch putsch pautsch piche pet...

P-K pik peek pic pique paque polk perc poke perk pac pock poch purk pak pa...

P-L pil poehl pille pehl pol pall pohl pahl paul perl pale paille perle po...

P-N paine payne pon pain pin pawn pinn pun pine paign pen pyne pane penn p...

P-P pap paap pipp paup pape pup pep poop pop pipe paape popp pip peep pope...

P-R paar poor par poore pear pare pour peer pore parr por pair porr pier...

P-S pearse piece posts pasts peace perce pos pers pace puss pesce pass pur...

P-T pot puett pit pete putt pat purt pet peart pott pett pait pert pote pa...

P-Z pays p.s pao's pais paws p.'s pas pez paz pei's pose poise peas paiz p...

Словник вимови можна використати для обробки тексту. У наступному прикладі програма знаходить вимову всіх зазначених слів.

>>> text = ['natural', 'language', 'processing']

>>> [ph for w in text for ph in prondict[w][0]]

['N', 'AE1', 'CH', 'ER0', 'AH0', 'L', 'L', 'AE1', 'NG', 'G', 'W', 'AH0', 'JH', 'P', 'R', 'AA1', 'S', 'EH0', 'S', 'IH0', 'NG']
^ 4.2. Порівняльні (компаративні) словники
Інший словник в NLTK це порівняльний словник (Swadesh wordlists), який містить 200 спільних слів для 24 мов. Мови ідентифікуються за двосимвольними кодами (ISO 639).

>>> from nltk.corpus import swadesh

>>> swadesh.fileids()

['be', 'bg', 'bs', 'ca', 'cs', 'cu', 'de', 'en', 'es', 'fr', 'hr', 'it', 'la', 'mk', 'nl', 'pl', 'pt', 'ro', 'ru', 'sk', 'sl', 'sr', 'sw', 'uk']

>>> swadesh.words('en')

['I', 'you (singular), thou', 'he', 'we', 'you (plural)', 'they', 'this', 'that', 'here', 'there', 'who', 'what', 'where', 'when', 'how', 'not', 'all', 'many', 'some', 'few', 'other', 'one', 'two', 'three', 'four', 'five', 'big', 'long', 'wide', ...]

До подібних слів з різних мов можна доступитися за допомогою метода entries(), аргументом якого є список мов.

>>> en2fr = swadesh.entries(['en', 'fr'])

>>> en2fr

[('I', 'je'), ('you (singular), thou', 'tu, vous'), ('he', 'il'), ('we', 'nous'), ('you (plural)', 'vous'), ('they', 'ils, elles'), ('this', 'ceci'), ('that', 'cela'), ('here', 'ici'), ('there', 'l\xc3\xa0'), ('who', 'qui'), ('what', 'quoi'), ('where', 'o\xc3\xb9'), ('when', 'quand'), ('how', 'comment'), ('not', 'ne...pas'), ('all', 'tout'), ('many', 'plusieurs'), ('some', 'quelques'), ('few', 'peu'), ('other', 'autre'), ('one', 'un'), ('two', 'deux'), ('three', 'trois'), ('four', 'quatre'), ('five', 'cinq'), ('big', 'grand'), ('long', 'long'), ('wide', 'large')…]

В наступному прикладі порівнюються слова романських і германських мов.

>>> languages = ['en', 'de', 'nl', 'es', 'fr', 'pt', 'la']

>>> for i in [139, 140, 141, 142]:

... print swadesh.entries(languages)[i]

...

('say', 'sagen', 'zeggen', 'decir', 'dire', 'dizer', 'dicere')

('sing', 'singen', 'zingen', 'cantar', 'chanter', 'cantar', 'canere')('play', 'spielen', 'spelen', 'jugar', 'jouer', 'jogar, brincar', 'ludere')('float', 'schweben', 'zweven', 'flotar', 'flotter', 'flutuar, boiar', 'fluctuare')
^ 5. WordNet – лексична база даних англійської мови
WordNet, це семантично орієнтований словник англійської мови, подібний до традиційних тезаурусів але з більш багатою структурою. У WordNet слова групуються у набори синонімів – синсети, кожен із своїм визначенням і зв’язками з іншими синсетами. WordNet 3.0 розповсюджується разом з NLTK і містить 155287 слів та 117659 синсетів. Хоча WordNet розроблявся для психолінгвістики - цей словник широко використовується в NLP та в задачах інформаційного пошуку. Розробки для інших мов проводяться на основі документації, яка наведена у http://www.globalwordnet.org/.

Словник можна запустити як окремий об’єкт за адресою C:\Python26\Lib\site-packages\nltk\app\wordnet_app.py. Він відкривається у вікні браузера, що встановлено за замовченням і має зручний для розуміння і використання інтерфейс.
^ 5.1. Значення і синоніми
Розглянемо наступне речення:

(1) Benz is credited with the invention of motorcar.

Якщо замінити слово motorcar на automobile зміст речення не зміниться.

(2) Benz is credited with the invention of automobile .

Можна вважати, що оскільки заміна слів не вплинула на зміст речень то ці слова синоніми. Для одержання значення слова потрібно вибрати до якої частини мови воно належить. WordNet містить чотири словники (іменники, дієслова, прикметники, прислівники). Знайдемо слово motorcar у словнику іменників:

>>> from nltk.corpus import wordnet as wn

Тут, вираз wordnet as wn позначає, що в подальшому для звертання до словника wordnet буде використана коротша назва wn.

>>> wn.synsets('motorcar')

[Synset('car.n.01')]

Слово motorcar має одне можливе значення і воно ідентифікується як car.n.01 перший сенс іменника car. car.n.01 називають синсетом – множиною синонімічних слів.

>>> wn.synset('car.n.01').lemma_names

['car', 'auto', 'automobile', 'machine', 'motorcar']

Слова в синсет об’єднані за спільним значенням, яке є однакове для всіх слів. В синсеті вказується текстовий опис цього значення та приклад вживання слів з синсету.

>>> wn.synset('car.n.01').definition

'a motor vehicle with four wheels; usually propelled by an internal combustion engine'

>>> wn.synset('car.n.01').examples

['he needs a car to get to work']

Для уникнення двозначності слова з синсету можна ідентифікувати як car.n.01.automobile, car.n.01.motorcar . Такі пари, як синсет і слово називають лемою. Можна переглянути всі леми даного синсету #1, переглянути окрему лему #2, відповідний лемі синсет #3, та ім’я леми #4.

>>> wn.synset('car.n.01').lemmas

#1 перегляд всіх лем даного синсету

[Lemma('car.n.01.car'), Lemma('car.n.01.auto'), Lemma('car.n.01.automobile'), Lemma('car.n.01.machine'), Lemma('car.n.01.motorcar')]

>>> wn.lemma('car.n.01.automobile')

#2 перегляд окремої леми

Lemma('car.n.01.automobile')

>>> wn.lemma('car.n.01.automobile').synset

#3 перегляд синсету відповідної леми

Synset('car.n.01')

>>> wn.lemma('car.n.01.automobile').name #4 дізнатися ім’я леми

'automobile'

Слова automobile та motorcar є однозначні і входять тільки в один синсет. Слово car багатозначне і входить в п’ять синсетів.

>>> wn.synsets('car')

[Synset('car.n.01'), Synset('car.n.02'), Synset('car.n.03'), Synset('car.n.04'), Synset('cable_car.n.01')]

>>> for synset in wn.synsets('car'):

... print synset.lemma_names

...

['car', 'auto', 'automobile', 'machine', 'motorcar']

['car', 'railcar', 'railway_car', 'railroad_car']

['car', 'gondola']

['car', 'elevator_car']

['cable_car', 'car']

До всіх лем слова car можна доступитися наступним чином:

>>> wn.lemmas('car')

[Lemma('car.n.01.car'), Lemma('car.n.02.car'), Lemma('car.n.03.car'), Lemma('car.n.04.car'), Lemma('cable_car.n.01.car')]
^ 5.2. Ієрархія в WordNet
Синсети відповідають абстрактним поняттям, які можуть мати або не мати відповід­них слів. Ці поняття зв’язуються разом в ієрархії. Деякі поняття Entity, State, Event – є загаль­ними і їх називають унікальними початковими поняттями. Інші є більше специфічними. Части­на ієрархії понять наведена на рис.4. Лінії між вузлами вказують на зв’язки (гіперонім\гіпонім), пунктирна лінія вказує, що artefact не є безпосереднім гіперонімом motorcar.
^ Рис.4. Фрагмент ієрархії понять
WordNet дозволяє легко переміщатися між поняттями. Наприклад для поняття motorcar ми можемо переглянути поняття, які є більш специфічними (гіпонім):

>>> motorcar = wn.synset('car.n.01')

>>> types_of_motorcar = motorcar.hyponyms()

>>> types_of_motorcar[26]

Synset('ambulance.n.01')

>>> sorted([lemma.name for synset in types_of_motorcar for lemma in synset.lemmas])

['Model_T', 'S.U.V.', 'SUV', 'Stanley_Steamer', 'ambulance', 'beach_waggon', 'beach_wagon', 'bus', 'cab', 'compact', 'compact_car', 'convertible', 'coupe', 'cruiser', 'electric', 'electric_automobile', 'electric_car', 'estate_car', 'gas_guzzler', 'hack', 'hardtop', 'hatchback', 'heap', 'horseless_carriage', 'hot-rod', 'hot_rod', 'jalopy', 'jeep', 'landrover', 'limo', 'limousine', 'loaner', 'minicar', 'minivan', 'pace_car', 'patrol_car', 'phaeton', 'police_car', 'police_cruiser', 'prowl_car', 'race_car', 'racer', 'racing_car', 'roadster', 'runabout', 'saloon', 'secondhand_car', 'sedan', 'sport_car', 'sport_utility', 'sport_utility_vehicle', 'sports_car', 'squad_car', 'station_waggon', 'station_wagon', 'stock_car', 'subcompact', 'subcompact_car', 'taxi', 'taxicab', 'tourer', 'touring_car', 'two-seater', 'used-car', 'waggon', 'wagon']

Аналогічно можна піднятися по ієрархії і переглянути більш широкі поняття ніж motorcar (гіперніми). Деякі слова мають декілька шляхів вверх, ці слова можуть класифікуватися більш ніж одним способом. Від car.n.01 до entity.n.01 є два шляхи оскільки wheeled_vehicle.n.01 може розглядатися як vehicle та container.

>>> motorcar.hypernyms()

[Synset('motor_vehicle.n.01')]

>>> paths = motorcar.hypernym_paths()

>>> len(paths)

2

>>> [synset.name for synset in paths[0]]

['entity.n.01', 'physical_entity.n.01', 'object.n.01', 'whole.n.02', 'artifact.n.01', 'instrumentality.n.03', 'container.n.01', 'wheeled_vehicle.n.01', 'self-propelled_vehicle.n.01', 'motor_vehicle.n.01', 'car.n.01']

>>> [synset.name for synset in paths[1]]

['entity.n.01', 'physical_entity.n.01', 'object.n.01', 'whole.n.02', 'artifact.n.01', 'instrumentality.n.03', 'conveyance.n.03', 'vehicle.n.01', 'wheeled_vehicle.n.01', 'self-propelled_vehicle.n.01', 'motor_vehicle.n.01', 'car.n.01']

Початкове кореневе поняття для синсета можна переглянути наступним чином.

>>> motorcar.root_hypernyms()

[Synset('entity.n.01')]
^ 5.3. Лексичні зв’язки в WordNet.
Таблиця 1 містить список найбільш важливих типів зв’язків, які реалізовані у WordNet. Таблиця 2 містить повний список зв’язків іменників.
Таблиця 1
Hypernym

Узагальнення

Тварини є гіпернімом собаки

Hyponym

Деталізація

Собака є гіпонімом тварин

Meronym

Частина від

Двері є меронімом будинку

Holonym

Містить складові

Будинок є холонімом дверей

Synonym

Подібне значення

Машина є синонімом автомобіля

Antonym

Протилежне значення

Подобається є антонімом не подобається

Entailment

Необхідна дія

Крок є ентейлментом ходи



Таблиця 2
Relation

Also Called

Definition

Example

Hypernym

Superordinate

From concepts to superordinates

Breakfast meal

Hyponym

Subordinate

From concepts to subtypes

Meal  Lunch

Instance Hypernym

Instance

From instances to their concepts

Austen  Author

Instance Hyponym

Has-Instance

From concepts to concepts instances

Composer  Bach

Member Meronym


Has-Member

From groups to their members

Faculty  Professor

Member Holonym


Member-Of

From members to their groups

Copilot  Crew

Part Meronym

Has-Part

From wholes to parts

Table  Leg

Part Holonym

Part-Of

From parts to wholes

Course  Meal

Substance Meronym




From substances to their subparts

Water  Oxyden

Substance Holonym




From parts of substances to wholes

Gin  Martini

Antonym





Semantic opposition between lemmas

Leader  Follower

Derivationally Related Form




Lemmas w/same morphological root

Destruction  Destroy

Гіперніми та гіпоніми називають лексичними зв’язками тому що вони пов’язують один синсет з іншим. Ці два зв’язки вказують на рух вверх-вниз в ієрархії «is-a». Інший можливий шлях в ієрархії WordNet це від предмету до його складових (меронім), або до поняття яке містить предмет в собі (голоніми). Наприклад, частини дерева – стовбур, крона та ін. part_meronyms() . Речовина з якого дерево зроблено включає heartwood та sapwood; - substance_meronyms(). Багато дерев утворюють ліс - member_holonyms()

>>> wn.synset('tree.n.01').part_meronyms()

[Synset('burl.n.02'), Synset('crown.n.07'), Synset('stump.n.01'),

Synset('trunk.n.01'), Synset('limb.n.02')]

>>> wn.synset('tree.n.01').substance_meronyms()

[Synset('heartwood.n.01'), Synset('sapwood.n.01')]

>>> wn.synset('tree.n.01').member_holonyms()

[Synset('forest.n.01')]

Прикладом складних випадків лексичних зв’язків може бути слово mint , яке має декілька близьких значень. Бачимо, що mint.n.04 є частиною mint.n.02 та речовиною з якої зроблено mint.n.05.

>>> for synset in wn.synsets('mint', wn.NOUN):

... print synset.name + ':', synset.definition

...

batch.n.02: (often followed by `of') a large number or amount or extent

mint.n.02: any north temperate plant of the genus Mentha with aromatic leaves and small mauve flowers

mint.n.03: any member of the mint family of plants

mint.n.04: the leaves of a mint plant used fresh or candied

mint.n.05: a candy that is flavored with a mint oil

mint.n.06: a plant where money is coined by authority of the government

>>> wn.synset('mint.n.04').part_holonyms()

[Synset('mint.n.02')]

>>> wn.synset('mint.n.04').substance_holonyms()

[Synset('mint.n.05')]

Для дієслів характерні зв’язки подібні до наступних:

>>> wn.synset('walk.v.01').entailments()

[Synset('step.v.01')]

>>> wn.synset('eat.v.01').entailments()

[Synset('swallow.v.01'), Synset('chew.v.01')]

>>> wn.synset('tease.v.03').entailments()

[Synset('arouse.v.07'), Synset('disappoint.v.01')]

Дія walking передбачає дію stepping - walking спричиняє (entails) stepping.

Ще один тип зв’язків представлений в WordNet це антоніми:

>>> wn.lemma('supply.n.02.supply').antonyms()

[Lemma('demand.n.02.demand')]

>>> wn.lemma('rush.v.01.rush').antonyms()

[Lemma('linger.v.04.linger')]

>>> wn.lemma('horizontal.a.01.horizontal').antonyms()

[Lemma('vertical.a.01.vertical'), Lemma('inclined.a.02.inclined')]

>>> wn.lemma('staccato.r.01.staccato').antonyms()

[Lemma('legato.r.01.legato')]
^ 5.4. Оцінка подібності в WordNet
Синсети зв’язані між собою складною мережею лексичних зв’язків. Для певного синсету можна переглянути зв’язки у WordNet і знайти синсети, які з ним зв’язані за змістом. Інформація про семантичні взаємозв’язки між словами цінна при класифікації текстів.

Кожен синсет має один або більше шляхів за яким він зводиться до ключового поняття entity.n.01. Два синсети можуть мати спільне ключове поняття і ми нижче за ієрархією це ключове поняття тим ближчі між собою ці два синсети.

>>> right = wn.synset('right_whale.n.01')

>>> orca = wn.synset('orca.n.01')

>>> minke = wn.synset('minke_whale.n.01')

>>> tortoise = wn.synset('tortoise.n.01')

>>> novel = wn.synset('novel.n.01')

>>> right.lowest_common_hypernyms(minke)

[Synset('baleen_whale.n.01')]

>>> right.lowest_common_hypernyms(orca)

[Synset('whale.n.02')]

>>> right.lowest_common_hypernyms(tortoise)

[Synset('vertebrate.n.01')]

>>> right.lowest_common_hypernyms(novel)

[Synset('entity.n.01')]

Зрозуміло що whale це чітко визначене поняття, тоді як vertebrate є більш загальним а entity найбільш загальним. Можна оцінити «загальність» поняття визначивши глибину кожного синсета.

>>> wn.synset('baleen_whale.n.01').min_depth()

14

>>> wn.synset('whale.n.02').min_depth()

13

>>> wn.synset('vertebrate.n.01').min_depth()

8

>>> wn.synset('entity.n.01').min_depth()

0

Семантична подібність двох понять пов’язана з довжиною шляху між цими поняттями в ^ WordNet . Пакет wordnet містить багато засобів для здійснення таких вимірювань (Leacock-Chodorow, Wu-Palmer, Resnik, Jiang-Conrath, Lin ). Наприклад path_similarity (присвоює значення від 0 до 1) базується на найкоротшому шляху, який поєднує поняття за ієрархією гіперонімів (-1 означає що шлях (спільний гіперонім) не знайдено).

>>> right.path_similarity(minke)

0.25

>>> right.path_similarity(orca)

0.16666666666666666

>>> right.path_similarity(tortoise)

0.076923076923076927

>>> right.path_similarity(novel)

0.043478260869565216
^ Додаток А
Сьогодні ми вивчили:

Поняття функції та модуля.

Основні лексичні ресурси NLTK та способи роботи з ними.

Робота з словником WordNet.
^ Порядок виконання роботи
1. Ознайомитися з теоретичними відомостями.

2. Виконати приклади, які використовуються в теоретичних відомостях.

3. Виконати наступні вправи:

Дослідити зв’язки голонім-меронім для іменників. Знайти іменники для демонстрації наступних зв’язків: member_meronyms(), part_meronyms(), substance_meronyms(), member_holonyms(), part_holonyms(), та substance_holonyms().

Використовуючи компаративний словник знайти для німецької, італійської та англійської мов близькі слова. Чи можуть отримані результати використовуватися для здійснення перекладу?

Побудувати умовний частотний розподіл для корпусу імен. Знайти які перші літери частіше використовуються в чоловічих та жіночих іменах.

Здійснити аналіз словника вимов. Знайти скільки різних слів він містить. Який відсоток слів з цього словника можуть мати різну вимову?

Який відсоток синсетів іменників не мають гіпонімів? До всіх синсетів можна доступитися за допомогою wn.all_synsets('n').

Визначити функцію supergloss(s) , яка буде приймати синсет s як аргумент і повертати стрічку в якій будуть поєднані всі описи всіх значень синсету s та описи всіх гіпернімів та гіпонімів s.

Модифікувати програму генерації випадкового тексту для виконання наступного: зберігати можливі наступні слова у списку та вибирати їх за допомогою random.choice() попередньо виконавши import random.

Модифікувати програму генерації випадкового тексту для виконання наступного: тренувати програму на текстах різних жанрів та різних корпусів. Генерацію тексту провести з 5-ма різними початковими словами. Результати проаналізувати та порівняти.

Модифікувати програму генерації випадкового тексту для виконання наступного: тренування програми на текстах двох різних жанрів та генерації тексту об’єднаного жанру.

Полісемія - це явище коли одне слово має декілька значень ( іменник dog має 7 значень, кількість яких визначити можна як len(wn.synsets('dog', 'n'))). Знайдіть середнє значення полісемії для іменників.

Полісемія - це явище коли одне слово має декілька значень ( іменник dog має 7 значень, кількість яких визначити можна як len(wn.synsets('dog', 'n'))). Знайдіть середнє значення полісемії для прикметників.

Полісемія - це явище коли одне слово має декілька значень ( іменник dog має 7 значень, кількість яких визначити можна як len(wn.synsets('dog', 'n'))). Знайдіть середнє значення полісемії для дієслів.

Полісемія - це явище коли одне слово має декілька значень ( іменник dog має 7 значень, кількість яких визначити можна як len(wn.synsets('dog', 'n'))). Знайдіть середнє значення полісемії для прислівників.

Використовуючи один з методів визначення подібності слів побудуйте відсортований по спаданню список значень подібності для наступних пар слів: car-automobile, gem-jewel, journey-voyage, boy-lad, coast-shore, asylum-madhouse, magician-wizard, midday-noon, furnace-stove, food-fruit, bird-cock.

Використовуючи один з методів визначення подібності слів побудуйте відсортований по спаданню список значень подібності для наступних пар слів: bird-crane, tool-implement, brother-monk, lad-brother, crane-implement, journey-car, monk-oracle, cemetery-woodland.

Використовуючи один з методів визначення подібності слів побудуйте відсортований по спаданню список значень подібності для наступних пар слів: monk-oracle, cemetery-woodland, food-rooster, coast-hill, forest-graveyard, shore-woodland, mo
еще рефераты
Еще работы по разное