Лабораторна №7 Основи програмування icon

Лабораторна №7 Основи програмування




Скачати 352.92 Kb.
НазваЛабораторна №7 Основи програмування
Дата конвертації07.01.2013
Розмір352.92 Kb.
ТипДокументи

Лабораторні роботи №№ 7-8

Лабораторна №7

1. Основи програмування

1.1 Присвоювання


Присвоювання – найпростіше поняття програмування, але навіть і йому властиві певні тонкощі. Розглянемо приклад:

 

>>> foo = 'Monty'

>>> bar = foo #1

>>> foo = 'Python' #2

>>> bar

'Monty'




Коли записується bar = foo (рядок програми #1), то значення змінної foo (стрічка 'Monty') присвоюється змінній bar. Таким чином, bar є копією foo. Якщо змінити foo на нову стрічку 'Python' (рядок програми #2), то змінної bar ці зміни не торкнулася.

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

 

>>> foo = ['Monty', 'Python']

>>> bar = foo #1

>>> foo[1] = 'Bodkin' #2

>>> bar

['Monty', 'Bodkin']




Розглянемо ще декілька прикладів. Створимо змінну empty і присвоємо їй значення пустого списку. В наступному рядку використаємо цю змінну декілька раз.

 

>>> empty = []

>>> nested = [empty, empty, empty]

>>> nested

[[], [], []]

>>> nested[1].append('Python')

>>> nested

[['Python'], ['Python'], ['Python']]




Бачимо, що зміна одного вкладеного списку привела до зміни і всіх інших. Це відбулося тому, що ці всі три елементи списку насправді є посиланнями на одне і те саме місце (на той самий список) .


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

 

>>> nested = [[]] * 3

>>> nested[1].append('Python')

>>> nested[1] = ['Monty']

>>> nested

[['Python'], ['Monty'], ['Python']]




Початковий список містить три посилання на єдиний пустий об’єкт типу список. В результаті модифікації цього об’єкту додаванням до нього 'Python' список містить ті самі три посилання але вже на єдиний об’єкт ['Python'] типу список. В подальшому відбувається перезаписування одного з цих посилань на посилання на новий об’єкт ['Monty']. У списку відбулася модифікація одного з трьох посилань на об’єкт ['Python'].

Потрібно чітко розрізняти модифікацію об’єкту через посилання на об’єкт і перезаписування посилання на об’єкт.

1.2 Порівняння


Python підтримує два способи порівняння. Оператор is перевіряє об’єкти на ідентичність. Створивши список з декількох копій одного і того самого об’єкту не складно переконатися, що елементи цього списку не тільки ідентичні, згідно ==, але і є одним і тим самим об’єктом:

 

>>> size = 5

>>> python = ['Python']

>>> snake_nest = [python] * size

>>> snake_nest[0] == snake_nest[1] == snake_nest[2] == snake_nest[3] == snake_nest[4]

True

>>> snake_nest[0] is snake_nest[1] is snake_nest[2] is snake_nest[3] is snake_nest[4]

True



^

1.3 Умовні твердження(висловлювання)


В частині умов if твердження, не пусті стрічки вважаються «true», а пусті стрічки чи списки вважаються «false» і не обробляються.

 

>>> mixed = ['cat', '', ['dog'], []]

>>> for element in mixed:

... if element:

... print element

...

cat

['dog']




Тому, не потрібно використовувати додаткову перевірку if len(element) > 0: в умові.

Для пояснення відмінностей між використанням if...elif та використання декількох if тверджень розглянемо наступний приклад:

 

>>> animals = ['cat', 'dog']

>>> if 'cat' in animals:

... print 1

... elif 'dog' in animals:

... print 2

...

1




Якщо if вираз твердження задовольняється то, Python ніколи не буде робити спроби перевірити чи справджується elif вираз. На екран «2» ніколи не буде виведено. Навпаки, якщо замінити elif на if, на екран буде виведено і «1» і «2». elif вираз потенційно є більш інформативний ніж простий if вираз; коли він справджується то це означає не тільки те що умова задовольняється але і те, що умова if виразу не справджується.

Вбудовані функції all() та any() можуть бути застосовані до списку або іншої послідовності для перевірки, чи всі, або будь-який з елементів задовольняють умову:

 

>>> sent = ['No', 'good', 'fish', 'goes', 'anywhere', 'without', 'a', 'porpoise', '.']

>>> all(len(w) > 4 for w in sent)

^ False

>>> any(len(w) > 4 for w in sent)

True






2. Послідовності


Серед послідовностей, в попередніх прикладах, використовувалися наступні: стрічки, списки та кортежі. Змінна, тип якої – кортеж, створюється за допомогою ком (#1) і переважно обмежується дужками. В попередніх лабораторних роботах кортежі використовувалися для представлення пар значень (елементів послідовності з двох членів). Зазвичай, кортежі можуть містити будь-яку кількість елементів та членів. Аналогічно до списків та стрічок, елементи кортежів можуть бути проіндексовані (#2), до них можна доступитися за допомогою зрізів (#3) та визначити кількість елементів (#4).

 

>>> t = ['walk'], 'fem', 3

>>> t

(['walk'], 'fem', 3)

>>> t[0]

['walk']

>>> t[1]

'fem'

>>> t[1:]

('fem', 3)




Кортежі створюються за допомогою ком (оператор - кома). Для створення кортежу, який містить єдиний елемент 'snark' , кома ставиться безпосередньо після цього елементу 'snark',. Пустий кортеж створюється за допомогою пустих дужок (t=()).

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

 

>>> raw = 'I turned off the spectroroute'

>>> text = ['I', 'turned', 'off', 'the', 'spectroroute']

>>> pair = (6, 'turned')

>>> raw[2], text[3], pair[1]

('t', 'the', 'turned')

>>> raw[-3:], text[-3:], pair[-3:]

('ute', ['off', 'the', 'spectroroute'], (6, 'turned'))

>>> len(raw), len(text), len(pair)

(29, 5, 2)






^

2.1 Операції над послідовностями різних типів


Елементи послідовності s можна обробляти почергово (здійснювати над ними ітерації, ітерувати) різними способами, основні з яких, наведено у таблиці 1.


Способи ітерування елементів послідовностей Таблиця 1:

^ Вираз Python

Пояснення

for item in s

Проітерувати елементи s

for item in sorted(s)

Проітерувати впорядковані елементи s

for item in set(s)

Проітерувати унікальні елементи s

for item in reversed(s)

Проітерувати зворотньо впорядковані елементи s

for item in set(s).difference(t)

Проітерувати елементи s, які не входять в t

for item in random.shuffle(s)

Проітерувати випадково впорядковані елементи s

Функції з Таблиці 1. можна поєднувати у різний спосіб. Наприклад, для одержання унікальних елементів s впорядкованих у зворотному порядку необхідно використовувати наступний вираз reversed(sorted(set(s))).

Python, за допомогою таких функцій, як sorted() and reversed(), дозволяє змінювати порядок елементів у послідовностях. Також існують функції, які модифікують структуру послідовностей, що знаходить широке використання при обробці мови. Функція, zip() приймає елементи двох або більше послідовностей і "zip" переміщує їх, попарно, один з одним, в один список пар. Маючи послідовність s, і скориставшись вбудованою функцією мови програмування Python enumerate(s) отримуємо пари, які містять індекс та елемент послідовності, який відповідає цьому індексу.

 

>>> words = ['I', 'turned', 'off', 'the', 'spectroroute']

>>> tags = ['noun', 'verb', 'prep', 'det', 'noun']

>>> zip(words, tags)

[('I', 'noun'), ('turned', 'verb'), ('off', 'prep'),

('the', 'det'), ('spectroroute', 'noun')]

>>> list(enumerate(words))

[(0, 'I'), (1, 'turned'), (2, 'off'), (3, 'the'), (4, 'spectroroute')]




Для вирішення деяких задач NLP часто необхідно ділити послідовності на декілька окремих частин. Наприклад, якщо необхідно тренувати ("train") систему на 90% даних а потім її тестувати на 10% даних , що залишились. Для цього, визначаємо місце поділу даних (#1) і в цьому місці ділимо дані (#2). .

 

>>> text = nltk.corpus.nps_chat.words()

>>> cut = int(0.9 * len(text)) #1

>>> training_data, test_data = text[:cut], text[cut:] #2

>>> text == training_data + test_data #3

True

>>> len(training_data) / len(test_data) #4

9




Можна пересвідчитись, що дані не дублюються і не втрачаються (#3), а також що дані поділені на дві частини в заданих пропорціях (#4).
^

3.2 Процедурний чи декларативний стиль


Одне і те саме завдання може бути виконане різними шляхами з використанням різних змінних та з різною ефективністю. Інший критерій, який впливає та розробку програм, це стиль програмування. Розглянемо наступний приклад в якому визначається середня довжина слів в Brown корпусі:

 

>>> tokens = nltk.corpus.brown.words(categories='news')

>>> count = 0

>>> total = 0

>>> for token in tokens:

... count += 1

... total += len(token)

>>> print total / count

4.2765382469




В цій програмі використовується змінна count для підрахунку кількості слів та змінна total для збереження загальної довжини всіх слів. Текст цієї програми написаний на стилі низького рівня, який нагадує машинні операції в процесорі комп’ютера. Дві змінні працюють подібно до регістрів процесора , накопичуючи значення на проміжних кроках, значення які втрачають зміст після завершення підрахунків. Ця програма написана в процедурному стилі, машинні операції виконуються крок за кроком. Розглянемо наступну програму, яка визначає те саме значення:

 

>>> total = sum(len(t) for t in tokens)

>>> print total / len(tokens)

4.2765382469




В першій стрічці використовується генератор виразів для сумування довжини слів а в другій визначається середнє значення. Кожен рядок програми виконує окрему задачу, яку можна зрозуміти на вищому рівні: "total – це сума довжин tokens". Деталі реалізації цієї дії залишаються прихованим і їх виконує інтерпретатор Python. Друга програма використовує вбудовану функцію (len()), програмування відбувається на більш абстрактному рівні і текст програми є більш декларативним. Розглянемо ще один наочний приклад:

 

>>> word_list = []

>>> len_word_list = len(word_list)

>>> i = 0

>>> while i < len(tokens):

... j = 0

... while j < len_word_list and word_list[j] < tokens[i]:

... j += 1

... if j == 0 or tokens[i] != word_list[j]:

... word_list.insert(j, tokens[i])

... len_word_list += 1

... i += 1




Еквівалентний декларативний варіант використовує відомі вбудовані функції і задача, яку виконує програма є відразу зрозуміла:

 

>>> word_list = sorted(set(tokens))




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

 

>>> text = nltk.corpus.gutenberg.words('milton-paradise.txt')

>>> longest = ''

>>> for word in text:

... if len(word) > len(longest):

... longest = word

>>> longest

'unextinguishable'




Більш вдале рішення задачі з попереднього прикладу забезпечує використання двох list comprehensions:

 

>>> maxlen = max(len(word) for word in text)

>>> [word for word in text if len(word) == maxlen]

['unextinguishable', 'transubstantiate', 'inextinguishable', 'incomprehensible']




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


^

4. Функції, як основа структурного програмування




Функції забезпечують ефективний спосіб збереження та повторного використання частин програм. Наприклад, припустимо, що існує необхідність часто читати тексти з HTML файлу. Це потребує виконання певної послідовності кроків: відкриття файлу, читання, нормалізація, видалення HTML розмітки. Можна зібрати ці кроки у функцію get_text().

 

import re

def get_text(file):

"""Read text from a file, normalizing whitespace and stripping HTML markup."""

text = open(file).read()

text = re.sub('\s+', ' ', text)

text = re.sub(r'<.*?>', ' ', text)

return text







Тепер, в будь-який момент, можна отримати текст з HTML файлу викликавши функцію get_text() вказавши назву файлу, як її аргумент. Функція повертає стрічку, значення, якої можна присвоїти будь-якій змінній, наприклад: contents = get_text("test.html").

При створенні функції важливе значення має вибір назви функції, що дозволяє зробити програму більш читабельною. У випадку попереднього прикладу, кожен раз коли програма повинна читати текст, немає потреби засмічувати текст основної програми чотирма рядками , потрібно тільки викликати функцію get_text (). Назва цієї функції має певну «семантичну інтерпретацію» і допомагає відразу зрозуміти що програма робить.

Перший рядок функції містить опис функції і його називають docstring. Така стрічка не тільки допомагає при читанні програми, вона також доступна програмісту при завантаженні тексту програми з файлу:

>>> help(get_text)

Help on function get_text:


get_text(file)

Read text from a file, normalizing whitespace

and stripping HTML markup.

Функції дозволяють не тільки повторно використовувати текст частини програми та підвищують читабельність програми але також підвищують достовірність тексту програми. Коли використовується текст програми, який вже попередньо розроблений і перевірений, то можна сподіватися що він працює правильно. Зменшується імовірність помилки та пропуску важливого кроку роботи програми.

Функція це фрагмент тексту програми, який має чітку, зрозумілу назву та виконує конкретне завдання.
^

4.1 Вхідні та вихідні дані функції


Інформація передається до функції за допомогою параметрів функції. Параметри функції, це список змінних та констант, які записані в круглих дужках після назви функції при визначенні (оголошенні) функції. Розглянемо приклад:

 

>>> def repeat(msg, num): #1

... return ' '.join([msg] * num)

>>> monty = 'Monty Python'

>>> repeat(monty, 3) #2

'Monty Python Monty Python Monty Python'




В прикладі визначається функція з двома параметрами, msg та num #1. Коли функція викликається то до неї передаються два аргументи , monty та 3 #2. Ці аргументи записані в місцях , що відповідають параметрам функції і передаються до функції, як msg та num.

Параметри функції не є обов’язковими, наприклад:

 

>>> def monty():

... return "Monty Python"

>>> monty()

'Monty Python'




Функція, зазвичай, передає результати своєї роботи програмі з якої вона викликалася за допомогою твердження return. Наступний приклад демонструє, як виклик функції може бути замінений на результат роботи функції:

 

>>> repeat(monty(), 3)

'Monty Python Monty Python Monty Python'

>>> repeat('Monty Python', 3)

'Monty Python Monty Python Monty Python'




Функція в Python не обов’язково повинна мати return твердження. Функції без return твердження виконують побічну роботу, таку як роздрук результатів, модифікація файлу чи оновлення значення параметру і часто їх називають – процедурами.

Розглянемо наступні три функції сортування. Застосовувати третю функцію небезпечно, тому що при використанні цієї функції змінюються її вхідні дані. Функції повинні модифікувати вміст параметру (my_sort1()), або повертати значення (my_sort2()), але не робити це одночасно (my_sort3()).

 

>>> def my_sort1(mylist): # good: modifies its argument, no return value

... mylist.sort()

>>> def my_sort2(mylist): # good: doesn't touch its argument, returns value

... return sorted(mylist)

>>> def my_sort3(mylist): # bad: modifies its argument and also returns it

... mylist.sort()

... return mylist






^

Лабораторна №8

1.   Складні випадки використання функцій

1.1 Функція, як аргумент


Аргументи функцій, які розглядалися в попередніх лабораторних роботах, були простими об’єктами, такими як стрічка, або структурованими, такими як список. В Python аргументом функції також може бути і інша функція.В наступному прикладі показано, яким чином вбудована функція len() або розроблена функція last_letter() передаються, як аргументи іншій функції:

 

>>> sent = ['Take', 'care', 'of', 'the', 'sense', ',', 'and', 'the',

... 'sounds', 'will', 'take', 'care', 'of', 'themselves', '.']

>>> def extract_property(prop):

... return [prop(word) for word in sent]

...

>>> extract_property(len)

[4, 4, 2, 3, 5, 1, 3, 3, 6, 4, 4, 4, 2, 10, 1]

>>> def last_letter(word):

... return word[-1]

>>> extract_property(last_letter)

['e', 'e', 'f', 'e', 'e', ',', 'd', 'e', 's', 'l', 'e', 'e', 'f', 's', '.']




Об’єкти len та last_letter передаються у функцію як списки та словники (тип даних словник буде розглянуто пізніше). Зауважимо, що дужки після імені функції використовуються тільки при її виклику, а якщо функція трактується, як об’єкт (аргумент іншої функції) то дужки опускаються.

Python підтримує ще один спосіб визначення функцій як аргументів іншої функції, це так званий лямбда-вираз (анонімна функція). Спробуємо виконати дії функції last_letter() без її створення і відповідно не використовуючи її імя. За допомогою лямбда-виразу отримаємо наступний результат:

 

>>> extract_property(lambda w: w[-1])

['e', 'e', 'f', 'e', 'e', ',', 'd', 'e', 's', 'l', 'e', 'e', 'f', 's', '.']




Наступний приклад ілюструє передавання функції до функції sorted(). У випадку виклику функції sorted() з одним аргументом #1 (сортування списку) ця функція використовує для порівняння вбудовану функцію cmp() (про що свідчить #2). Звичайно, можна, як аргумент, використати і власну функцію, наприклад функцію сортування в порядку спадання довжин елементів.

 

>>> sorted(sent) #1

[',', '.', 'Take', 'and', 'care', 'care', 'of', 'of', 'sense', 'sounds',

'take', 'the', 'the', 'themselves', 'will']

>>> sorted(sent, cmp) #2

[',', '.', 'Take', 'and', 'care', 'care', 'of', 'of', 'sense', 'sounds',

'take', 'the', 'the', 'themselves', 'will']

>>> sorted(sent, lambda x, y: cmp(len(y), len(x))) #3

['themselves', 'sounds', 'sense', 'Take', 'care', 'will', 'take', 'care',

'the', 'and', 'the', 'of', 'of', ',', '.']






^

1.3 Функції вищого рівня


Python підтримує деякі функції вищого порядку, які є стандартними для мов функціонального програмування, таких як Haskell. Розглянемо ці функції разом з еквівалентними виразами , які використовують list comprehensions.

Визначимо функцію is_content_word(), яка перевіряє чи належить слово до відкритого класу слів. Ця функція використовується, як перший параметр функції вищого порядку filter(). Функція filter() застосовує функцію is_content_word() до кожного елементу послідовності, яка є її другим параметром і зберігає тільки ті елементи для яких функція is_content_word() повертає значення True.

 

>>> def is_content_word(word):

... return word.lower() not in ['a', 'of', 'the', 'and', 'will', ',', '.']

>>> sent = ['Take', 'care', 'of', 'the', 'sense', ',', 'and', 'the',

... 'sounds', 'will', 'take', 'care', 'of', 'themselves', '.']

>>> filter(is_content_word, sent)

['Take', 'care', 'sense', 'sounds', 'take', 'care', 'themselves']

>>> [w for w in sent if is_content_word(w)]

['Take', 'care', 'sense', 'sounds', 'take', 'care', 'themselves']




Інша функція вищого порядку map(), також застосовує функцію до кожного з елементів послідовності. Наступний приклад ілюструє застосування цієї функції для одержання аналогічних з функцією extract_property()(пункт 1.1) результатів. В прикладі показано простий спосіб знаходження середньої довжини речень в корпусі Brown Corpus, та еквівалентний варіант цих обчислень за допомогою list comprehension:

 

>>> lengths = map(len, nltk.corpus.brown.sents(categories='news'))

>>> sum(lengths) / len(lengths)

21.7508111616

>>> lengths = [len(w) for w in nltk.corpus.brown.sents(categories='news'))]

>>> sum(lengths) / len(lengths)

21.7508111616




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

 

>>> map(lambda w: len(filter(lambda c: c.lower() in "aeiou", w)), sent)

[2, 2, 1, 1, 2, 0, 1, 1, 2, 1, 2, 2, 1, 3, 0]

>>> [len([c for c in w if c.lower() in "aeiou"]) for w in sent]

[2, 2, 1, 1, 2, 0, 1, 1, 2, 1, 2, 2, 1, 3, 0]




Рішення на основі list comprehensions є зазвичай більш зручні для читання і розуміння ніж рішення на основі функцій вищого порядку.


^

2.   Розробка програми


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

2.1 Структура модуля в Python


Мета розробки модулів програми - виділити логічно пов’язані визначення і функції для спрощення їх повторного використання та розуміння. Модуль в Python не що інше, як окремий *.py файл. Наприклад, для роботи з форматом певного корпусу, функції читання та запису цього формату повинні бути зібрані разом. Константи, які використовуються (розділювачі полів, чи розширення імен файлів EXTN = ".inf") повинні бути спільні. Якщо формат буде змінено, то ці зміни потрібно буде внести тільки в один файл. Аналогічно, модуль може містити текст програми для створення і маніпулювання певними структурами даних, наприклад синтаксичними деревами, або текст програми для виконання певної задачі, наприклад друк статистичних даних корпусу.
^

2.2 Багатомодульні програми


Деякі програми розробляються для вирішення багатьох різнотипних задач. Наприклад, програма повинна завантажити дані, здійснити їх певну обробку чи аналіз а результати візуалізувати. Якщо вже є готові стабільні модулі для завантаження даних та візуалізаці, то розробка такої програми полягає тільки в створенні тієї її частини, яка здійснює обробку чи аналіз даних та виклику потрібних функцій з існуючих модулів. Рис.1. ілюструє запропонований підхід.



Рис 1. Структура багатомодульної програми: Головна програма my_program.py імпортує функції з двох інших модулів; рішення задачі аналізу здійснюється в головній програмі а загальні задачі завантаження даних та візуалізація вирішуються окремо, що дозволяє їх повторно використовувати та при потребі змінювати.

Розподіл виконання задач між декількома модулями та використання твердження для доступу до функцій дозволяє зберігати індивідуальність та простоту модулів та спрощувати їх обслуговування. Зрозуміло, такий підхід приводить до зростання кількості модулів. При побудові складних систем виникає потреба в побудові певних ієрархій модулів. Належне документування функцій та модулів значно спрощує виконання таких задач.

2.3 Помилки


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

2.4 Техніка налагодження (зневаджування) програм


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

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

Якщо проблема локалізована чи у функції чи в рядку програми, потрібно вирішити що працює не так, як потрібно. Для цього можна відтворити за допомогою інтерпретатора та командної стрічки цю проблему, додати чи змінити деякі змінні. Потрібно перевірити розуміння тексту програми прочитавши документацію, чи проаналізувавши подібні приклади. Також корисно спробувати пояснити свою програму комусь ще – хто зможе побачити ваші проблеми.

В Python реалізовано зневаджувач програм ( debugger ) який дозволяє відслідковувати виконання програм, контролювати значення змінних, встановлювати місця зупинки (контрольні точки) виконання програми ( breakpoints), та покроково виконувати фрагменти програм. Застосувати зневаджувач для своєї програми (mymodule) та її функцій можна наступними чином:
^

3.   Розробка алгоритму програми


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

Найбільш відома стратегія розробки алгоритмів це divide-and-conquer (Поділяй і володарюй). Якщо потрібно вирішити задачу (проблему) розміром n, то можна її поділити на дві проблеми розмірами n/2, вирішити ці проблеми і поєднати ці результати для рішення початкової задачі (проблеми). Наприклад, припустимо, що потрібно відсортувати слова записані на окремих картках. Таке сортування можна виконати віддавши одну половину карток одній людині а іншу другій, які будуть сортувати тільки свої картки (звичайно вони можуть поступити аналогічно). Дві частини вже відсортованих карток не складно об’єднати в одне ціле. Рисунок 2 ілюструє такий підхід до вирішення задачі сортування.



Рис. 2 Сортування на основі Divide-and-Conquer.

Іншим прикладом може бути пошук слова у словнику. Книжка (словник) відкривається посередні і слово порівнюється з словами на цій сторінці. Якщо виявиться, що слово повинно бути в першій половині словника то знову перша половина ділиться, приблизно, на дві ріні частини і пошук повторюється. Такий метод пошуку називається бінарним пошуком, під час якого проблема ділиться на дві половини на кожному кроці.

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

3.1 Рекурсія


Приклади сортування та пошуку мають вражаючу властивість: для рішення проблеми розміром n, ця проблема ділиться на на дві половини і тоді вирішується одна або більше проблем розміром n/2. Загальний спосіб реалізувати такі методи це використати рекурсію. Визначається функція, яка спрощує проблему і ця функція викликає саму себе для рішення одного або більше випадків тієї самої проблеми. Далі ці результати поєднуються в рішенні початкової проблеми.
^

3.2 Динамічне програмування


Динамічне програмування основний метод розробки алгоритмів, який знайшов широке використання в обробці природної мови. Термін 'програмування' використовується в значенні планування або складання розкладу. Динамічне програмування використовується коли задача містить під задачі, що перетинаються. Замість повторного рішення цих під задач ці рішення зберігаються в таблиці.
^

4.   Приклади бібліотек Python


Існують сотні Python бібліотек сторонніх розробників, які є спеціалізованими програмними пакетами для розширення функціональності Python. NLTK є однією з таких бібліотек. Для використання всіх можливостей програмування на Python потрібно бути знайомими та використовувати такі бібліотеки. Більшість з цих бібліотек потрібно окремо встановлювати на комп’ютер.

4.1 Matplotlib


В Python розроблені спеціальні бібліотеки для візуалізації лінгвістичних даних. Пакет Matplotlib містить складні функції для побудови графічних зображень в стилі MATLAB. Бібліотека доступна за адресою http://matplotlib.sourceforge.net/.

Для представлення результатів роботи програми переважно використовується вивід по формату на екран або у файл. Графічна форма представлення результатів часто буває більш наочною та презентабельною. Наприклад, при виконанні лабораторної роботи №3 частотний розподіл модальних дієслів в різних жанрах корпуса Brown представлявся у вигляді таблиці. За допомогою наступної програми ці самі дані можуть бути представлені в графічному вигляді. Результат роботи програми представлено на рис 3.

 

colors = 'rgbcmyk' # red, green, blue, cyan, magenta, yellow, black

def bar_chart(categories, words, counts):

"Plot a bar chart showing counts for each word by category"

import pylab

ind = pylab.arange(len(words))

width = 1 / (len(categories) + 1)

bar_groups = []

for c in range(len(categories)):

bars = pylab.bar(ind+c*width, counts[categories[c]], width,

color=colors[c % len(colors)])

bar_groups.append(bars)

pylab.xticks(ind+width, words)

pylab.legend([b[0] for b in bar_groups], categories, loc='upper left')

pylab.ylabel('Frequency')

pylab.title('Frequency of Six Modal Verbs by Genre')

pylab.show()




 

>>> genres = ['news', 'religion', 'hobbies', 'government', 'adventure']

>>> modals = ['can', 'could', 'may', 'might', 'must', 'will']

>>> cfdist = nltk.ConditionalFreqDist(

... (genre, word)

... for genre in genres

... for word in nltk.corpus.brown.words(categories=genre)

... if word in modals)

...

>>> counts = {}

>>> for genre in genres:

... counts[genre] = [cfdist[genre][word] for word in modals]

>>> bar_chart(genres, modals, counts)









Рисунок 3 Гісторгама (діаграма у вигляді стовпчиків) частоти модальних дієслів в корпусі Brown.

З гістограми відразу зрозуміло що may та must мають приблизно однакові розподіли частот. Те саме можна сказати і про could та might.

4.2 NetworkX


Пакет NetworkX створений для роботи з графами. При необхідності його потрібно додатково встановлювати. Інсталяційні файли знаходяться на сторінці https://networkx.lanl.gov/. NetworkX може бути використаний разом з бібліотекою Matplotlib для візуалізації таких мереж, як WordNet (семантична мережа). В наступній програмі спочатку створюється пустий граф #1 далі здійснюється обхід по вузлах ієрархії гіпернімів WordNet (дуги додаються до графа) #2 . Здійснення обходу по вузлах потребує рекурсії #3. Результати візуалізації показані на рис 4.

 

import networkx as nx

import matplotlib

from nltk.corpus import wordnet as wn


def traverse(graph, start, node):

graph.depth[node.name] = node.shortest_path_distance(start)

for child in node.hyponyms():

graph.add_edge(node.name, child.name) #1

traverse(graph, start, child) #2


def hyponym_graph(start):

G = nx.Graph() #3

G.depth = {}

traverse(G, start, start)

return G


def graph_draw(graph):

nx.draw_graphviz(graph,

node_size = [16 * graph.degree(n) for n in graph],

node_color = [graph.depth[n] for n in graph],

with_labels = False)

matplotlib.pyplot.show()




 

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

>>> graph = hyponym_graph(dog)

>>> graph_draw(graph)









Рисунок 4. Візуалізація за домомогою NetworkX та Matplotlib: Показано частину ієрархії гіпернімів, починаючи від синсету dog.n.01 (темний вузол посередині); розмір візлів визначається кількістю його дітей, а колір визначається відстанню вузла від dog.n.01;

4.3 csv


При аналізі лінгвістичних даних зручно представляти ці дані у вигляді таблиць. CSV (від англ. Comma-Separated Values, Значення, розділені комою) — файловий формат, котрий є відмежовувальним форматом для представлення табличних даних, у якому поля відокремлюються символом коми та переходу на новий рядок. Фрагмент лексикону в CSV форматі буде наступний:

sleep, sli:p, v.i, a condition of body and mind ...

walk, wo:k, v.intr, progress by lifting and setting down each foot ...

wake, weik, intrans, cease to sleep

Можна використовувати бібліотеку Python CSV для читання та запису файлів у цьому форматі. Наприклад, можна відкрити CSV файл lexicon.csv #1 і проітерувати його рядки #2:

 

>>> import csv

>>> input_file = open("lexicon.csv", "rb") #1 Для виконання цього прикладу потрібно створити файл lexicon.csv з відповідними даними.

>>> for row in csv.reader(input_file): #2

... print row

['sleep', 'sli:p', 'v.i', 'a condition of body and mind ...']

['walk', 'wo:k', 'v.intr', 'progress by lifting and setting down each foot ...']

['wake', 'weik', 'intrans', 'cease to sleep']




Кожен рядок це список стрічок. Якщо певні поля містять числові дані то вони представляються, як стрічки і якщо потрібно то для подальшої роботи їх можна перетворити використовуючи функції int() або float().

4.4 NumPy


Пакет NumPy забезпечує виконання числових обчислень in Python. NumPy містить об’єкт – багатовимірний масив, який просто створити та доступатися до даних, які в ньому зберігаються:

 

>>> from numpy import array

>>> cube = array([ [[0,0,0], [1,1,1], [2,2,2]],

... [[3,3,3], [4,4,4], [5,5,5]],

... [[6,6,6], [7,7,7], [8,8,8]] ])

>>> cube[1,1,1]

4

>>> cube[2].transpose() # Транспонування матриці, операція транспонування: заміна рядків матриці на стовпчики.

array([[6, 7, 8],

[6, 7, 8],

[6, 7, 8]])

>>> cube[2,1:]

array([[7, 7, 7],

[8, 8, 8]])




NumPy містить також функції лінійної алгебри. В пакет кластеризації NLTK clustering package nltk.cluster широко використовуються масиви NumPy. Детальну інформацію можна отримати скориставшись файлами допомоги (в інтерпретаторі набрати help(nltk.cluster)).

4.5 Інші бібліотеки


На сьогодні розроблено багато інших бібліотек Python, перелік яких можна знайти за адресою http://pypi.python.org/. Багато бібліотек забезпечують інтерфейс з іншим програмним забезпеченням, таким як реляційні бази даних (наприклад mysql-python) та великими колекціями документів (наприклад PyLucene). Інші бібліотеки забезпечують доступ до файлів у таких форматах як: PDF, MSWord, та XML (pypdf, pywin32, xml.etree), RSS (наприклад feedparser), та файлів електронної пошти (наприклад imaplib, email).




Схожі:

Лабораторна №7 Основи програмування iconПрограма вступних випробувань з навчальної дисципліни «основи програмування та алгоритмічні мови»
Для студентів комп’ютерних спеціальностей вивчення дисципліни «Основи програмування та алгоритмічні мови» є однією з найважливіших...
Лабораторна №7 Основи програмування iconКурс «Спеціалізовані мови програмування»
Опанування мови програмування Java відкриває перспективи для застосування усього спектру технологій Java платформи. Метою та завданням...
Лабораторна №7 Основи програмування iconПрограма 2012
Оап (основи алго­рит­мізації та програмування). Програма передбачає навчити учнів володінню комп’ютером, його операційною системою...
Лабораторна №7 Основи програмування iconЗавдання для практичних І контрольних робіт із розділу «основи алгоритмізації та програмування»
...
Лабораторна №7 Основи програмування iconЗавдання для практичних І контрольних робіт із розділу «основи алгоритмізації та програмування»
...
Лабораторна №7 Основи програмування iconДокументи
1. /Основи програмування в середовищ_ MatLAB/Нац_ональний техн_чний ун_верситет Украхни.docx
Лабораторна №7 Основи програмування iconЛабораторна робота 6 Тема. Основи економічної кібернетики. Основи теорії систем. Управління в економічних системах. Основи теорії інформації
Мета роботи: закріплення теоретичного матеріалу з теорії систем та теорії інформації
Лабораторна №7 Основи програмування iconЛабораторна робота №1 тема: Основи роботи в локальних мережах Windows. Мережеві ресурси мета: Вивчення способів доступу до мережевих ресурсів. Ознайомлення з мережевими можливостями Windows
Лабораторна робота №1 тема: Основи роботи в локальних мережах Windows. Мережеві ресурси
Лабораторна №7 Основи програмування iconЛабораторна робота №1 Постановка задачі лінійного програмування та її розв’язання графічним методом Мета роботи
Мета роботи: Набуття навиків побудови математичної моделі задачі лінійного програмування, вивчення графічного методу для знаходження...
Лабораторна №7 Основи програмування iconВступ у програмування мовою Паскаль. Загальні відомо мості про мову Паскаль
Мова паскаль є універсальною мовою програмування високого рівня. Його основи розробив Ніклаус Вірт, професор технічного університету...
Додайте кнопку на своєму сайті:
Документи


База даних захищена авторським правом ©te.zavantag.com 2000-2017
При копіюванні матеріалу обов'язкове зазначення активного посилання відкритою для індексації.
звернутися до адміністрації
Документи