В этой статье основное внимание уделяется тому, как я запускаю выпущенный код статьи EMNLP 2018: Совместное извлечение нескольких событий с помощью агрегирования графической информации на основе внимания.

Их ссылка на GitHub находится здесь, или вы можете скачать ее по этой ссылке (время загрузки: 22.02.2019) (Я не владею им.)

Честно говоря, я ненавижу читать чужой код, не говоря уже о том, что код имеет плохую документацию.

Бьюсь об заклад, есть такие, как я (поднимите руку); поэтому я решаю написать этот пост, чтобы записывать все обнаруженные мной ошибки.

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: мой процесс не может быть ярлыком. Вы обнаружите, что нет необходимости перемещать некоторые файлы и что вы редактируете файлы раньше, но это не решит проблему позже. Вы должны сначала прочитать его, а не следовать моей процедуре шаг за шагом. Кроме того, термин «запустить» означает, что кажется, что он работает правильно, я не писал кода для преобразования набора данных ACE 2005 в его формат, и я не тестировал их производительность. Я просто отлаживаю некоторые очевидные проблемы, надеясь, что это поможет облегчить работу при использовании этого кода.

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

Ладно, приступим.

На первый взгляд, их код на GitHub организован несколько аккуратно, я думаю, но я особенно ненавижу это, если README не сообщает нам правильную позицию каждого файла и какой файл запускать. Итак, я прочитал их README, и там написано:

Как запустить код?

После предварительной обработки набора данных ACE 2005 и помещения его в ace-05-splits главный вход находится в enet/run/ee/runner.py. Мы не можем включить данные в этот выпуск из-за проблем с лицензией.

Но мы предлагаем образец данных в ace-05-splits/sample.json, формат должен соблюдаться.

КОД ЯВЛЯЕТСЯ ОСНОВНОЙ ПРЕДВАРИТЕЛЬНОЙ ВЕРСИЕЙ И ПРЕДСТАВЛЯЕТСЯ «КАК ЕСТЬ», БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ.

Ладно, неплохо (фейспалм). Может, мне сначала пойти на runner.py и запустить его. Итак, вот что произошло:

(venv) xxxyyyzzz: ~ / JMEE / enet / run / ee $ python runner.py
Отслеживание (последний вызов последним):
Файл «runner.py», строка 13, в ‹module› < br /> from enet import consts
ImportError: нет модуля с именем 'enet'

Местоположение runner.py должно быть под ~/JMEE/.
Решение: используйте команду mv (я предлагаю вместо этого использовать cp, поскольку вы не знаете, столкнетесь ли вы с другими проблемами позже).

Повторно запустите код еще раз.

(venv) xxxyyyzzz: ~ / JMEE $ python runner.py
Запуск на процессоре
Отслеживание (последний вызов последним):
Файл «runner.py», строка 237, в ‹module›
EERunner (). run ()
Файл «runner.py», строка 95, в процессе
keep_events = 1)
Файл «xxxyyyzzz / JMEE / enet / corpus / Data .py », строка 190, в __init__
super (ACE2005Dataset, self) .__ init __ (путь, поля, ** kwargs)
Файл« xxxyyyzzz / JMEE / enet / corpus / Corpus.py », строка 20, в __init__
examples = self.parse_example (путь, поля)
Файл «xxxyyyzzz / JMEE / enet / corpus / Data.py», строка 195, в parse_example
с open (path , «R», encoding = »utf-8) как f:
TypeError: недопустимый файл: None

Мы видим, что после вызова функции parse_example файл будет открыт, но сейчас этот файл None, что означает, что аргумент path равен None. Таким образом, я ищу runner.py. В строке 87 путь назначен self.a.train, а self.a - из parser (строка 46). Я захожу в папку scripts и смотрю, что делать train.sh, потому что я проверил этот сценарий и помню, что у него много аргументов, которые нужно передать.

Мы находим, что поезд (--train) ест ace-05-splits/training.jl, мы также видим, что --dev и --test едят ace-05-splits/dev.jl и ace-05-splits/test.jl соответственно. Следовательно, нам нужно подготовить эти три файла позже. (Кстати, что за чертовщина .jl?) [Обновление: думаю, это список json.]

p.s. Увидев содержимое train.sh, я копирую его в _26 _. (Поскольку он будет запускать enet.run.ee.runner)

Следующий шаг - узнать, откуда берутся три файла (training.jl, dev.jl и test.jl), поэтому я смотрю на datasplit.py (под qi_filelist). Я отчасти знаю, что file_name в строке 17 может быть output_path / [обучение, тест, разработчик] .jl, и он записывается в fout.

Затем я вижу, что flist может быть new_filelist_ACE_training, new_filelist_ACE_dev и new_filelist_ACE_test. В строке 18 код

«Qi_filelist / new_filelist_ACE_% s»% split_name

похож на sprintf в C.

p.s. простой пример

››› s = «test% s»% «123»
››› s
‘test123’

В datasplit.py, строки 19–25, он будет открывать соответствующий файл json построчно ─ программа откроет «CNN_CF_20030303.1900.00.json» в строке 1 (bc / text2norm / CNN_CF_20030303.1900.00) ─ и затем запишет файл json в fout , то есть training.jl, dev.jl и test.jl.

Примечание: файл json находится в каталоге input_path; training.jl, dev.jl и test.jl находятся в output_path каталоге.

Посмотрите в код (строки 9, 10), input_path и output_path, мы должны создать файл json. Автор загрузил sample.json под ace-05-splits/.
p.s. нам нужно переместить (скопировать) datasplit.py с ~/JMEE/qi_filelist/ на ~/JMEE/ из-за кода в datasplit.py (строка 18).

Я стараюсь сначала использовать sample.json на случай, если напрасно напишу сценарии для преобразования набора данных ACE 2005 в его формат (если авторский код по какой-то причине не работает должным образом). Поработав, я печатаю

python datasplit.py ./ace-05-splits/ ./ace-05-splits/

И результат становится

Отслеживание (последний вызов последним):
Файл «datasplit.py», строка 22, в ‹module›
fname = fname.split («/») [- 1] + «.json» < br /> TypeError: требуется объект, подобный байтам, а не str

В операции добавления тип в первой части является байтовым, а не строковым, поэтому я пытаюсь отключить двоичный параметр при открытии файла в строке 18, 23. ("rb""r", "wb""w")

Кажется разумным следующее:

Проверяя training.jl, dev.jl и test.jl, я обнаружил, что этот код работает должным образом. Он будет читать new_filelist_ACE_training (также new_filelist_ACE_dev и new_filelist_ACE_test). В каждом файле он читает строку за строкой, извлекает соответствующий файл json в input_path, а затем записывает его в training.jl в output_path. (Один файл jl содержит несколько файлов json.)

p.s. Из приведенного выше эксперимента я пишу только одну строку (path/sample) в new_filelist_ACE_training, new_filelist_ACE_dev и new_filelist_ACE_test. Следовательно, training.jl, dev.jl и test.jl такие же, как sample.json.

p.p.s. строки 20, 21 будут иметь дело с вводом некорректного формата (на всякий случай?)

Теперь, когда он работает, мы можем выполнить train.sh. Однако сообщение об ошибке появляется в enet081.log:

Умммммм… Похоже, возникла проблема при изменении бинарного опциона? И я считаю, почему автор использует json.loads (с буквой «s»), а НЕ _82 _ !!!! (переворот стола)

В любом случае, автор использует f.write() для записи файла json, это странно, разве мы обычно не используем json.dump()?

После некоторого поиска «s» в json.loads означает «строка». Потому что мы храним файл построчно, поэтому он содержит «\ n» в каждой строке. Неудивительно, что при загрузке файла json происходит сбой. Решение состоит в том, чтобы сохранить файл json в одной длинной ~ длинной ~ строке, и нам также нужно удалить символ новой строки в файле json, чтобы он успешно «загружался».

p.s. Я думаю, что этот метод называется Stringify в Node.js
p.p.s. Некоторая справка (одна на английском, две на китайском):







Чтобы решить эту проблему, я изменяю код в data-split.py (строка 24) и меняю его на эти две строки (строки 24, 25):

jj = jf.read().strip()
jj = ''.join(jj.split("\n"))+ "\n"

Кажется работоспособным, поскольку я повторно запускаю train.sh:

Теперь нам нужен файл встраивания GloVe (glove.6B.300d.txt). Зайдите на сайт Stanford NLP, загрузите glove.6B.zip, разархивируйте и создайте путь (~/JMEE/embedding/glove.6B/), переместите в него glove.6B.300d.txt.

Выполните еще раз и получите следующее:

Нам нужно создать каталог enet-081 в JMEE/models/
p.s. В коде есть каталог models в enet, но я не уверен, будут ли на файлы внутри него ссылаться другие файлы (например, импорт, открытие и т. Д.), Поэтому я воссоздаю еще один.

После этого я запускаю ./train.sh, и теперь он работает. (Ура!)

Ты хочешь.

Он работает «вечно», и файл журнала становится все больше и больше. Чтобы понять, почему запуск одного файла занимает так много времени, я проверяю train.sh и обнаруживаю, что для epochs установлено значение 99999. Измените значение на 10, чтобы сократить время ожидания, и снова запустите train.sh.

Прочтите файл журнала, он говорит:

Похоже, нам нужно создать каталог test 1 в ~/JMEE/models/enet-081/, чтобы можно было сгенерировать 1.txt. Мне также нужно построить dev 1, чтобы избежать следующей ошибки.

Наконец, повторно запустите train.sh…

Надеюсь, он сможет успешно работать…

Теперь мы можем видеть 1.txt в папках test 1 и dev 1. В конце концов, это работает !! Хотя я еще не оценил производительность их кода, используя их оценочные сценарии ...

КАКАЯ РАЗНИЦА?

Теперь это работает, и я могу немного отдохнуть.

Следующая задача: оценить работоспособность кода, провести анализ ошибок

Продолжение следует…