[Перевод] Учебное пособие по маркировке частей речи с помощью библиотеки глубокого обучения Keras

искусственный интеллект глубокое обучение Программа перевода самородков Python Keras
[Перевод] Учебное пособие по маркировке частей речи с помощью библиотеки глубокого обучения Keras

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

существуетобработка естественного языка, определение части речи — хорошо известная задача. Это относится к классификации слов по частям речи (также называемым частями речи или категориями частей речи). Это контролируемый метод обучения.

Искусственные нейронные сетиОн был успешно применен для маркировки частей речи с отличной производительностью. Мы сосредоточимся на многослойных персептронных сетях, очень популярной сетевой структуре, которая считается передовой для решения задач маркировки частей речи. (Примечание переводчика: для проблем с тегами частей речи RNN дает лучшие результаты)

Давайте применим это на практике!

В этой статье вы получите краткое руководство о том, как реализовать простой многослойный персептрон в Keras и обучить его на аннотированном корпусе.

обеспечить повторяемость

Чтобы гарантировать воспроизводимость наших экспериментов, нам нужно установить случайное начальное число:

import numpy as np

CUSTOM_SEED = 42
np.random.seed(CUSTOM_SEED)

Получить аннотированный корпус

Penn Treebankпредставляет собой корпус тегов частей речи. В библиотеке Python есть пример[NLTK](https://github.com/nltk/nltk)Содержит корпуса, которые можно использовать для обучения и тестирования определенных моделей обработки естественного языка (моделей НЛП).

Сначала мы загружаем аннотированный корпус:

import nltk

nltk.download('treebank')

Затем мы загружаем отмеченные предложения.

from nltk.corpus import treebank

sentences = treebank.tagged_sents(tagset='universal')

Затем давайте выберем предложение наугад и посмотрим:

import random

print(random.choice(sentences))

Это список кортежей(term, tag).

[('Mr.', 'NOUN'), ('Otero', 'NOUN'), (',', '.'), ('who', 'PRON'), ('apparently', 'ADV'), ('has', 'VERB'), ('an', 'DET'), ('unpublished', 'ADJ'), ('number', 'NOUN'), (',', '.'), ('also', 'ADV'), ('could', 'VERB'), ("n't", 'ADV'), ('be', 'VERB'), ('reached', 'VERB'), ('.', '.')]

Это проблема множественной классификации с более чем сорока различными классами. Маркировка частей речи в корпусе Treebank — хорошо известная проблема, и мы ожидаем, что точность модели превысит 95 %.

tags = set([
    tag for sentence in treebank.tagged_sents() 
    for _, tag in sentence
])
print('nb_tags: %sntags: %s' % (len(tags), tags))

производит:

46
{'IN', 'VBZ', '.', 'RP', 'DT', 'VB', 'RBR', 'CC', '#', ',', 'VBP', 'WP$', 'PRP', 'JJ', 
'RBS', 'LS', 'PRP$', 'WRB', 'JJS', '``', 'EX', 'POS', 'WP', 'VBN', '-LRB-', '-RRB-', 
'FW', 'MD', 'VBG', 'TO', '$', 'NNS', 'NNPS', "''", 'VBD', 'JJR', ':', 'PDT', 'SYM', 
'NNP', 'CD', 'RB', 'WDT', 'UH', 'NN', '-NONE-'}

### Предварительная обработка набора данных для контролируемого обучения

Мы делим помеченные предложения на 3 набора данных:

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

Мы используем около 60 % помеченных предложений для обучения, 20 % в качестве проверочного набора и 20 % для оценки нашей модели.

train_test_cutoff = int(.80 * len(sentences)) 
training_sentences = sentences[:train_test_cutoff]
testing_sentences = sentences[train_test_cutoff:]

train_val_cutoff = int(.25 * len(training_sentences))
validation_sentences = training_sentences[:train_val_cutoff]
training_sentences = training_sentences[train_val_cutoff:]

разработка функций

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

def add_basic_features(sentence_terms, index):
    """ 计算基本的单词特征
        :param sentence_terms: [w1, w2, ...] 
        :type sentence_terms: list
        :param index: the index of the word 
        :type index: int
        :return: dict containing features
        :rtype: dict
    """
    term = sentence_terms[index]
    return {
        'nb_terms': len(sentence_terms),
        'term': term,
        'is_first': index == 0,
        'is_last': index == len(sentence_terms) - 1,
        'is_capitalized': term[0].upper() == term[0],
        'is_all_caps': term.upper() == term,
        'is_all_lower': term.lower() == term,
        'prefix-1': term[0],
        'prefix-2': term[:2],
        'prefix-3': term[:3],
        'suffix-1': term[-1],
        'suffix-2': term[-2:],
        'suffix-3': term[-3:],
        'prev_word': '' if index == 0 else sentence_terms[index - 1],
        'next_word': '' if index == len(sentence_terms) - 1 else sentence_terms[index + 1]
    }

Мы сопоставляем список предложений со списком словарей функций.

def untag(tagged_sentence):
    """ 
    删除每个标记词语的标签。

:param tagged_sentence: 已标注的句子
    :type tagged_sentence: list
    :return: a list of tags
    :rtype: list of strings
    """
    return [w for w, _ in tagged_sentence]

def transform_to_dataset(tagged_sentences):
    """
    将标注的句子切分为 X 和 y 以及添加一些基本特征

:param tagged_sentences: 已标注的句子列表
    :param tagged_sentences: 元组列表之列表 (term_i, tag_i)
    :return: 
    """
    X, y = [], []

for pos_tags in tagged_sentences:
        for index, (term, class_) in enumerate(pos_tags):
            # Add basic NLP features for each sentence term
            X.append(add_basic_features(untag(pos_tags), index))
            y.append(class_)
    return X, y

Для обучения, проверки и тестовых предложений мы разделяем атрибуты на X (входные переменные) и y (выходные переменные).

X_train, y_train = transform_to_dataset(training_sentences)
X_test, y_test = transform_to_dataset(testing_sentences)
X_val, y_val = transform_to_dataset(validation_sentences)

Кодирование функций

Наша нейронная сеть принимает векторы в качестве входных данных, поэтому нам нужно преобразовать функции нашего словаря в векторы.sklearnвстроенные функции[DictVectorizer](http://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.DictVectorizer.html)Предоставляет очень простой способ выполнения векторных преобразований.

from sklearn.feature_extraction import DictVectorizer

# 用我们的特征集拟合字典向量生成器
dict_vectorizer = DictVectorizer(sparse=False)
dict_vectorizer.fit(X_train + X_test + X_val)

# 将字典特征转换为向量
X_train = dict_vectorizer.transform(X_train)
X_test = dict_vectorizer.transform(X_test)
X_val = dict_vectorizer.transform(X_val)

Наш вектор y должен быть закодирован. Выходная переменная содержит 49 различных строковых значений, закодированных как целые числа.

from sklearn.preprocessing import LabelEncoder

# 用类别列表训练标签编码器
label_encoder = LabelEncoder()
label_encoder.fit(y_train + y_test + y_val)

# 将类别值编码成整数
y_train = label_encoder.transform(y_train)
y_test = label_encoder.transform(y_test)
y_val = label_encoder.transform(y_val)

Затем нам нужно преобразовать эти закодированные значения в фиктивные переменные (горячее кодирование).

# 将整数转换为虚拟变量(独热编码)
from keras.utils import np_utils

y_train = np_utils.to_categorical(y_train)
y_test = np_utils.to_categorical(y_test)
y_val = np_utils.to_categorical(y_val)

Построить модель Кераса

[Keras](https://github.com/fchollet/keras/)представляет собой высокоуровневую структуру для проектирования и запуска нейронных сетей с несколькими бэкэндами, такими как[TensorFlow](https://github.com/tensorflow/tensorflow/), [Theano](https://github.com/Theano/Theano)а также[CNTK](https://github.com/Microsoft/CNTK).

Мы хотим создать базовую нейронную сеть: многослойный персептрон. Этот линейный стек может быть достигнут последовательным (Sequential) модель легко сделать. Модель будет содержать входной слой, скрытый слой и выходной слой. Чтобы преодолеть переоснащение, мы используем регуляризацию отсева. Мы устанавливаем скорость отключения 20%, что означает случайное отключение входных нейронов с вероятностью 20% каждый раз, когда параметры обновляются во время обучения.

Используем скрытый слойRectified Linear Units(ReLU) функции активации, поскольку они являются простейшими доступными нелинейными функциями активации.

Для задач множественной классификации мы хотим преобразовать выходные данные нейронов в вероятности, что можно сделать с помощьюsoftmaxфункция завершена. Мы решили использовать мультиклассовую кросс-энтропию (categorical cross-entropy) функция потерь. Наконец мы выбираемAdam optimizerПотому что кажется, что он очень подходит для задач классификации.

from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation

def build_model(input_dim, hidden_neurons, output_dim):
    """
    构建、编译以及返回一个用于拟合/预测的 Keras 模型。
    """
    model = Sequential([
        Dense(hidden_neurons, input_dim=input_dim),
        Activation('relu'),
        Dropout(0.2),
        Dense(hidden_neurons),
        Activation('relu'),
        Dropout(0.2),
        Dense(output_dim, activation='softmax')
    ])

model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
    return model

Создайте оболочку между Keras API и Scikit-Learn.

[Keras](https://github.com/fchollet/keras/)обеспечивает[KerasClassifier](https://keras.io/scikit-learn-api/)обертка. он достигаетScikit-LearnИнтерфейс классификатора.

Все параметры модели определяются следующим образом. Нам нужно предоставить функцию, которая возвращает структуру нейронной сети (build_fn). Выбор количества скрытых нейронов и размера партии очень произвольный. Мы устанавливаем количество итераций равным 5, потому что по мере увеличения количества итераций многослойный персептрон начинает переобучать (т. е. использоватьDropout Regularization).

from keras.wrappers.scikit_learn import KerasClassifier

model_params = {
    'build_fn': build_model,
    'input_dim': X_train.shape[1],
    'hidden_neurons': 512,
    'output_dim': y_train.shape[1],
    'epochs': 5,
    'batch_size': 256,
    'verbose': 1,
    'validation_data': (X_val, y_val),
    'shuffle': True
}

clf = KerasClassifier(**model_params)

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

Наконец, мы обучаем многослойный персептрон на обучающем наборе.

hist = clf.fit(X_train, y_train)

С помощью истории обратных вызовов мы можем визуализировать модельlog lossиaccuracyизменение с течением времени.

import matplotlib.pyplot as plt

def plot_model_performance(train_loss, train_acc, train_val_loss, train_val_acc):
    """  绘制模型损失和准确度随时间变化的曲线  """

    blue= '#34495E'
    green = '#2ECC71'
    orange = '#E23B13'

    # 绘制模型损失曲线
    fig, (ax1, ax2) = plt.subplots(2, figsize=(10, 8))
    ax1.plot(range(1, len(train_loss) + 1), train_loss, blue, linewidth=5, label='training')
    ax1.plot(range(1, len(train_val_loss) + 1), train_val_loss, green, linewidth=5, label='validation')
    ax1.set_xlabel('# epoch')
    ax1.set_ylabel('loss')
    ax1.tick_params('y')
    ax1.legend(loc='upper right', shadow=False)
    ax1.set_title('Model loss through #epochs', color=orange, fontweight='bold')

    # 绘制模型准确度曲线
    ax2.plot(range(1, len(train_acc) + 1), train_acc, blue, linewidth=5, label='training')
    ax2.plot(range(1, len(train_val_acc) + 1), train_val_acc, green, linewidth=5, label='validation')
    ax2.set_xlabel('# epoch')
    ax2.set_ylabel('accuracy')
    ax2.tick_params('y')
    ax2.legend(loc='lower right', shadow=False)
    ax2.set_title('Model accuracy through #epochs', color=orange, fontweight='bold')

Затем посмотрите на производительность модели:

plot_model_performance(
    train_loss=hist.history.get('loss', []),
    train_acc=hist.history.get('acc', []),
    train_val_loss=hist.history.get('val_loss', []),
    train_val_acc=hist.history.get('val_acc', [])
)

Производительность модели как функция количества итераций.

После двух итераций мы обнаружили, что модель переоснащается.

Оценка многослойных персептронов

Поскольку наша модель уже обучена, мы можем оценить ее напрямую:

score = clf.score(X_test, y_test)
print(score)

[Out] 0.95816

Наша точность на тестовом наборе близка к 96%, что довольно впечатляет, если посмотреть на базовые функции, которые мы добавили в модель. Помните, что 100% точность невозможна даже для комментаторов-людей. По нашим оценкам, точность маркировки частей речи человека составляет около 98%.

визуализация модели

from keras.utils import plot_model

plot_model(clf.model, to_file='model.png', show_shapes=True)

Сохраните модель Кераса

Сохранить модель Keras легко, потому что библиотека Keras предоставляет локализованный метод:

clf.model.save('/tmp/keras_mlp.h5')

Структура модели, веса и конфигурация обучения (функция потерь, оптимизатор) сохраняются.

ресурс

  • Keras: библиотека глубокого обучения Python:[doc]
  • Адам: Метод стохастической оптимизации:[paper]
  • Improving neural networks by preventing co-adaptation of feature detectors: [paper]

В этой статье вы узнаете, как использовать библиотеку Keras для определения и оценки точности нейронных сетей для мультиклассификации. Код здесь: [.py|.ipynb].


Программа перевода самородковэто сообщество, которое переводит высококачественные технические статьи из Интернета сНаггетсДелитесь статьями на английском языке на . Охват контентаAndroid,iOS,внешний интерфейс,задняя часть,блокчейн,продукт,дизайн,искусственный интеллектЕсли вы хотите видеть более качественные переводы, пожалуйста, продолжайте обращать вниманиеПрограмма перевода самородков,официальный Вейбо,Знай колонку.