Изменить: этот код был обработан и выпущен в качестве базового модуля: https://github.com/hyperreality/Poetry-Tools
Я лингвист, который недавно взял питон, и я работаю над проектом, который надеется автоматически анализировать стихи, включая обнаружение формы стихотворения. То есть если он найдет 10 слоговых строк с рисунком напряжения 0101010101, он объявит, что это ямбический пентаметр. Стихотворение с 5-7-5 слогами будет хайку.
Я использую следующий код, часть более крупного script, но у меня есть ряд проблем, которые перечислены ниже программы:
corpus в script - это просто исходный ввод текста стихотворения.
import sys, getopt, nltk, re, string
from nltk.tokenize import RegexpTokenizer
from nltk.util import bigrams, trigrams
from nltk.corpus import cmudict
from curses.ascii import isdigit
...
def cmuform():
tokens = [word for sent in nltk.sent_tokenize(corpus) for word in nltk.word_tokenize(sent)]
d = cmudict.dict()
text = nltk.Text(tokens)
words = [w.lower() for w in text]
regexp = "[A-Za-z]+"
exp = re.compile(regexp)
def nsyl(word):
lowercase = word.lower()
if lowercase not in d:
return 0
else:
first = [' '.join([str(c) for c in lst]) for lst in max(d[lowercase])]
second = ''.join(first)
third = ''.join([i for i in second if i.isdigit()]).replace('2', '1')
return third
#return max([len([y for y in x if isdigit(y[-1])]) for x in d[lowercase]])
sum1 = 0
for a in words:
if exp.match(a):
print a,nsyl(a),
sum1 = sum1 + len(str(nsyl(a)))
print "\nTotal syllables:",sum1
Я предполагаю, что результат, который я хочу, будет таким:
1101111101
0101111001
1101010111
Первая проблема заключается в том, что я потерял разрывы строк во время токенизации, и мне действительно нужны разрывы строк, чтобы иметь возможность идентифицировать форму. С этим не должно быть слишком сложно справиться. Большие проблемы заключаются в следующем:
- Я не могу иметь дело с словарями, отличными от словаря. В данный момент я возвращаю 0 для них, но это будет путать любую попытку идентифицировать стихотворение, поскольку слоговое число строки, вероятно, уменьшится.
- Кроме того, в словаре CMU часто говорится, что есть стресс на слово - "1" - когда нет - "0". Вот почему результат выглядит следующим образом: 1101111101, когда это должно быть напряжение ямбического пентаметра: 0101010101
Итак, как бы я мог добавить некоторый fudging фактор, чтобы стихотворение все еще идентифицировалось как ямбический пентаметр, когда оно только приближалось к шаблону? Нехорошо кодировать функцию, которая идентифицирует строки 01, когда словарь CMU не будет выводить такой чистый результат. Полагаю, я спрашиваю, как закодировать алгоритм "частичного совпадения".