![]() |
Модераторы: korob2001, ginnie |
![]() ![]() ![]() |
|
Zuzu |
|
|||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 140 Регистрация: 19.10.2006 Где: Екатеринбург Репутация: 3 Всего: 4 |
Напиши, пожалуйста, что было до обработки этого предложения (там, возможно, были пробелы) Про <to be>. Приведи, пожалуйста, точный пример: Исходное предложение: То же предложение, "обработанное" goldStandart: То же предложение, обработанное tagger: Математическая модельтребует, чтобы тексты (для tagger и goldStandart) были абсолютно, слово в слово, одинаковые. Проблему с I'm можно решить, путем переведения "I'm" в "I am" (для goldStandart) либо обратно "I am" в I'm для (tagger). По этому поводу можно либо написать маленькую программку и обработать ей goldStandart (или tagger) - текст Затем, для первого случая, - по накатанной дорожке (убрать тэги, скормить tagger'у, скормить програмрамме - считальщику качества тэггера). После этого было бы неплохо сравнить "пословно" файлы. В принципе, программа-анализатор, в качестве бесплатного приложения, это сделает. Третий способ (в моем случае) - взять данные "как есть" и возложить эту непосильную задачу (по приведению I'am r I am) на объект GoldStorage или TaggerStorage Как чувствовал, что будут проблемы с исходными данными! Поэтому при проектировании не воспользовался одним классом Storage, а породил от него два класса: GoldStorage и TaggerStorage! LisaST, спасибо за отзыв по коду. Если по каким-то причинам нет возможности (или, как вариант, времени на изучение) ООП-механизмов на Perl, напиши, как тебе удобнее. Тем более, что с "трансформерами" я несколько перемудрил. В принципе, для "приведения диалекта тэга к каноническому виду", достаточно такого механизма, как хэш. P.S. По терминологии ООП, которую я использовал: интерфейс класса (или порожденного от него объекта) - есть множество (или совокупность) методов и свойств, которые разрешены к использованию по отношению к объекты (в терминологии классического ООП - public методы и свойства). Понятия свойство и метод - аналогичны классическим определениям. Понятия "пакет" и "модуль" вроде не использовал. Уж очень отличаются эти понятия в контексте UML и perl, например. Но это здесь offtopic. --------------------
Проводить эксперименты на живом сервере опасно, а на мертвом - бесполезно. |
|||
|
||||
amg |
|
||||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1145 Регистрация: 3.8.2006 Где: Новосибирск Репутация: 38 Всего: 50 |
Убрать все несоответствия на многомегабайтном файле не очень реально, особенно если разные таггеры будут вести себя по разному, все равно останется много ручной работы. Повторю (скорее для себя) что уже предлагал Zuzu:
|
||||
|
|||||
Zuzu |
|
|||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 140 Регистрация: 19.10.2006 Где: Екатеринбург Репутация: 3 Всего: 4 |
Мысли по поводу решения задачи в связи с появлением такого артефакта, как "разные слова".
В математической модели я потребовал, в качестве определения контекста слова расположение по отношению (ко всем) к другим словам в тексте. Это несколько больше, чем определение контекста с точки зрения лингвистики (ИМХО, могу и ошибаться). Если сузить определение контекста до взаимного расположения слов внутри предложения (нужно еще, конечно, четко определить, что такое предложение ![]() ![]() --------------------
Проводить эксперименты на живом сервере опасно, а на мертвом - бесполезно. |
|||
|
||||
amg |
|
||||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1145 Регистрация: 3.8.2006 Где: Новосибирск Репутация: 38 Всего: 50 |
То, что находится в пределах одной строки (так в GoldStandard'е, а другого текста и иным расположением предложений, я так понимаю, все равно взять неоткуда, точнее, взять то можно, но не с чем будет сравнивать).
|
||||
|
|||||
LisaST |
|
||||||||
Шустрый ![]() Профиль Группа: Участник Сообщений: 56 Регистрация: 8.4.2006 Где: Munich Репутация: нет Всего: нет |
1. нет, пробелов не было, самое интересное, что двойные точки не остались, а ?, !, :,; остались в двойном варианте, но мы знаки препинания все равно будем игнорировать, я удалила двойные с помощью sed и протестировала таггер на этом голдстандард тексте 2. внизу пример для одного и того же предложения, т.е. в голдстандард кол-во слов будет на 1 меньше, но таких примеров будет очень много, как ты предлагаешь позднее- их лучше после проверки игнорировать, т.к. они очень усложняют задачу. ps Еще в голдстандард варианте с тегами видимо проводили chunking, поэтому на теги иногда навешаны дополнительные теги к части речи не имеющие ничего общего (-tl, -hl, -tl-hl), мне их надо удалить, чтобы упростить нахождение соотв. тегов. goldstandard.txt
очень хорошая идея, хотя я не совсем точно препологаю, что здесь можно сделать. например, один из вариантов посчитать "/" (что будет подразумевать кол-во тегов) для каждого предложения, если есть расхождения, то предложения в анализе не использовать (т.е. там будут расхождения как в примере выше) Это сообщение отредактировал(а) LisaST - 26.1.2007, 21:47 |
||||||||
|
|||||||||
Zuzu |
|
|||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 140 Регистрация: 19.10.2006 Где: Екатеринбург Репутация: 3 Всего: 4 |
По поводу "предложений с разными словами" есть такая сырая идея.
Основная мысль, собственно, проста. Исходные тексты у нас нормальные - мы их сами такими старались-готовили. И, наверно, даже проверяли, чтобы они изначально были "пословно равны"!. Если собака-тэггер попортил наши данные, путем "вставления в предложения" нового слова, то удаление этого слова может только улучшить ситуачию, т.к. приводит ее к тому виду, который был раньше. ![]() Опять-же, сильно он напортить не мог. Ему ведь отдали "нормальное предложение", его задача не "испортить предложение", а тэги расставить! А то, что предложения испортилоси это получилось у него так, случайно, случайно. ![]() 1. Пусть предложения равны, если они "пословно" равны. 2. Пронумеруем предложения сверху вниз по двум текстам (от tagger и goldStandart). 3. По построению (т.е. текст-то мы делали сами!) у нас получается, что кол-во предложений в первом тексте и во втором - одинаковое. 4. Если не сошлось кол-во предложений - оставшиеся предложения в каком-то тексте отбросим, результат посчитаем, но будем считать его недостоверным - это повод проверить исходные данные. 5. Пусть в некотором числовом выражении мы получили критерий "степени равенства предложений". Это должна быть некоторая функция, определенная на двух предложениях (из разного текста, но с одним номером), которая, как вариант, достигает своего локального (на этих двух предложениях), максимального значения при равенстве предложений (пословно). Или, говоря по-русски, в каждый момент времени, нас интересует ее максимум на этой "двойке предложений" (т.е. локальный максимум). В этот момент на остальные предложения нам абсолютно наплевать. И вообще, как соотносятся эти максимумы для разных "двоек" - нам тоже абсолютно безразлично. 6. Итак, взяли двойку предложений, пронумеровали слова, сравнили их пословно, выяснили, что предложения не равны. 7. Находим в предложениях то слово, по которому они не сошлись. Т.е. находим такое n (слова), что w1(n) ne w2(n), где w1(n), w2(n) - слова с номером n в первом и втором предложении соответственно, "ne" - операция сравнения строк на неравенство от Perl. 8. Считаем исходный "критерий равенства предложений", запоминаем его в c0. 9. Из исходного первого предложения выбрасываем слово с номером n, считаем "критерий равенства предложений" для "поправленного первого" и "исходного второго" предложения, запоминаем в c1 10. Аналогично поступаем со вторым предложением, запоминаем значение в c2 11. Выбрасываем слово с номером n и из первого (исходного) и из второго (исходного) предложения, считаем "критерий равенства", запоминаем значение в с3 12. По максимальному значению из с0, c1, с2, с3 выбираем тот способ, которые "лучше уравнивает предложения", его и пременяем к двойке предложений. Т.е. выбрасываем слово либо из первого предложения, либо слово из второго либо слово с номером n из первого и из второго предложения. Либо ничего ниоткуда не выбрасываем. 13. Если что-то выбросили , сравниваем предложения. Если не равны - переходим к п. 7. 14. Если получилось, что исходные предложения не равны, а значение с0 - максимально, предложение бракуем - оно не участвует в подсчете качества тэггера. ![]() Как определить "критерий равенства предложений"? С этим сложнее... Надо смотреть... Пока четкой мысли нет. P.S. Разговор про локальный максимум функции. Наверно вспоминается (кому-то пресловутый) курс математического анализа. Как находили локальный экстремум (минимум, максимум, перегиб) функции в мат. анализе? Правильно, путем двойного последовательного дифференцирования функции, приравнивания первой производной для нахождения точек экстремума и выяснения знака второй производной в этой точке для выяснения типа точек экстремума. Казалось бы, все просто. НО! У нас-то функция дискретная, а значит не являющаяся непрерывной! Следовательно, ее нельзя дифференцировать. Значит вся эта "крутая теория" в нашем случае неприемлима. Я кстати, изначально слукавил - в теоремах про нахождение локального максимума и минимума изначально говорится о том, что они пименимы к два раза диференцируемым (читай - непрерывным и с непрерывной первой произодной) функциям. К чему я все это? Так вот. Если вдруг удастся построить функцию "критерия равенства" таким образом, что бы она была непрерывна, то можно будет решить задачу "выбрасывания лишних слов" аналитически, т.е. не перебирая все варианты. В чем прикол? А в том, что затем ее можно будет применить к какому угодно большому тексту и время которое будет необходимо для "выбрасывания" слов будет зависеть только от количества "плохих слов", а не от размера самого текста. Вот так. Высшая математика (а пока мы коснулись только ее основ - на уровне первого курса вуза) РУЛИТ! Это сообщение отредактировал(а) Zuzu - 27.1.2007, 10:29 --------------------
Проводить эксперименты на живом сервере опасно, а на мертвом - бесполезно. |
|||
|
||||
Zuzu |
|
|||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 140 Регистрация: 19.10.2006 Где: Екатеринбург Репутация: 3 Всего: 4 |
LisaST, и еще. Как бы я реализовывал все это дело (программу в целом). С учетом разных слов.
Следал бы объект "предложение". Он бы запрашивам предложения у объекта "хранилище". (см. мой код) Написал бы метод, который бы "нормализовал" два предложения. Т.к. пока непонятно как он должне работать - он бы просто ничего интеллектуального не делал. Разве что предложения друг с другом сравнивал пословно и возводил в обоих объектах-предложениях флажок, если предложения не равны. Слово и тип слова запрашивал бы у объекта "предложение", пока там есть слова. Попросил бы объект "предложение" возвращать слова только в том случае, если предложения равны. Вот собственно. В первом приближениии получится, что "предложения с разными словами" мы будем пропускать. В реальном проекте, если не хватит ресурсов (времени на разработку или денег у заказчика, как вариант) получил бы работающий в некотором приближении проект, которому в дальнейшем (при появлении ресурсов) можно достаточно просто "добавить интеллекта", не переписывая его целиком (и, собственно, особо не вникая во всю проблему, а только обозначив ее часть - функцию "критерий равенства предложения"). Это сообщение отредактировал(а) Zuzu - 27.1.2007, 11:02 --------------------
Проводить эксперименты на живом сервере опасно, а на мертвом - бесполезно. |
|||
|
||||
amg |
|
||||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1145 Регистрация: 3.8.2006 Где: Новосибирск Репутация: 38 Всего: 50 |
Это сообщение отредактировал(а) amg - 27.1.2007, 12:01 |
||||
|
|||||
amg |
|
||||||||||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1145 Регистрация: 3.8.2006 Где: Новосибирск Репутация: 38 Всего: 50 |
LisaST, предлагаю Вам набор скриптов. К сожалению, совсем некогда сейчас подробно расписывать, что они делают. Если что не понятно будет, то позже поясню. Собственно, осталось только реализовать алгоритм подсчета индексов, который Вы с Zuzu обсуждали, на "нормализованных" файлах это должно быть легко.
Первые 4 скрипта используют конструкцию while (<>) {} и печатают на stdout, т.е. можно использовать конвейеры: tag-good GoldStandart.pos | tag-uni -G > GoldStandart.pos.uni tag-good CRFTagger.pos | tag-uni -С > CRFTagger.pos.uni tag-norm GoldStandart.pos.uni CRFTagger.pos.uni
Это сообщение отредактировал(а) amg - 30.1.2007, 10:02 |
||||||||||
|
|||||||||||
LisaST |
|
||||||||
Шустрый ![]() Профиль Группа: Участник Сообщений: 56 Регистрация: 8.4.2006 Где: Munich Репутация: нет Всего: нет |
спасибо вам большое обоим за участие в решении проблемы и помощь. нормализацию, как я поняла амг реализовал в последнем отрывке кода, я попробую завтра все это потестировать. Высшую мат-ку я, к сожалению, не проходила, из определения мах и мин помню только Lagrangian algorithm
согласна, "/" в голдстандард без тегов не встречается, но в другом тексте вполне вероятно -------------------------------- к коду от амг, я там многого не понимаю, конечно 1. ($good_word = qr/^[^\W\d_]+$/; # Only letters -> я так поняла, что "[^\W\d_]" = \w ^ перед [, это начало сроки? #$good_word = qr/^[[:^punct:]]+$/; # Except punctuations) -> в этом отрывке кода мы пытаемся удалить -tl, -hl etc? оставив только слово и тег после него, кот. тоже является словом? !возникает проблема, т.к. существуют "нормальные теги" , которые заканчиваются на $, например pp$ 2.
не совсем понимаю, что в $TAG keys, a что values? 3.
не понятно, что имелось ввиду с digits (\d) здесь? и вот с этим выражением не разобралась : sprintf("%03d",$i++) ------------------------------------------------------------------------- sorry за простые вопросы, но я в модулях перл никак и вообще дальше user не забредала |
||||||||
|
|||||||||
Zuzu |
|
|||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 140 Регистрация: 19.10.2006 Где: Екатеринбург Репутация: 3 Всего: 4 |
Обещанная полное описание требований и определений для задачи:
Понятия: слово, предложение, часть речи (по отношению к слову), текст, равенство слов определяются исходя из общеупотребительного значения соответствующего понятия. Два слова равны, если они побуквенно, слева направо, равны. Слово обозначим за wrd. Контекст (слова) - взаимное расположение слова относительно слов в преджложении. Тип слова - часть речи, к которой принадлежит слово. Канонический тип слова - название типа слова, которое выбрал пользователь для каждого типа слова. Если не указано особо, подразумевается именно канонический тип слова. Наречие таггера, названия типов слов, которое возвращает таггер. Обозначим также как тип слова от таггера. Таггер (tagger) - некая процедура, которая ставит слову в соответствие его тип из множества типов из наречия таггера. Различают тестируемый таггер - тот качество которого мы оценивает, назовем его собственно таггер() (или tagger()) и tagger - образец, который сопоставляет слову его тип заведомо правильно. Назовем его goldStandart() . Результатом работы таггера является тип слова в соответствии с наречием таггера. Трансформация наречия (таггера) - некий механизм приведения наречия таггера к каноническому виду. Возможно реализуется в виде отношения много (типов от таггера) к одному (каноническому типу). Обозначим соответственно trT() и trG() для tagger() и goldStandart() соответственно. Возможен вариант, когда элемент наречия таггера не имеет значения в каноническом типе. Для определения равенства предложений, будем считать предложение также упорядоченным множеством слов, его составляющим. Для этого пронумеруем слова в предложении слева направо. Предложения равны, если слова с одинаковыми номерами в первом и втором предложении равны. Для определения равенства текстов пронумеруем предложения в тексте с начала до конца тектса. Тексты равны, если предложения первого и второго текста с одинаковыми номерами равны. Множество слов W - определим как упорядоченное множество троек (p, n, wrd), где p - порядковый номер предложения в тексте, n - порядковый номер слова в предложении, w слово. p(W) - количество (число) элементов в этом множестве. Двух одинаковых элементов-слов в (одном) множестве нет! Элемент множества (тройку (p, n, wrd)) обозначим за w Дополнительно заметим, что tagger() и goldStandart() должны быть определены на всем этом множестве W. Релевантность - правильность определения tagger()'oм типа слова. Может принимать только значения "да" или "нет". Для w из W релевантность считается истиной, если trT(tagger(w)) == trG(goldStandart(w)). Заметим, если слова, (в общем случае) взяты из разных текстов, то релевантность для слов (не для тройки w!) имеет смысл только если эти слова (как слова) равны и взяты в одинаковом контексте (т.е. из одинаковых (равных) предложений, слова с одинаковыми номерами). Это уменьшение строгости , в принципе, позволяет применять определение релевантности к "неравным" текстам и по ним считать Recall и Precision (естественно, для этого, множество W должно быть специальным построено по этим двум текстам!). Напомним, что t - некоторый канонический тип слова. Общее кол-во отпределенных слов одного типа - количество элементов w из всего W, тип которым тэггер определил как t (правильно или нет - нас не интересует). Обозначм как NT(t) (для типа t). Общее кол-во правильных слов одного типа - количество элементов w из всего W, тип которым goldStantart определил как t (обязательно правильно - по построению goldStandart) Обозначм как NG(t) (для типа t). Общее кол-во правильно определенных слов одного типа - количество элементов w из всего W, тип которым тэггер определил как t правильно (т.е. так же как goldStandart) или, другими словами, релевантно. Обозначим N(t) (для типа t). И, собственно, самое главное (наконец-то!) Еще раз: t - тип слова. Precision (насколько точно выбирает) Отношение кол-ва правильно выбранных (релевантных) слов к общему кол-ву выбранных тэггером для определенного типа. Precision(t) = (N(t) / NT(t)) * 100% Recall (как вообще выбирает) Отношение кол-ва релевантно выбранных тэггером слов к общему кол-ву правильных слов для определенного типа. Recall(t) = (N(t) / NG(t)) * 100% Вроде все. За границами остался алгоритм "нормализации" предложений. если они не равны. Смтрите, может где ошибся - немаленький текст получился. ![]() Это сообщение отредактировал(а) Zuzu - 31.1.2007, 11:42 --------------------
Проводить эксперименты на живом сервере опасно, а на мертвом - бесполезно. |
|||
|
||||
amg |
|
||||||||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1145 Регистрация: 3.8.2006 Где: Новосибирск Репутация: 38 Всего: 50 |
Не так. У меня $good_word - это то, что в конструкции word/tag находится до последнего экземпляра "/". Если хочется обработать тэги, то нужно что-то вроде
В выражении $TAG{$2}{$1}++ while m/(\S+)\/(\S+)/g; %TAG - это хэш хэшей. Его ключи - это тэги, значения - ссылки на хэши. У последних ключи - это слова, значения - кол-во слов. Например, $TAG{nn}{work} == 12 означает, что среди слов, помеченных тэгом "nn", слово "work" встретилось 12 раз. LisaST, обратите, пожалуйста внимание, насколько хорошо perl приспособлен для подобного рода задач! Одно короткое выражение разбирает строку и создает довольно нетривиальную структуру данных (все остальное - лишь представление результатов).
1. Сортируем элементы каждой строки по алфавиту. Если в пределах одной строки нет совпадающих элементов, то этого достаточно. Соответствие строк не нарушится. Но строки могут выглядеть так: aaa/xx work/nn bbb/xx work/vb aaa/xx work/vb bbb/xx work/nn и простая сортировка по алфавиту даст aaa/xx bbb/xx work/nn work/vb aaa/xx bbb/xx work/nn work/vb Это неправильно. Поэтому сначала элементы нумеруются, затем сортируются и нумерация удаляется. aaa/xx work/nn bbb/xx work/vb => aaa/001xx work/002nn bbb/003xx work/004vb aaa/xx work/vb bbb/xx work/nn => aaa/001xx work/002vb bbb/003xx work/004nn sprintf("%03d",$i++) как раз для вставки номера: это выражение возвращает номер с нулями и затем этот номер инкрементирует. Кстати, после внимательного прочтения perldoc -f sort выяснилось, что для perl 5.7 и выше функцию, возвращающую сортированный массив, можно упростить. Дело в том, что в этой версии perl ввели алгоритм сортировки, который в случае, если с точки зрения sort элементы совпадают, то сохраняется тот порядок элементов, который был в источнике.
2. Дальше сравниваем отсортированные массивы: - Если элементы совпадают, то переходим к следующим элементам. - Если в 1-ом массиве i-й элемент "меньше" (с точки зрения cmp), чем во i-й элемент второго, то удаляем этот элемент из 1-го массива, если "больше" - то из 2-го массива - Снова сравниваем i-е элементы Добавлено @ 11:20 Zuzu, как во-время твой пост! Я как раз собрался листать все 4 страницы этого топика, чтобы точно понять, что такое Recall & Precision. А тут все в одном месте с четкими определениями. Кстати, глянь, пожалуйста, алгоритм нормализации и покритикуй, если есть за что. |
||||||||
|
|||||||||
Zuzu |
|
|||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 140 Регистрация: 19.10.2006 Где: Екатеринбург Репутация: 3 Всего: 4 |
То, что алгоритм работает правильно, неочевидно (по крайней мере для меня). Несколько смущает изменение порядка слов. Но на примерах вроде работает. К сожалению доказать неправильность (подобрать хотя бы один пример, когда не сработает) не могу. Строго доказать правильность (что выбросит именно неверные слова) - тоже не приходит на ум, как это можно сделать математически точно. Сам код пока не смотрел. Предлагаю просто сейчас оставить алгоритм как есть, т.к. (если он работает по задуманному), то на одинаковые предложения он не реагирует. Дополнительно вывести в отдельный файл результаты "нормализации" (где она сработала) и просто оценить "глазами", сработало правильно или нет (да уж, кропотливый труд предстоит!) --------------------
Проводить эксперименты на живом сервере опасно, а на мертвом - бесполезно. |
|||
|
||||
amg |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1145 Регистрация: 3.8.2006 Где: Новосибирск Репутация: 38 Всего: 50 |
Для проверки можно использовать такой способ:
Это сообщение отредактировал(а) amg - 29.1.2007, 13:18 |
|||
|
||||
Zuzu |
|
|||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 140 Регистрация: 19.10.2006 Где: Екатеринбург Репутация: 3 Всего: 4 |
amg, здраво, конечно. К сожалению, строго не доказывает, что удалены именно "неправильные" слова. Могут быть с таким же успехом быть удалены и "нормальные" слова (попарно) из обоих текстов.
Для дополнительной проверки можно посчитать кол-во удаленных слов. По специфике построения текста от tager, из него должно быть удалено слов в два раза больше, чем из текста от goldStandart. Это условие должно выполняться для каждого (неверного) предложения текста и, следовательно, для всего текста в целом. LisaST поправит, если это не так. В целом, т.к. соблюдается указанное тобой в предыдущем топике условие (тексты равны пословно) и нормализация затрагивает только одно предложение (в каждый момент выполнения), думаю, что можно назвать алгоритм "условно правильным". --------------------
Проводить эксперименты на живом сервере опасно, а на мертвом - бесполезно. |
|||
|
||||
![]() ![]() ![]() |
Правила форума "Perl" | |
|
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, korob2001, sharq. |
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Perl: Общие вопросы | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |