В этой статье основное внимание уделяется тому, как я запускаю выпущенный код статьи 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
. В конце концов, это работает !! Хотя я еще не оценил производительность их кода, используя их оценочные сценарии ...
КАКАЯ РАЗНИЦА?
Теперь это работает, и я могу немного отдохнуть.
Следующая задача: оценить работоспособность кода, провести анализ ошибок
Продолжение следует…