Skip to content

Latest commit

 

History

History
83 lines (58 loc) · 6.02 KB

File metadata and controls

83 lines (58 loc) · 6.02 KB

Tokenization

Как известно, даже путь в тысячи строк начинается с первой строки, а точнее даже с постановки первой задачи — куда вообще нужно идти. Чтобы иметь возможность разбить японский текст на токены, нам нужно следующее: создать словарь уникальных слов, подготовить тестовый файл с предложениями, написать алгоритм MaxMatch, оценить результат работы нашего алгоритма с помощью метрики WER.

Словарь мы создаем на основе файла ja_gsd-ud-train.conllu, используя регулярные выражения, чтобы избавиться от ‘шума’:

$ sed ‘/^#/d’ ja_gsd-ud-train.conllu > ja_gsd-ud-train.conllu-clean
$ cut -f2 -d’	‘ ja_gsd-ud-train.conllu-clean > ja_gsd-ud-train.conllu-dict
$ sort -u ja_gsd-ud-train.conllu-dict > ja_gsd-ud-train.conllu-dict_uniq

Открываем файл в редакторе vim, чтобы оценить его вид. Получившийся словарь я преобразовала в dictionary.txt и удалила первую и последнюю пустые строки. Получилось 15326 уникальных слов:

$ wc -l dictionary.txt
15325 dictionary.txt

Чтобы извлечь предложения из файла ja_gsd-ud-test.conllu (именно их мы и будем токенизировать) нам также потребуются регулярные выражения:

$ sed -n ‘/^# text =/p’ ja_gsd-ud-test.conllu > jp-sentences.txt
$ sed -e 's/^# text = //' jp-sentences.txt > sentences.txt

Получилось 558 предложений (команда $ wc -l выдает 557, но $ wc -l — это подсчет перевода строки, поэтому нужно прибавить еще последнее предложение).

С получившимися файлами dictionary.txt и sentences.txt можно работать дальше.

Алгоритм MaxMatch, который я применила (конечно, его можно сделать и в более общем виде, чтобы аргументы можно было вводить из командной строки):

# открываем файл со словарем 
with open('dictionary.txt', 'r') as d:
    lines_dict = d.readlines()
    lines_dict = [line.strip() for line in lines_dict] 

# открываем файл с текстом, в котором хотим выделить токены
with open('sentences.txt', 'r') as s:
    lines_sent = s.readlines()
    lines_sent = [line.strip() for line in lines_sent]

# сортируем словарь по длине слов так, чтобы сначала шли длинные слова
def sortbylength(word):
    return len(word)
def new_sorted(dictionary):
    dict_sorted = sorted(dictionary, key=sortbylength, reverse=True)
    return dict_sorted

dictionary = lines_dict
new_dictionary = new_sorted(dictionary)

‘’’ применяем MaxMatch
проверяем, совпадают ли первые символы строки со словом из словаря; 
если да — отделяем слово и начинаем по-новой с оставшимися символами строки, 
если нет — неизвестный символ назначается словом, отделяется и мы повторяем алгоритм с оставшимися символами;
если длина строки — ноль, то и токенов, соответственно, нет
‘’’
def maxmatch(line):
    if len(line) == 0:
        return '\n'
    try:
        word = next(w for w in new_dictionary if line.startswith(w))
    except StopIteration:
        word = line[0]
    return (word+ ' ' + maxmatch(line[len(word):]))

list = lines_sent

for line in list:
    sentences_tokenized = maxmatch(line)
    print(sentences_tokenized)

В итоге мы получаем файл с предложениями, разбитыми на токены (почистила его фильтром [x for x in sentences_tokenized if x]).

Чтобы иметь возможность вводить предложения из командной строки, в программу нужно импортировать sys, а также добавить следующее:

for line in sys.stdin:
    for word in maxmatch(line):
        print(word)

С помощью команды

$ grep '^[0-9]' ja_gsd-ud-test.conllu | cut -d $'\t'  -f2 > correct_sentences_tokenized.txt

получаем файл с токенами, которые правильно и последовательно выделены из наших тестовых предложений.

В конце концов у меня получилось 2 файла c текстом, токенизированным по предложениям: correct_sentences_tokenized.txt (результат) и sentences_tokenized.txt (гипотеза), которые предстояло сравнить, используя метрику WER, используя предложенный алгоритм. Это долго не удавалось сделать (2 дня), программа вылетала. В конце концов я посчитала значение WER на 30 первых предложениях. Результат такой: 6.52% (вероятно, многие из слов в токенизируемых предложениях отсутствовали в нашем словаре).