вівторок, 6 квітня 2010 р.

Задача №7 розділ №6 "Learning to Classify Text"

Умова задачі:
The dialogue act classifier assigns labels to individual posts, without considering
the context in which the post is found. However, dialogue acts are highly dependent
on context, and some sequences of dialogue act are much more likely than
others. For example, a ynQuestion dialogue act is much more likely to be answered
by a yanswer than by a greeting. Make use of this fact to build a consecutive classifier
for labeling dialogue acts. Be sure to consider what features might be useful.
See the code for the consecutive classifier for part-of-speech tags in Example 6-5
to get some ideas.

Варіант рішення:
В умові задачі міститься підказка.
Потрібно поєднати приклад 6-5 та приклад зі сторінки 235.
Ось що в мене вийшло.
>>> import nltk
>>> posts = nltk.corpus.nps_chat.xml_posts()
>>> history=[] # змінна для збереження типу попереднього повідомлення (post’s dialogue act type)
# функція для вилучення властивостей(ознак) з повідомлення
>>> def dialogue_act_features(post,i,history):
features = {}
for word in nltk.word_tokenize(post):
features['contains(%s)' % word.lower()] = True
if i == 0:
features["prev-class"] = ""
else:
features["prev-class"] = history[i-1] # тип попереднього повідомлення
return features
>>> featuresets=[]
>>> for i, post in enumerate(posts): # обробляємо пронумерований список повідомлень
featuresets.append((dialogue_act_features(post.text, i, history), post.get('class')))
history.append(post.get('class')) # список типів всіх повідомлень
>>> size = int(len(featuresets) * 0.1)
>>> train_set, test_set = featuresets[size:], featuresets[:size]
>>> classifier = nltk.NaiveBayesClassifier.train(train_set)
>>> print nltk.classify.accuracy(classifier, test_set)
0.644886363636

# а чому точність нижча ніж у прикладі зі сторінки 235, де тип попереднього повідомлення не враховувався?

Задача №6 розділ №6 "Learning to Classify Text"

Умова задачі:
The synonyms strong and powerful pattern differently (try combining them with
chip and sales). What features are relevant in this distinction? Build a classifier that predicts when each word should be used.

Варіант рішення:
Основне питання задачі це знайти ознаки за якими можна було б описати випадки вживання цих двох прикметників. Що впливає на вибір того чи іншого прикметника? Потрібно почитати граматику англійської мови, можливо стилістику, порадитись з спеціалістами філологами. Але в мене часу мало, тому вибираю найпростішу ознаку. Аналізую контексти вживання цих прикметників, а саме наступне після прикметника слово та його морфологічні характеристики. Звідки взяти цю інформацію, яка буде служити даними для тренування класифікатора? Корпус Brown.
# з корпуса Brown вибираю всі біграми в яких перше слово "strong" або "powerful" і промарковане, як прикметник. Зберігаю всі наступні слова та тери якими вони промарковані у словнику.
>>> import nltk
>>> from nltk.corpus import brown
>>> featureset=[]
>>> context={}
>>> for tagged_sent in brown.tagged_sents():
for (w1,t1), (w2,t2) in nltk.bigrams(tagged_sent):
if t1.startswith('JJ') and w1 == 'strong':
context[w2]=t2
featureset.append((a,w1))
context={}
elif t1.startswith('JJ') and w1 == 'powerful':
context[w2]=t2
featureset.append((a,w1))
context={}
# дивимось що отримали
>>> featureset[5]
({'New': 'JJ-TL'}, 'powerful')
>>> len(featureset)
253
# в корпусі мало випадків вживання цих прикментників. Всього 253. Як їх збільшити? Це я і буду питати при здачі практичної роботи.
# далі шлях побудови класифікатора вже знайомий
>>> size = int(len(featureset) * 0.1)
>>> train_set, test_set = featureset[size:], featureset[:size]
>>> classifier = nltk.NaiveBayesClassifier.train(train_set)
>>> nltk.classify.accuracy(classifier, test_set)
0.59999999999999998
>>> classifier.classify({'fight':'NN'})
'strong'
>>> classifier.classify({'fight':'v'})
'strong'
>>> classifier.classify({'fight':'JJ'})
'strong'
>>> classifier.classify({'fight':'VB'})
'strong'
>>> classifier.classify({'chip':'NN'})
'strong'
# от і результат недостатності даних для тренування, і вибору ознаки.

суботу, 3 квітня 2010 р.

Задача №3 розділ №6 "Learning to Classify Text"

Умова задачі:
The Senseval 2 Corpus contains data intended to train word-sense disambiguation
classifiers. It contains data for four words: hard, interest, line, and serve.
Choose one of these four words, and load the corresponding data:
>>> from nltk.corpus import senseval
>>> instances = senseval.instances('hard.pos')
>>> size = int(len(instances) * 0.1)
>>> train_set, test_set = instances[size:], instances[:size]
Using this dataset, build a classifier that predicts the correct sense tag for a given
instance. See the corpus HOWTO at http://www.nltk.org/howto for information
on using the instance objects returned by the Senseval 2 Corpus.

Шлях рішення:
Спочатку здається все просто. instances - це ознаки (features) на основі яких ми можемо тренувати будь-який з класифікаторів. Пробуємо:
>>> import nltk
>>> from nltk.corpus import senseval
>>> instances = senseval.instances('hard.pos')
>>> size = int(len(instances) * 0.1)
>>> train_set, test_set = instances[size:], instances[:size]
>>> classifier = nltk.NaiveBayesClassifier.train(train_set)

Traceback (most recent call last):
File "", line 1, in
classifier = nltk.NaiveBayesClassifier.train(train_set)
File "C:\Python26\lib\site-packages\nltk\classify\naivebayes.py", line 192, in train
for featureset, label in labeled_featuresets:
TypeError: 'SensevalInstance' object is not iterable

!!! Помилка. Використати instances як ознаки (features) не вдалося.
Потрібно розібратися у якому вигляді класифікатор (в даному випадку NaiveBayesClassifier) потребує дані для тренування (train_set)
Беремо будь-який з прикладів з підручника і аналізуємо(приклад сторінка 225):
>>> from nltk.corpus import names
>>> import random
>>> names = ([(name, 'male') for name in names.words('male.txt')] +
[(name, 'female') for name in names.words('female.txt')])
>>> random.shuffle(names)
>>> def gender_features2(name):
features = {}
features["firstletter"] = name[0].lower()
features["lastletter"] = name[-1].lower()
for letter in 'abcdefghijklmnopqrstuvwxyz':
features["count(%s)" % letter] = name.lower().count(letter)
features["has(%s)" % letter] = (letter in name.lower())
return features
>>> featuresets = [(gender_features2(n), g) for (n,g) in names]
>>> train_set, test_set = featuresets[500:], featuresets[:500]
# перевіримо що за змінна train_set
>>> type(train_set)
# тип цієї змінної - список
# скільки елементів у цьому списку
>>> len(train_set)
7444
# багато, поглянемо на один з них
>>> train_set[5]
({'count(u)': 0, 'has(d)': False, 'count(b)': 0, 'count(w)': 0, 'has(b)': False, 'count(l)': 1, 'count(q)': 0, 'count(n)': 0, 'has(j)': False, 'count(s)': 0, 'count(h)': 0, 'has(h)': False, 'has(y)': False, 'count(j)': 0, 'has(f)': False, 'has(o)': False, 'count(x)': 0, 'has(m)': True, 'count(z)': 0, 'has(k)': False, 'has(u)': False, 'count(d)': 0, 'has(s)': False, 'count(f)': 0, 'lastletter': 'a', 'has(q)': False, 'has(w)': False, 'has(e)': False, 'has(z)': False, 'count(t)': 0, 'count(c)': 0, 'has(c)': False, 'has(x)': False, 'count(v)': 0, 'count(m)': 1, 'has(a)': True, 'has(v)': False, 'count(p)': 0, 'count(o)': 0, 'has(i)': False, 'count(i)': 0, 'has(r)': False, 'has(g)': False, 'count(k)': 0, 'firstletter': 'm', 'count(y)': 0, 'has(n)': False, 'has(l)': True, 'count(e)': 0, 'has(t)': False, 'count(g)': 0, 'count(r)': 0, 'count(a)': 2, 'has(p)': False}, 'female')
# структура елементу складна. кортеж, словник, стрічки....
>>> type(train_set[5])
# тип елемента списку train_set - кортеж
>>> len(train_set[5])
2 # цей кортеж складається з двох елементів
>>> type(train_set[5][0])
# тип першого елемента - словник
>>> type(train_set[5][1])
# тип другого елемента - стрічка
Все зрозуміло, за допомогою словника описуються ознаки а за допомогою стрічки описується мітка, яка відповідає цим ознакам.
Тепер потрібно розібратися що таке - instances. Найпростіше почитати HOWTO at http://www.nltk.org/howto як рекомендують автори. Точніше читаємо тут: http://nltk.googlecode.com/svn/trunk/doc/howto/corpus.html#other-corpora
instances - також складний об'єкт. Він складається з окремих SensevalInstance - в яких описано слово (word), позиція цього слова у реченні (position), всі слова речення та їх морфологічні характеристики (context) та значення слова (senses).
Для доступу до елементів SensevalInstance є окремі методи:
.position, .word, .context, .senses
Отже потрібно доступитися до SensevalInstance і перетворити його елементи до вигляду:
Окремий SensevalInstance це буде кортеж, position, word, context, - словник, senses - стрічка.
Пишемо текст програми:
# імпортуємо необхідні для роботи програми модулі
import nltk
import types
from nltk.corpus import senseval
# доступаємся до даних з корпусв
instances = senseval.instances('serve.pos')
features=[]
# перетворюємо instances до потрібного вигляду (списку кортежів кожен з яких складається зі словника та стрічки). Змінна features і буде цим списком.
for inst in instances:
zx=[]
for i in inst.context:
if type(i) == types.TupleType:
zx.append(i)
elif type(i) == types.StringType:
zx.append(("None",i))
a={"word": inst.word,"position": inst.position,}
b=dict(zx)
a.update(b)
features.append((a,' '.join(inst.senses)))
# далі вже все просто
# встановлюємо розмір даних для тестуваня (10%)
size = int(len(features) * 0.1)
# ділимо всі дані на дві частини - для тренування і для тестування
train_set, test_set = features[size:], features[:size]
# тренуємо класифікатор
classifier1 = nltk.NaiveBayesClassifier.train(train_set)
# оцінюємо точність його роботи
print nltk.classify.accuracy(classifier1, test_set)
0.66590389016
# точність - так собі, не дуже
але задачу здається виконали....

пʼятницю, 2 квітня 2010 р.

Задача №1 розділ №6 "Learning to Classify Text"

Умова задачі: Read up on one of the language technologies mentioned in this section, such as
word sense disambiguation, semantic role labeling, question answering, machine
translation, or named entity recognition. Find out what type and quantity of annotated
data is required for developing such systems. Why do you think a large
amount of data is required?

Що потрібно зробити:
- прочитати про word sense disambiguation, semantic role labeling, question answering, machine translation, named entity recognition в підручнику починаючи зі сторінки 28;
- прочитати про word sense disambiguation, semantic role labeling, question answering, machine translation, named entity recognition в інших книжках (Jurafsky), інтернет ресурсах (Вікіпедія) тощо...
- обдумати, які дані (корпуси) необхідні для побудови (тренування) класифікатора для вирішення тої чи ншої задачі;
- аргументувати, який об'єм даних потрібний для успішного вирішення задачі.

Складнощі з вивченням розділу "Learning to Classify Text"

При вивчення розділу "Learning to Classify Text" студенти зіткнулися із значними труднощами. В наступних дописах будуть розглядатися задачі з цього розділу.

понеділок, 11 січня 2010 р.

Контрольна робота: умови, вимоги, критерії оцінювання

Практична частина контрольної роботи буде проводитись 20-го та 21-го січня згідно розкладу лабораторних робіт.
Тривалість – 45 хвилин.
Максимальна кількість балів -20.
Практична частина контрольної роботи передбачає розробку програми для вирішення певної задачі, умова якої міститься у завданні.
Основні вимоги до розробки програми:
Програма повинна бути оформлена у вигляді окремого модуля (файл *.py). Назва файлу відповідає прізвищу студента.
Програма повинна передбачати збереження результатів роботи у файл (*.dat). Назва файлу відповідає прізвищу студента.
Для розробки програми студент повинен володіти засобами мови програмування
Python та бібліотеки програм NLTK, а саме:
функціями та методами роботи з типами даних : стрічка, список, словник
;
функціями та методами доступу (відкриття, читання) до файлів
;
функціями та методами збереження даних (відкриття, запис) у файл
;
функціями та методами доступу до корпусів текстів
;
функціями та методами для роботи з
WordNet;
функціями та методами для роботи з морфологічно розміченими корпусами текстів.

Критерії оцінки
Виконані всі вимоги: розроблено модуль, який вирішує поставлену задачу і зберігає результати у файл - 20 балів.
Вимоги виконані частково:
відсутній модуль - мінус 3 бали;
в модулі відсутні коментарі - мінус 2 бали;
результати не зберігаються у файл - мінус 3 бали;
задача вирішена частково або неправильно - мінус 10 балів