Точка знаний НЛП: токенизатор токенизатора

искусственный интеллект TensorFlow
Точка знаний НЛП: токенизатор токенизатора

«Это первый день моего участия в ноябрьском испытании обновлений, ознакомьтесь с подробностями события:Вызов последнего обновления 2021 г.".

1. Зачем нужен токенизатор?

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

Компьютер в любом случае не может понимать человеческий язык, он просто вычисляет, но вычисляя, вы чувствуете, что понимаете человеческий язык.

  • Например: одинарное = 1, двойное = 2, когда компьютер сталкивается с «одинарным» и «двойным», он понимает отношение 2х.
  • Другой пример: похвала = 1, дискредитация = 0, когда компьютер встречает 0,5, он знает, что это «смешанное».
  • Другой пример: Королева={1,1}, Женщина={1,0}, Король={0,1}, он понимает, что "женщина" + "король" = "королева".

Видите ли, когда речь идет о словах, ее нужно понимать через числа.

Таким образом, как преобразовать текст в числа, является самым основным шагом в НЛП.

К счастью, фреймворк TensorFlow предоставляет очень полезный класс Tokenizer, созданный для этой цели.

2. Инструмент сегментации слов Tokenizer

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

Формат текста следующий:

corpus = ["I love cat" , "I love dog" , "I love you too"]

2.1 Создание токенизатора

Если вам нужен объект, вы должны сначала поговорить о нем. Чтобы использовать токенизатор, вам сначала нужно его создать.

from tensorflow.keras.preprocessing.text import Tokenizer

tokenizer = Tokenizer()

2.2 Вписать текст fit_on_texts

можно вызвать токенизаторfit_on_textsметод, чтобы соответствовать тексту.

tokenizer.fit_on_texts(corpus)

После того, как токенизатор съел текстовые данные и адаптировал их, токенизатор изменился с Xiaobai на Hongru, и можно сказать, что он хорошо знает эти тексты.

["I love cat" , "I love dog" , "I love you too"]

  • tokenizer.document_countОн записывает, сколько абзацев текста было обработано.На данный момент значение равно 3, что означает, что обработано 3 абзаца.

  • tokenizer.word_indexСтавим все слова на счет, каждому слову присваивается идентификационный номер, а значение{'cat': 3, 'dog': 4, 'i': 1, 'love': 2, 'too': 6, 'you': 5}. Например, номер кошки — 3, а 3 представляет собой кошку.

  • tokenizer.index_wordОтносительно word_index число первое{1: 'i', 2: 'love', 3: 'cat', 4: 'dog', 5: 'you', 6: 'too'}, номер 1 - это я, я представлен 1.

  • tokenizer.word_docsЗатем подсчитывается количество вхождений каждого слова, и значение в это время равно{'cat': 1, 'dog': 1, 'i': 3, 'love': 3, 'too': 1, 'you': 1}. Например, «i» встречается 3 раза.

Расширенные знания: использование заглавных букв и пунктуация

«Я люблю кота», «я люблю кота», «я люблю кота!», послеfit_on_textsПосле этого результат тот же.

Это показывает, что его обработка игнорирует регистр английских букв и английские знаки препинания.

2.3 Сериализация текста texts_to_sequences

Хотя текст адаптирован выше, он только нумерует и считает слова, а текст не весь превращается в цифры.

В этот момент токенизаторtexts_to_sequencesметод сериализации текста в числа.

input_sequences = tokenizer.texts_to_sequences(corpus)

["I love cat" , "I love dog" , "I love you too"]

После сериализации текстовый список становится числовым списком[[1, 2, 3], [1, 2, 4], [1, 2, 5, 6]].

Расширение знаний: за пределами корпуса OOV

Причина, по которой текст может быть сериализован, заключается в том, что каждое слово имеет номер.

1 2 3 4 5 6
i love cat dog you too

I love you -> 1 2 5

Когда мы сталкиваемся со словами, которых раньше не видели, например, я не люблю кошку. Что нам делать в это время?

И вероятность этого достаточно высока.

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

Давайте сначала посмотрим, что произойдет?

corpus = ["I love cat","I love dog","I love you too"]
tokenizer = Tokenizer()
tokenizer.fit_on_texts(corpus)
# tokenizer.index_word: {1: 'i', 2: 'love', 3: 'cat', 4: 'dog', 5: 'you', 6: 'too'}
input_sequences = tokenizer.texts_to_sequences(["I do not love cat"])
# input_sequences: [[1, 2, 3]]

Судя по результатам, это игнорируется. «Я не люблю кота» и «я люблю кота» заканчиваются одинаково, просто потому, что «делаю» и «не» не записывают.

Однако иногда мы не хотим игнорировать это, что же нам тогда делать?

Это очень просто, просто передайте параметр при создании Tokenizer.oov_token='<OOV>'.

Что означает ООВ? При обработке текста на естественном языке у нас обычно есть словарный запас (словарь), полученный из обучающего набора данных. Конечно, этот тезаурус ограничен. Когда у вас будет новый набор данных в будущем, в этом наборе данных будут некоторые слова, которых нет в вашем существующем словаре, мы говорим, что эти слова находятся вне словаря, или сокращенно OOV.

Следовательно, покаTokenizer(oov_token='<OOV>')Токенизатор зарезервирует номер для пометки внеклассной лексики.

Посмотрим, что будет снова?

corpus = ["I love cat","I love dog","I love you too"]
tokenizer = Tokenizer(oov_token='<OOV>')
tokenizer.fit_on_texts(corpus)
# tokenizer.index_word: {1:'<OOV>',2:'i',3:'love',4:'cat',5:'dog',6:'you',7:'too'}
input_sequences = tokenizer.texts_to_sequences(["I do not love cat"])
# input_sequences: [[2, 1, 1, 3, 4]]

Из результатов видно, что слову надкласса присваивается номер 1, и, наконец, «Я не люблю кошку» сериализуется как 2, 1, 1, 3, 4.

2.4 Последовательность pad_sequences

["I love cat" , "I love dog" , "I love you too"]был сериализован в[[1, 2, 3], [1, 2, 4], [1, 2, 5, 6]].

Шаг превращения текста в числа вроде бы сделан, но на самом деле до него еще один шаг.

Посмотрите на картинку ниже.В ней две пачки карандашей.Как вы думаете,какая из них удобнее для хранения или транспортировки?

铅笔.jpg

Исходя из здравого смысла жизни, это должна быть последовательность B, которая более удобна в обращении. Поскольку он имеет одинаковую длину, вы можете игнорировать разницу, 50 или 50 000, просто простую множественную связь.

Да, компьютеры такие же, как и вы,[[1, 2, 3], [1, 2, 4], [1, 2, 5, 6]]Эти числа также бывают длинными и короткими, и он также надеется, что вы сможете объединить их в одну длину.

TensorFlow уже подумал об этом, он предоставляетpad_sequencesметод, специально для этого.

from tensorflow.keras.preprocessing.sequence import pad_sequences

sequences = [[1, 2, 3], [1, 2, 4], [1, 2, 5, 6]]
sequences = pad_sequences(sequences)
# sequences:[[0, 1, 2, 3],[0, 1, 2, 4],[1, 2, 5, 6]]

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

Последовательность одинаковой длины — это материал, в котором нуждается НЛП.

Фокус: мы будем видеть такой код в различных случаяхvocab_size = len(tokenizer.word_index) + 1, общее количество слов = все слова в тексте + 1, эта 1 на самом деле является 0, используемым для заполнения, в наборе данных нет такого слова, его цель — восполнить длину. обращать внимание<OOV>Это реальное слово, и оно представляет слово суперкласса.

Расширенные знания: больше пользовательских заливок

Возможны разные сценарии обработки заполнения данных.

Выше сказано, что передняя часть заполнена 0. На самом деле иногда также надеются, что задняя часть заполнена 0.

sequences=[[1,2,3],[1,2,4],[1,2,5,6]]
sequences=pad_sequences(sequences, padding="post")
# sequences:[[1, 2, 3, 0],[1, 2, 4, 0],[1, 2, 5, 6]]

Параметр padding — это тип заполнения,padding="post"За ним следует 0. Ведущий 0padding="pre", pre по умолчанию.

Также есть сцена, которая обрезается до фиксированной длины, что также очень распространено.

Например, посмотрите на следующие последовательности:

[[2,3],[1,2],[3,2,1],[1,2,5,6,7,8,9,9,9,1]]

Выше есть 4 набора данных, и их длины равны 2, 2, 3 и 10 соответственно. В это время, если последовательность заполнена, все данные будут заполнены до длины 10.

  • [2, 3, 0, 0, 0, 0, 0, 0, 0, 0]
  • [1, 2, 0, 0, 0, 0, 0, 0, 0, 0]
  • [3, 2, 1, 0, 0, 0, 0, 0, 0, 0]
  • [1, 2, 5, 6, 7, 8, 9, 9, 9, 1]

На самом деле в этом нет необходимости. Потому что общие данные не могут быть избыточными ради отдельных данных.

Поэтому набивку необходимо обрезать.

Мы предпочитаем дополнять последовательность длиной 5, которая может сбалансировать интересы всех сторон.

код показывает, как показано ниже:

sequences=[[2,3],[1,2],[3,2,1],[1,2,5,6,7,8,9,9,9,1]]
sequences=pad_sequences(sequences, maxlen = 5, padding='post', truncating='post')
# [[2,3,0,0,0],[1,2,0,0,0],[3,2,1,0,0],[1,2,5,6,7]]

Добавлено 2 параметра, одинmaxlen = 5, — это максимально допустимая длина последовательности. Другой параметрtruncating='post', указывая на то, что он усечен сзади (передняя часть пред).

Этот код означает, что какая бы последовательность ни пришла, я должен сделать данные длиной 5. Если их будет недостаточно, то они будут заполнены 0, а лишнее будет выброшено.

На самом деле, этот метод является наиболее часто используемым на практике. Поскольку мы можем контролировать формат входной последовательности обучающих данных, мы также обучаем модель с его помощью. Но когда дело доходит до прогнозирования, формат ввода странный. Например, мы использовали данные длиной 100 для обучения модели. При использовании этой модели для прогнозирования пользователь вводит данные длиной 10 000, и модель не может их распознать. Поэтому, независимо от того, теряет ли пользователь 10 000 длин или 1 длину, ее необходимо преобразовать в длину во время обучения.

3. Сегментация китайских слов

В английском языке есть пробелы для разделения каждого слова.

I love cat.

В нем 3 слова: я, любовь, кот.

Однако в китайском нет знака для различения слов.

Я люблю кошек.

Сколько слов?

Это раздражительно.

При выполнении НЛП в качестве базовой единицы должен использоваться словарный запас.

Словарный запас китайского языка очень велик, и обычно используются сторонние сервисы.

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

3.1 Как установить и использовать jieba

Код совместим с Python 2/3

  • Полностью автоматическая установка:easy_install jiebaилиpip install jieba / pip3 install jieba
  • Полуавтоматическая установка: сначала загрузитеpypi.python.org/pypi/jieba/, запустить после декомпрессииpython setup.py install
  • Ручная установка:Загрузите файл кодаПоместите каталог jieba в текущий каталог или каталог сайтов-пакетов.
  • пройти черезimport jiebaЦитировать

Следите за «Пекинским университетом» ниже:

import jieba
sentence = " ".join(jieba.cut("欢迎来北京大学餐厅")) 
print(sentence) # 欢迎 来 北京大学 餐厅
sentence2 = " ".join(jieba.cut("欢迎来北京大学生志愿者中心")) 
print(sentence2) # 欢迎 来 北京 大学生 志愿者 中心

Обработка естественного языка китайского языка должна сначала разделить словарный запас, что является единственным отличием.