Эта статья представляет собой заметку для изучения из книги Учителя Хэ Хана «Введение в обработку естественного языка».
Поскольку сегментация по словарю не может устранить неоднозначность, например, для данных результатов сегментации «товары и услуги» и «товары и услуги», сегментация по словарю не знает, что более разумно.
Одним из основных направлений статистической обработки естественного языка является использование статистических методов для моделирования языка.
языковое моделирование
Языковая модель (LM)Это относится к математической абстракции языковых явлений.
как приговор, языковая модель заключается в вычислении вероятности появления предложениямодель.
Вероятностное распределение — это статистика аннотированного вручную корпуса.
Представить предложение в виде списка слов, который определяет языковую модель:
в(Начало предложения, ),(Конец предложения, ).
Например «товары и услуги», вероятность оценивается следующим образом:
Мы используем оценку максимального правдоподобия (MLE) для расчета каждой апостериорной вероятности:
ввыражатьсчитать.
У этой языковой модели есть две проблемы:
- мало данныхБолее длинные предложения труднее представить, что приводит кравно 0
- вычислительно дорогойЧем больше k, тем большечем больше
Цепи Маркова и биграммы
Используйте допущение Маркова для упрощения языковой модели: существует последовательность событий на заданной временной шкале, если предположить, что вероятность каждого события зависит только от предыдущего события, тогда причинно-следственная цепочка, образованная этой последовательностью событий, называетсяЦепь Маркова(Цепь Маркова).
В языковой модели первоесобытие относится кв видеКаждое слово появляется, и цепь Маркова предполагает, что вероятность появления каждого слова зависит только от предыдущего слова:
n-грамм
Используя аналогичные идеи бинарной грамматики, мы можем получитьn-грамм(н-грамм) Определение: Вероятность каждого слова зависит только от n-1 слов, предшествующих этому слову.
Специальное число n=1 называется униграммой, n=3 — триграммой.
Разреженные данные и стратегии сглаживания
Чем больше n модели n-грамм, тем серьезнее проблема разреженности данных. Учитывая, что n-граммы более низкого порядка богаче, n-граммы более высокого порядка сглаживаются с использованием n-грамм более низкого порядка. Так называемое сглаживание: полилиния частоты n-граммы сглаживается в кривую.
Например, мы не хотим, чтобы частота биграммы «товарная валюта» внезапно упала до нуля, мы можем сгладить ее частотностью унарного синтаксиса «товар» и/или «валюта». Ниже приведен один из простейших методов линейной интерполяции (Linear Interpolation), определяющий вероятность бинарной грамматики:
Точно так же унарная линейная интерполяция:
вкоэффициент сглаживания,это общее количество слов в корпусе.
тренироваться
Корпус
Языковая модель — это всего лишь скелет функции, а параметры функции должны быть получены статистически на корпусе.
- People's Daily Corpus PKU
- Microsoft Research Asia Corpus MSR
- Корпус сегментации слов традиционного китайского языка
тренироваться
тренироваться(обучение) относится к процессу оценки параметров модели для заданного набора образцов (набора данных, называемого обучающим набором для обучения).
Для модели биграмм обучение относится к подсчету частоты биграммы и униграммы, С помощью стратегии оценки максимального правдоподобия и сглаживания оценивается распределение вероятностей любого предложения, то есть получается языковая модель.
Код
Предположим, что word_count — это объект collections.Counter, содержащий статистику слов (форма слово: частота слов)
# TOKENS是分好词的文本列表
# 单个词频统计
words_count = Counter(TOKENS)
# 计算相邻的两个词词频
_2_gram_words = [
TOKENS[i] + TOKENS[i+1] for i in range(len(TOKENS)-1)
]
_2_gram_word_counts = Counter(_2_gram_words)
def get_gram_count(word, wc):
"""
获取词在wc中词频
:param word 要统计的单词
:param wc Counter类型的词频
"""
if word in wc:
return word_count[word]
else:
# 返回最小的词频
return wc.most_common()[-1][-1]
def two_gram_model(sentence):
"""
2-gram 模型计算
:param sentence 话术
"""
# cut为分词函数,得到一个分好的词列表
tokens = cut(sentence)
probability = 1
# 根据上面的公式计算话术概率
for i in range(1, len(tokens)):
word = tokens[i]
pre_word = tokens[i-1]
_two_gram_c = get_gram_count(pre_word + word, _2_gram_word_counts)
_one_gram_c = get_gram_count(pre_word, words_count)
pro = _two_gram_c / _one_gram_c
probability *= pro
return probability
Пример
Возьмите следующие три текста в качестве примера.
текст | Список причастий |
---|---|
Товары и услуги | [товары и услуги] |
Товары и дешевые кимоно | [Товары, Кимоно, Хорошее качество и низкая цена] |
Услуги и валюта | [Сервис и валюта] |
Начните с «start##start» и закончите «last##end»
Результаты обучения унарной грамматике
слово | часть речи | частота |
---|---|---|
и | n | 2 |
кимоно | n | 1 |
товар | n | 2 |
Служить | n | 2 |
валюта | n | 1 |
Недорогой | n | 1 |
BOS | begin | 3 |
EOS | end | 3 |
Результаты обучения бинарной грамматике
Разделяйте два слова в биграмме знаком @.
слово | частота |
---|---|
и обслуживание | 1 |
и @валюта | 1 |
Кимоно @ Хорошее и дешевое | 1 |
Товары @ и | 1 |
Товары @ Кимоно | 1 |
Сервис @ и | 1 |
BOS@Товары | 2 |
БОС@Сервис | 1 |
Сервис @EOS | 1 |
Валюта@EOS | 1 |
Недорогой @EOS | 1 |
Симуляционный расчет вероятностей «товаров и услуг» с использованием биграмм
предсказывать
Прогнозирование относится к процессу использования модели для вывода образца (предложения), а в задаче сегментации китайских слов модель используется для вывода последовательности сегментации слова.
сеть слов
Слово «сеть» относится к сетевой структуре, состоящей из всех униграмм в предложении, что является концепцией инженерии HanLP. Например, в предложении «товары и услуги» слова с одинаковой начальной позицией (смещением) записываются одной строкой, и получается слово нетто:
offset | Причастие |
---|---|
0 | BOS |
1 | [товар] |
2 | |
3 | [и, кимоно] |
4 | [Служить] |
5 | [обязанности] |
6 | EOS |
Среди них «задача» в строке 5 — это слово, не существующее в унарной грамматике, это однословное слово, добавленное для обеспечения связи сети слов.
- Слово net должно гарантировать, что все пути от начальной точки соединены с конечной точкой.
сеть словДлина линиислово сВсе слова строки связаны друг с другом, образуя граф слов.
Расчет расстояния между узлами
Вероятность двоичной грамматики использует MLE, дополненный стратегией сглаживания, для получения следующих эмпирических формул, часто используемых при сегментации китайских слов:
в,два разных коэффициента сглаживания.
учитывая несколькоНепрерывное умножение с плавающей запятой между потерями памяти (равно 0), поэтому инженеры частоОтрицательный логарифм вероятности, который преобразует умножение с плавающей запятой в сложение между отрицательными логарифмами:
Граф слов на приведенном выше рисунке вычисляет расстояние следующим образом, и кратчайший путь является оптимальным решением:
Вычисление кратчайших путей: алгоритм Вибита на графах слов
Шаги алгоритма Витерби:
- вперед: пройти узел от начальной точки спереди назад, обновить минимальную стоимость от начальной точки до узла и указателя-предшественника
- назад: Начните с конечной точки и проведите указатель предшественника назад вперед, чтобы получить кратчайший путь.
def viterbi(nodes):
"""
维比特分词计算
:param nodes 计算的分词词网
"""
# 前向遍历,计算路径
for i in range(len(nodes) - 1):
# 遍历当前offset
for node in nodes[i]:
# 遍历当前节点的下一个offset列表,更新前驱指针
for to in nodes[i + len(node.realWord)]:
# 根据距离公式计算节点距离,并维护最短路径上的前驱指针from
to.updateFrom(node)
# 后向遍历,获取路径
path = []
# 从终点回溯
f = nodes[len(nodes) - 1].getFirst()
while f:
path.insert(0, f)
# 根据前驱指针from回溯
f = f.getFrom()
# 返回最短路径分词结果
return [v.realWord for v in path]
/**
* 更新weight最小的前驱词
* @param from 前面的词
*/
public void updateFrom(Vertex from) {
double weight = from.weight + calculateWeight(from, this);
if (this.from == null || this.weight > weight) {
this.from = from;
this.weight = weight;
}
}
/**
* 从一个词到另一个词的词的花费
*
* @param from 前面的词
* @param to 后面的词
* @return 分数
*/
public static double calculateWeight(Vertex from, Vertex to) {
int frequency = from.getAttribute().totalFrequency;
if (frequency == 0) {
frequency = 1; // 防止发生除零错误
}
int nTwoWordsFreq = CoreBiGramTableDictionary.getBiFrequency(from.wordID, to.wordID);
// 上面的计算公式
double value = -Math.log(dSmoothingPara * frequency / (MAX_FREQUENCY) + (1 - dSmoothingPara) * ((1 - dTemp) * nTwoWordsFreq / frequency + dTemp));
if (value < 0.0) {
value = -value;
}
return value;
}
Суммировать
- Модель n-грамм начинается с беглости продолжений слов, оценивает двоичные продолжения в полностью сегментированной сети слов, а затем использует алгоритм Vibit для решения пути с наибольшей вероятностью вероятности.
- Проблема OOV: OOV больше не может входить в сеть слов на начальном этапе полной сегментации, поэтому отзыв OOV по-прежнему является недостатком модели n-грамм.