неділю, 13 листопада 2011 р.

Відповідь на лист стосовно 19го завдання 9ї лабораторної"Згадайте про n-грами"

Лист
Доброго вечора)
Маю до Вас запитання стосовно 19го завдання 9ї лабораторної.
Напишіть програми для знаходження слів та словосполучень згідно відповідних їм тегів для відповіді на наступне питання:
які послідовності слів маркуються як IN + DET + NN.

Чи можна це записати як:
brown_tagged=nltk.corpus.brown.tagged_words()
def findwords(text):
        s=nltk.defaultdict(list)
        for i in text:
                s[i[0]]+=[i[1]]
                a=[]
        for i in s.items():
                if 'IN' in i[1]:
                        a+=[i[0]]
        return a [:50]
findwords(brown_tagged)
Чи ось так:
cfd=nltk.ConditionalFreqDist((tag,word) for (word,tag) in
brown_tagged)
cfd['IN'].keys()
Або так:
brown_tagged=nltk.corpus.brown.tagged_words()
cfd=nltk.ConditionalFreqDist(brown_tagged)
[w for w in cfd.conditions() if 'IN' in cfd[w]]
Порадьте щось будь ласка)) Буду вдячна!!!




Відповідь у темі....
help(nltk.trigrams)
help(nltk.ngrams)
Також сподіваюсь Ви читали 10 сторінку методичних вказівок
for (w1,t1), (w2,t2), (w3,t3) in nltk.trigrams(sentence):

Відповідь на лист "лр 9, завд 18"

Добрий день!
Питання таке: лр 9, завд 18. Потрібно знайти співвідношення між жін. і чол.
займенниками. Таке розв'язання зараховується?)
from nltk import FreqDist, ConditionalFreqDist
from nltk.corpus import brown
fd = FreqDist()
cfd = ConditionalFreqDist()
for sentence in brown.tagged_sents():
    for (token, tag) in sentence:
        fd.inc(tag)
        cfd[token].inc(tag)
male = ['he','his','him','himself'] # masculine pronouns
female = ['she','hers','her','herself'] # feminine pronouns
n_male, n_female = 0, 0
for m in male:
    n_male += cfd[m].N()
n_male
16207
for f in female:
    n_female += cfd[f].N()
n_female
4975
print float(n_male)/n_female
3.2576884422


Відповідь_______________

Зарахувати завдання звичайно можна, але Ваша програм це просто підрахунок 'he','his','him','himself' та 'she','hers','her','herself'.
Я дев'ята лабораторна робота присвячена вивченню морфологічно розмічених корпусів. Тому я сподівався що при рішенні цієї задачі буде використовуватись інформація про теги якими маркуються займенники nltk.help.brown_tagset('P.*').
Наприклад Ваша програма не буде враховувати займенники записані наприклад так як he's she'd а використовуючи теги ви це врахуєте:
PPS+HVZ: pronoun, personal, nominative, 3rd person singular + verb 'to have', present tense, 3rd person singular
    it's he's she's
PPS+HVD: pronoun, personal, nominative, 3rd person singular + verb 'to have', past tense
    she'd he'd it'd

Відповідь на лист про гематрію

Доброї ночі!

Я у Вас вже була питала на парі про задачу з гематрією, але щось все одно в
мене не виходить... Подивіться, будь ласка, де помилка?
import nltk
state=nltk.corpus.state_union.words()
letter_vals = {'a':1, 'b':2, 'c':3, 'd':4, 'e':5, 'f':80, 'g':3,
'h':8,'i':10, 'j':10, 'k':20, 'l':30, 'm':40, 'n':50, 'o':70, 'p':80,
'q':100, 'r':200, 's':300, 't':400, 'u':6, 'v':6, 'w':800, 'x':60, 'y':10,
'z':7}
def gematria(state):
    for i in range(len(state)):
        word=state
        gem=0
        for i in word.lower():
            gem+=letter_vals[i]
        word=gem
        return word
for w in state:
    k=0
    if ([letter_vals[w] for w in state if w.isalpha() and w.islower() and
len(w)==3 and gematria(w)==555]):
    k+=1
    print k


__________________________________-


Перше - у восьмій лаб. роботі Ви вивчаєте, як зневаджувати програми. Потрібно цими знаннями скористатися і тоді....
Друге - у сьомій лаб. роботі Ви знайомилися з елементами стилю програмування. Але у своїй програмі у Вас state то список слів з корпуса то аргумент функції. Те саме з word.... 
Третє - В останньому циклі Ви перебираєте слова корпуса і далі стрічка:
 if ([letter_vals[w] for w in state if w.isalpha() and w.islower() and
len(w)==3 and gematria(w)==555]):
у якій перевіряєте все на купу, і довжину слова, і навіщось, чи є у letter_vals запис з ключем w(слово з корпуса) і так далі...
Порада - наведіть порядок зі змінними і тоді Вам буде простіше написати те що потрібно і зрозумієте де помилка 
Підказка - помилки у letter_vals[w] for w in state

вівторок, 8 листопада 2011 р.

Задача №6 Лабораторна робота №8

Умова. Написати програму для створення двовимірного масиву word_vowels елементами якого є набори. Програма повинна обробити список слів і додати кожне зі слів до word_vowels[l][v] де l – довжина слова, v – кількість голосних у слові.

Отже, якщо у мене, наприклад, список слів Іван, Петро, Василь - то я повинен в комірку масиву з індексами 4,2 записати слово Іван, в комірку масиву з індексами 5,2 записати слово Петро, в комірку масиву з індексами 6,2 записати слово Василь.

import nltk
from nltk.corpus import brown
list_w=[w.lower() for w in brown.words()[:10]] # список слів
# побудова двовимірного масиву
# сторінка 12 лаб.робота №7
#>>> m, n = 3, 7
#>>> array = [[set() for i in range(n)] for j in range(m)]
#>>> array[2][5].add('Alice')
#>>> pprint.pprint(array)
#[[set([]), set([]), set([]), set([]), set([]), set([]), set([])],
#[set([]), set([]), set([]), set([]), set([]), set([]), set([])],
#[set([]), set([]), set([]), set([]), set([]), set(['Alice']), set([])]]
#m, n - розміри масиву #як їх отримати,
#максимальне значення, яке може мати m - це довжина найдовшого слова зі списку #максимальне значення, яке може мати n - це найбільша кількість голосних у слові зі списку len_m_of_array=max([len(w) for w in list_w])
len_n_of_array=max([len([char for char in w if char in 'aoieu']) for w in list_w])
array = [[set() for i in range(len_n_of_array+1)] for j in range(len_m_of_array+1)]
# заповнення масиву
for w in list_w:
    array[len(w)][len([char for char in w if char in 'aoieu'])].add(w)
# переглядаю масив
pprint.pprint(array)

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

середу, 28 вересня 2011 р.

Unicode в Python (лаб.робота №5)

Додаткову інформацію по роботі з Unicode в Python
можна знайти в:
http://boodebr.org/main/python/all-about-python-and-unicode
http://www.uchi-it.ru/9/11/6.html
http://www.py-my.ru/post/4bfb3c6a1d41c846bc00009b
або
http://www.python.su/forum/viewtopic.php?id=7742
http://www.python.su/forum/viewtopic.php?id=11747

пʼятницю, 6 травня 2011 р.

Перегляд синсетів у які входить задане слово (Задача №7 11 розділ)

Write a function which displays the complete entry for a lexeme. When the
lexeme is incorrectly spelled, it should display the entry for the most similarly
spelled lexeme.

Вважаю, що entry для lexeme це будуть всі синсети з WordNet у які вона входить.
Повністю повторення прикладу зі сторінки 424 але все зроблено, як одна функція, хоча так робити недоцільно. Кожен раз коли виконується ця функція відбувається індексування словника signatures = nltk.Index((signature(w), w) for w in nltk.corpus.words.words())

import nltk, re

def fuzzy_spell(word):
mappings = [('ph', 'f'), ('ght', 't'), ('^kn', 'n'), ('qu', 'kw'), ('[aeiou]+', 'a'), (r'(.)\1', r'\1')]
def signature(word):
for patt, repl in mappings:
word = re.sub(patt, repl, word)
pieces = re.findall('[^aeiou]+', word)
return ''.join(char for piece in pieces for char in piece)

signatures = nltk.Index((signature(w), w) for w in nltk.corpus.words.words())

def rank(word, wordlist):
ranked = sorted((nltk.edit_distance(word, w), w) for w in wordlist)
return [word for (_, word) in ranked]

# Якщо слово відсутнє у словнику то вважаємо що воно містить помилку
if word not in nltk.corpus.words.words():
sig = signature(word)
if sig in signatures:
for words in rank(word, signatures[sig]):
print words, nltk.corpus.wordnet.synsets(words)
else:
return []
else:
print nltk.corpus.wordnet.synsets(word)

print fuzzy_spell('closeі')

Зовсім просто (Задача№1 11 Розділ)

In Example 11.8 the new field appeared at the bottom of the entry. Modify this program so that it inserts the new subelement right after the lx field. (Hint: create the new cv field using Element('cv'), assign a text value to it, then use the insert() method of the parent element.)

Доволі все просто.
import nltk,re,pprint
from nltk.corpus import toolbox
from nltk.etree.ElementTree import Element

lexicon = toolbox.xml('rotokas.dic')

def cv(s):
s = s.lower()
s = re.sub(r'[^a-z]', r'_', s)
s = re.sub(r'[aeiou]', r'V', s)
s = re.sub(r'[^V_]', r'C', s)
return (s)

def add_cv_field(entry):

for field in entry:
if field.tag == 'lx':
cv_field = Element('cv')
cv_field.text = cv(field.text)
entry.insert(1,cv_field)

print nltk.toolbox.to_sfm_string(lexicon[53])
add_cv_field(lexicon[53])
print nltk.toolbox.to_sfm_string(lexicon[53])

пʼятницю, 11 березня 2011 р.

Які будуть ще ідеї (Задача №8 Розділ №6)

Умова задачі: Word features can be very useful for performing document classification, since the words that appear in a document give a strong indication about what its semantic content is. However, many words occur very infrequently, and some of the most informative words in a document may never have occurred in our training data. One solution is to make use of a lexicon, which describes how different words relate to one another. Using WordNet lexicon, augment the movie review document classifier presented in this chapter to use features that generalize the words that appear in a document, making it more likely that they will match words found in the training data.

#Спробую врахувати вплив гіпернімів.
#Варіант 1.
#Згідно приладу з підручника:
import nltk
import random
from nltk.corpus import movie_reviews
from nltk.corpus import wordnet as wn
documents = [(list(movie_reviews.words(fileid)), category)
for category in movie_reviews.categories()
for fileid in movie_reviews.fileids(category)]
random.shuffle(documents)
all_words = nltk.FreqDist(w.lower() for w in movie_reviews.words())
word_features = all_words.keys()[:2000]
def document_features(document):
document_words = set(document)
features = {}
for word in word_features:
features['contains(%s)' % word] = (word in document_words)
return features
featuresets = [(document_features(d), c) for (d,c) in documents]
train_set, test_set = featuresets[1800:], featuresets[:200]
classifier = nltk.NaiveBayesClassifier.train(train_set)
print nltk.classify.accuracy(classifier, test_set)
#Отримую базову точність
#Якщо слово не попало в список з 2000 найчастотніших але його гіперніми зустрічаються серед слів корпуса то:
#Збільшую частоту для цих гіпернімів і знову беру 2000 найчастотніших
for word in all_words.keys():
if all_words[word]<70:
for synset in wn.synsets(word):
for hypernyms in synset.hypernyms():
for l_names in hypernyms.lemma_names:
all_words.inc(l_names)
word_features1 = all_words.keys()[:2000]
# Яких змін зазнав список найчастотніших слів
print len([word for word in word_features1 if word not in word_features])
word_features = all_words.keys()[:2000]
featuresets = [(document_features(d), c) for (d,c) in documents]
train_set, test_set = featuresets[1800:], featuresets[:200]
classifier = nltk.NaiveBayesClassifier.train(train_set)
print nltk.classify.accuracy(classifier, test_set)

Результати погані точність не збільшилась, список змінився на 270 слів.
0.725
270
0.71
>>>
0.715
270
0.72
>>>
0.765
270
0.75
>>>
0.805
270
0.805
>>>
0.69
270
0.705
>>>
#Варіант 2.
#Згідно приладу з підручника:
import nltk
import random
from nltk.corpus import movie_reviews
from nltk.corpus import wordnet as wn
documents = [(list(movie_reviews.words(fileid)), category)
for category in movie_reviews.categories()
for fileid in movie_reviews.fileids(category)[:100]]
random.shuffle(documents)
all_words = nltk.FreqDist(w.lower() for w in movie_reviews.words())
print len(all_words)
word_features = all_words.keys()[:200]
def document_features(document):
document_words = set(document)
features = {}
for word in word_features:
features['contains(%s)' % word] = (word in document_words)
return features
featuresets = [(document_features(d), c) for (d,c) in documents]
train_set, test_set = featuresets[80:], featuresets[:20]
classifier = nltk.NaiveBayesClassifier.train(train_set)
print nltk.classify.accuracy(classifier, test_set)
#Отримую базову точність
#Якщо слово не попало в список найчастотніших але його гіперніми входять у цей список то:
#додати це слово до списку найчастотніших
for word in all_words.keys()[:300]:
if all_words[word]< all_words[all_words.keys()[200]]:
for synset in wn.synsets(word):
for hypernyms in synset.hypernyms():
for l_names in hypernyms.lemma_names:
if l_names in all_words.keys()[:200]:
if word not in word_features:
word_features.append(word)
#Скільки слів додалося до списку
print len(word_features)
featuresets = [(document_features(d), c) for (d,c) in documents]
train_set, test_set = featuresets[80:], featuresets[:20]
classifier = nltk.NaiveBayesClassifier.train(train_set)
print nltk.classify.accuracy(classifier, test_set)
Слів додалося 37 а точність так і не збільшилась.

>>>
0.55
237
0.65
>>>
0.55
237
0.5
>>>
0.65
237
0.55
>>>
39768
0.5
237
0.5
>>>
0.65
237
0.65
>>>

Потрібні ще ідеї по використанню WordNet для рішення цієї задачі

понеділок, 21 лютого 2011 р.

Чому точність зменшилась(Задача №30, Розділ№5 )

Умова задачі:
Preprocess the Brown News data by replacing low-frequency words with UNK,
but leaving the tags untouched. Now train and evaluate a bigram tagger on this
data. How much does this help? What is the contribution of the unigram tagger
and default tagger now?

За умовою задачі очікуємо підвищення точності аналізатора.
Пишемо програму:
>>> import nltk
>>> from nltk.corpus import brown
>>> brown_tagged_sents = brown.tagged_sents(categories='news')
>>> vocab = nltk.FreqDist(brown.words(categories='news'))
# Важливий момент. Заміна всіх слів з частотоу =< 2 на "UNK"
>>> mapping = nltk.defaultdict(lambda: 'UNK')
>>> for v,t in brown.tagged_words(categories='news'):
if vocab[v]>2:
mapping[v],t = v,t
# Частотніші слова у словнику відобразили самих на себе
# Всі інші міняємо і результат зберігаємо у списку new_tagged_sents
>>> new_tagged_sents=[]
>>> for i in brown.tagged_sents(categories='news'):
new_tagged_sents.append([(mapping[v],t) for (v,t) in i])

# Поглянули чи дійсно відбулася заміна
>>> brown.tagged_sents(categories='news')[10]
[('It', 'PPS'), ('urged', 'VBD'), ('that', 'CS'), ('the', 'AT'), ('city', 'NN'), ('``', '``'), ('take', 'VB'), ('steps', 'NNS'), ('to', 'TO'), ('remedy', 'VB'), ("''", "''"), ('this', 'DT'), ('problem', 'NN'), ('.', '.')]
>>> new_tagged_sents[10]
[('It', 'PPS'), ('urged', 'VBD'), ('that', 'CS'), ('the', 'AT'), ('city', 'NN'), ('``', '``'), ('take', 'VB'), ('steps', 'NNS'), ('to', 'TO'), ('UNK', 'VB'), ("''", "''"), ('this', 'DT'), ('problem', 'NN'), ('.', '.')]

# будуємо набори даних для тренування тестування
# будуємо і тренуємо аналізатори
# оцінюємо точність їх роботи
>>> size = int(len(brown_tagged_sents) * 0.9)
>>> train_sents1 = brown_tagged_sents[:size]
>>> test_sents1 = brown_tagged_sents[size:]
>>> train_sents2 = new_tagged_sents[:size]
>>> test_sents2 = new_tagged_sents[size:]
>>> t0 = nltk.DefaultTagger('NN')
>>> t1 = nltk.UnigramTagger(train_sents1, backoff=t0)
>>> t2 = nltk.BigramTagger(train_sents1, backoff=t1)
>>> print t2.evaluate(test_sents1)
0.844911791089
>>> t1 = nltk.UnigramTagger(train_sents2, backoff=t0)
>>> t2 = nltk.BigramTagger(train_sents2, backoff=t1)
>>> print t2.evaluate(test_sents2)
0.836938104256
>>> t2 = nltk.BigramTagger(train_sents2, backoff=t0)
>>> print t2.evaluate(test_sents2)
0.722416027111

Результат несподіваний. Точність зменшилась.
Хто знає чому?