Условные случайные поля для распознавания именованных объектов

машинное обучение искусственный интеллект глубокое обучение NLP
Условные случайные поля для распознавания именованных объектов

предисловие

Многие люди называют НЛП жемчужиной искусственного интеллекта, что свидетельствует о его важности в области ИИ, а распознавание именованных сущностей (NER) всегда было горячей точкой исследований в области НЛП, поэтому эта задача является обязательной для НЛП. .

Ранние реализации NER в основном основывались на словарях и правилах, а затем на традиционном машинном обучении, таком как HMM, MEMM и CRF. Затем развитие глубокого обучения осуществляется с помощью CRF в сочетании с рекуррентной нейронной сетью или сверточной нейронной сетью. Самые последние из них основаны на моделях внимания и трансферном обучении.

На самом деле основным основным алгоритмом NER является условное случайное поле (CRF), включая более поздние модели глубокого обучения и внимания, которые необходимо использовать в сочетании с CRF, поэтому в этой статье рассматривается, как CRF реализует распознавание именованных объектов.

Об условных случайных полях

CRF - это условное случайное поле, которое представляет собой модель условного распределения вероятностей другого набора выходных случайных величин при условии заданного набора входных случайных величин. Это модель неориентированного графа дискриминантной вероятности. Поскольку это дискриминант, то есть моделирование условного распределения вероятностей.

В НЛП CRF - это вероятностная модель для маркировки и разделения данных последовательности.Согласно определению CRF, относительной последовательности дается последовательность наблюдений X и выходная последовательность Y, а затем модель описывается путем определения условной вероятности P (Y | X) .

Подробности смотрите в предыдущей статье »Условные случайные поля (CRF) для машинного обучения".

корпус NER

Для удобства непосредственного использования корпуса распознавания именованных сущностей, предоставленного nltk, загрузите его следующим образом.

>>> import nltk
>>> nltk.download('conll2002')
[nltk_data] Downloading package conll2002 to
[nltk_data]     C:\Users\84958\AppData\Roaming\nltk_data...
[nltk_data]   Unzipping corpora\conll2002.zip.

читать корпус,

train_sents = list(nltk.corpus.conll2002.iob_sents('esp.train'))
test_sents = list(nltk.corpus.conll2002.iob_sents('esp.testb'))

Характеристика Функция

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

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

def word2features(sent, i):
    word = sent[i][0]
    postag = sent[i][1]
    features = [
        'bias',
        'word.lower=' + word.lower(),
        'word[-3:]=' + word[-3:],
        'word[-2:]=' + word[-2:],
        'word.isupper=%s' % word.isupper(),
        'word.istitle=%s' % word.istitle(),
        'word.isdigit=%s' % word.isdigit(),
        'postag=' + postag,
        'postag[:2]=' + postag[:2],
    ]
    if i > 0:
        word1 = sent[i - 1][0]
        postag1 = sent[i - 1][1]
        features.extend([
            '-1:word.lower=' + word1.lower(),
            '-1:word.istitle=%s' % word1.istitle(),
            '-1:word.isupper=%s' % word1.isupper(),
            '-1:postag=' + postag1,
            '-1:postag[:2]=' + postag1[:2],
        ])
    else:
        features.append('BOS')
    if i < len(sent) - 1:
        word1 = sent[i + 1][0]
        postag1 = sent[i + 1][1]
        features.extend([
            '+1:word.lower=' + word1.lower(),
            '+1:word.istitle=%s' % word1.istitle(),
            '+1:word.isupper=%s' % word1.isupper(),
            '+1:postag=' + postag1,
            '+1:postag[:2]=' + postag1[:2],
        ])
    else:
        features.append('EOS')
    return features

Обучите модель

Затем вы можете приступить к созданию тренера для обучения, преобразовать каждое предложение корпуса в список функций и меток, затем установить соответствующие параметры тренера и добавить образцы в тренер, чтобы начать обучение. в конечном итоге сохранит модель вmodel_pathсередина.

def train():
    X_train = [sent2features(s) for s in train_sents]
    y_train = [sent2labels(s) for s in train_sents]

    trainer = pycrfsuite.Trainer(verbose=False)
    trainer.set_params({
        'c1': 1.0,  
        'c2': 1e-3, 
        'max_iterations': 50, 
        'feature.possible_transitions': True
    })

    for xseq, yseq in zip(X_train, y_train):
        trainer.append(xseq, yseq)

    trainer.train(model_path)

предсказывать

Создайте Tagger и загрузите модель, вы можете выбрать предложение в тестовом наборе для тега.

def predict():
    tagger = pycrfsuite.Tagger()
    tagger.open(model_path)
    example_sent = test_sents[3]
    print(' '.join(sent2tokens(example_sent)), end='\n\n')
    print("Predicted:", ' '.join(tagger.tag(sent2features(example_sent))))
    print("Correct:  ", ' '.join(sent2labels(example_sent)))

Например, следующие результаты предсказания.

García Aranda presentó a la prensa el sistema Amadeus , que utilizan la mayor parte de las agencias de viajes españolas para reservar billetes de avión o tren , así como plazas de hotel , y que ahora pueden utilizar también los usuarios finales a través de Internet .

Predicted: B-PER I-PER O O O O O O B-MISC O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B-MISC O
Correct:   B-PER I-PER O O O O O O B-MISC O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B-MISC O

оценивать

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

def bio_classification_report(y_true, y_pred):
    lb = LabelBinarizer()
    y_true_combined = lb.fit_transform(list(chain.from_iterable(y_true)))
    y_pred_combined = lb.transform(list(chain.from_iterable(y_pred)))

    tagset = set(lb.classes_) - {'O'}
    tagset = sorted(tagset, key=lambda tag: tag.split('-', 1)[::-1])
    class_indices = {cls: idx for idx, cls in enumerate(lb.classes_)}

    return classification_report(
        y_true_combined,
        y_pred_combined,
        labels=[class_indices[cls] for cls in tagset],
        target_names=tagset,
    )


def evaluate():
    tagger = pycrfsuite.Tagger()
    tagger.open(model_path)
    X_test = [sent2features(s) for s in test_sents]
    y_test = [sent2labels(s) for s in test_sents]
    y_pred = [tagger.tag(xseq) for xseq in X_test]
    print(bio_classification_report(y_test, y_pred))

Например, следующие результаты.

             precision    recall  f1-score   support

      B-LOC       0.78      0.75      0.76      1084
      I-LOC       0.66      0.60      0.63       325
     B-MISC       0.69      0.47      0.56       339
     I-MISC       0.61      0.49      0.54       557
      B-ORG       0.79      0.81      0.80      1400
      I-ORG       0.80      0.79      0.80      1104
      B-PER       0.82      0.87      0.84       735
      I-PER       0.87      0.93      0.90       634

avg / total       0.77      0.76      0.76      6178

github

https://github.com/sea-boat/nlp_lab/blob/master/crf_ner/crf_ner.py

Наконец

crf является более гибким в дизайне признаков, чем hmm, и crf является неориентированным графом.Например, ориентированный граф hmm может извлекать больше признаков, поэтому общий эффект лучше, чем hmm, но он также имеет свои недостатки, сложность Высокая, большое количество функциональных возможностей делает обучение дорогим.

------------- Рекомендуем прочитать ------------

Резюме моей статьи за 2017 год — машинное обучение

Резюме моих статей за 2017 год — Java и промежуточное ПО

Резюме моих статей 2017 года — глубокое обучение

Краткое изложение моих статей за 2017 год — исходный код JDK

Резюме моей статьи за 2017 год — обработка естественного языка

Резюме моих статей 2017 года — Java Concurrency

------------------рекламное время----------------

Поговори со мной, задай мне вопросы:

这里写图片描述

Меню официальной учетной записи было разделено на «распределенное», «машинное обучение», «глубокое обучение», «НЛП», «глубина Java», «ядро параллелизма Java», «исходный код JDK», «ядро Tomcat», и т.д. Там может быть один стиль, чтобы удовлетворить ваш аппетит.

Зачем писать «Анализ проектирования ядра Tomcat»

Добро пожаловать, чтобы следовать:

这里写图片描述