Основы НЛП - понимание китайской семантики: анализ настроений в обзорах фильмов Douban

TensorFlow
Основы НЛП - понимание китайской семантики: анализ настроений в обзорах фильмов Douban

Мало знаний, большой вызов! Эта статья участвует в "Необходимые знания для программистов«Творческая деятельность.

1. NLP

NLP (обработка естественного языка) относится к обработке естественного языка, и его цель — позволить компьютерам понимать человеческую речь.

Ниже приведен результат окончательного вывода ИИ после того, как я обучил 20 000 обзоров фильмов Douban и случайным образом ввел новый обзор фильма в нейронную сеть.

    "很好,演技不错", 0.91799414 ===>好评
    "要是好就奇怪了", 0.19483969 ===>差评
    "一星给字幕", 0.0028086603 ===>差评
    "演技好,演技好,很差", 0.17192301 ===>差评
    "演技好,演技好,演技好,演技好,很差" 0.8373259 ===>好评

Прочитав эту статью, вы сможете приобрести вышеуказанные навыки.

2. Чтение данных

Прежде всего, нам нужно найти набор данных для обучения, Вот файл csv, который содержит 50 000 обзоров фильмов и телевидения, полученных от Douban.

Его формат следующий:

название счет Комментарий Классификация
название фильма от 1 до 5 баллов Комментарии 1 хорошо, 0 плохо

Часть данных выглядит так:2021-10-22_063822.jpg

Код такой:

# 导入包
import csv
import jieba

# 读取csv文件
csv_reader = csv.reader(open("datasets/douban_comments.csv"))

# 存储句子和标签
sentences = []
labels = []

# 循环读出每一行进行处理
i = 1 
for row in csv_reader:
    
    # 评论内容用结巴分词以空格分词
    comments = jieba.cut(row[2]) 
    comment = " ".join(comments)
    sentences.append(comment)
    # 存入标签,1好评,0差评
    labels.append(int(row[3]))

    i = i + 1

    if i > 20000: break # 先取前2万条试验,取全部就注释

# 取出训练数据条数,分隔开测试数据条数
training_size = 16000
# 0到16000是训练数据
training_sentences = sentences[0:training_size]
training_labels = labels[0:training_size]
# 16000以后是测试数据
testing_sentences = sentences[training_size:]
testing_labels = labels[training_size:]

Здесь было сделано несколько вещей:

  1. Файл читается построчно, выбирая поля комментариев и тегов.
  2. Содержимое комментариев сегментируется и сохраняется.
  3. Разделите данные на группы обучения и тестирования.

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

Сосредоточьтесь на причастиях.

Причастия уникальны для китайского языка и не существуют в английском языке.

Далее следует английское предложение.

This is an English sentence.

Сколько слов в этом предложении?

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

This is an English sentence .
1 2 3 4 5 6

Ниже приводится китайское предложение.

Добро пожаловать в мой блог Наггетс.

Сколько слов в этом предложении?

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

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

способ установки

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

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

После импорта позвонитеjieba.cut("欢迎访问我的掘金博客。")Его можно разделить на слова.

import jieba
words = jieba.cut("欢迎访问我的掘金博客。") 
sentence = " ".join(words)
print(sentence) # 欢迎 访问 我 的 掘金 博客 。

Почему есть причастия? Поскольку слова — это наименьшая единица языка, только тогда, когда вы понимаете слова, вы можете понимать язык и знать, что сказать.

Для китайского языка одно и то же слово имеет разные методы сегментации в разных контекстах.

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

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

Таким образом, сложность обработки китайского естественного языка заключается в сегментации слов.

Пока что наш продукт имеет следующий формат:

sentences = ['我 喜欢 你','我 不 喜欢 他',……]
labels = [0,1,……]

3. Сериализация текста

Текст, на самом деле компьютер не может распознавать текст напрямую, он распознает только 0 и 1.

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

Возьмем, к примеру, букву А, для ее представления мы используем 65, а в двоичном формате это 0100 0001.

бинарный десятичный Аббревиатура/символ объяснять
0100 0001 65 A заглавная буква А
0100 0010 66 B заглавная буква Б
0100 0011 67 C заглавная буква С
0100 0100 68 D заглавная буква Д
0100 0101 69 E заглавная буква Е

Когда вы видите A, B, C, он на самом деле обращается к компьютеру как 0100 0001, 0100 0010, 0100 0011, и ему нравятся числа.

Советы: Вот почему, когда вы сравниваете размер букв, вы находите A

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

3.1 классификация fit_on_texts

Существует класс под названием Tokenizer, который представляет собой токенизатор и используется для классификации и сериализации текста.

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

from tensorflow.keras.preprocessing.text import Tokenizer

sentences = ['我 喜欢 你','我 不 喜欢 他']
# 定义分词器
tokenizer = Tokenizer()
# 分词器处理文本,
tokenizer.fit_on_texts(sentences)
print(tokenizer.word_index) # {'我': 1, '喜欢': 2, '你': 3, '不': 4, '他': 5}

Все, что делается выше, это находит в тексте несколько типов слов и нумерует их.

Посмотрите на результаты вывода, чтобы знать: 2 предложения, наконец, извлекают 5 разных слов, пронумерованных 1 ~ 5.

3.2 последовательность изменения текста texts_to_sequences

Все слова в тексте пронумерованы, поэтому текст можно представить цифрами.

# 文本转化为数字序列
sequences = tokenizer.texts_to_sequences(sentences)
print(sequences) # [[1, 2, 3], [1, 4, 2, 5]]

Таким образом, компьютер постепенно показывал улыбку.

3.3 последовательность заполнения pad_sequences

Хотя он снабжен цифрами, это не стандарт, есть длинные и короткие, компьютер - это сборочная линия, и питается только едиными стандартными данными.

pad_sequences обработает последовательность в единую длину, по умолчанию выбирается самая длинная, а если ее недостаточно, добавляется 0.

from tensorflow.keras.preprocessing.sequence import pad_sequences

# padding='post' 后边填充, padding='pre'前面填充
padded = pad_sequences(sequences, padding='post')
print(padded) # [[1 2 3] [1 4 2 5]] -> [[1 2 3 0] [1 4 2 5]]

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

Его можно добавить, если он меньше, но что делать, если он слишком длинный?

Слишком длинный можно обрезать.

# truncating='post' 裁剪后边, truncating='pre'裁剪前面
padded = pad_sequences(sequences, maxlen = 3,truncating='pre')
print(padded) # [[1, 2, 3], [1, 4, 2, 5]] -> [[1 2 3] [4 2 5]]

Пока наш продукт в таком формате:

sentences = [[1 2 3 0] [1 4 2 5]]
labels = [0,1,……]

4. Постройте модель

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

流水线.gif

流水线2.gif

流水线3.gif

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

То же самое верно и для модели, которая определяет уровни «оборудования», настраивает различные «индикаторы» в процессе и ожидает онлайн-производства.

# 构建模型,定义各个层
model = tf.keras.Sequential([
    tf.keras.layers.Embedding(vocab_size, embedding_dim, input_length= max_length),
    tf.keras.layers.GlobalAveragePooling1D(),
    tf.keras.layers.Dense(64, activation='relu'),
    tf.keras.layers.Dense(1, activation='sigmoid')
])
# 配置训练方法 loss=损失函数 optimizer=优化器 metrics=["准确率”]
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])

4.1 Последовательная последовательность

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

4.2 Встраивание слоя встраивания

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

嵌入.gif

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

Ниже приведены размеры.

Двухмерный выглядит так (длина, ширина):坐标系.jpg

3D выглядит так (длина, ширина, высота):

三维坐标系.jpg

Как выглядит 100 измерений, вы можете себе это представить? Больше трех измерений трудно описать в пространстве разве что физику. Тем не менее, данные очень хорошие.

Пол, положение, возраст, рост, цвет кожи, это 5 измерений, сможете ли вы найти это в 1000 измерениях?

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

Если мы установим R, B, G 3 размера для цвета:

цвет R G B
красный 255 0 0
зеленый 0 255 0
синий 0 0 255
желтый 255 255 0
белый 255 255 255
чернить 0 0 0

Станьте свидетелем чуда ниже.Каждый, кто разбирается в науке о цвете, знает, что такое красный и зеленый цвета, смешанные вместе?

Приходите, почитайте со мной: красный + зеленый = желтый.

В цифрах это: [255,0,0]+[0,255,0] = [255,255,0]

Таким образом, компьютер может рассчитать степень светлоты и оттенка цвета и соотношение между цветами.

Пока маркировка разумна, компьютер может вычислить: король + женщина = королева, прекрасно = - плохо, счастливо > улыбка.

Тогда вы говорите, понимает ли компьютер значение слов?

Встраивание слоев — это маркировка слов с разумными размерами.

Давайте посмотрим на определение слоя внедрения:Встраивание (vocab_size, embedding_dim, input_length)

  • vocab_size: размер словаря. Сколько существует типов слов.
  • embedding_dim: выходной размер этого слоя. Сколько измерений представляет слово.
  • input_length: размер входных данных. Сколько слов в предложении, обычно max_length (максимальная длина тренировочного набора).

4.3 GlobalAveragePooling1D объединение глобальных средних значений в одно измерение

Главное - уменьшение размерности. В конце концов, нам нужен только одномерный результат, который является положительным или отрицательным отзывом, но теперь измерений слишком много, и нам нужно уменьшить размерность.

4.4 Dense

Это тоже уменьшение размерности.Dense(64, activation='relu')вплоть доDense(1, activation='sigmoid'), и, наконец, выведите результат, как и на предыдущей сборочной линии, вводите муку, воду, мясо, овощи и другое сырье, а конечный результат - приготовленные на пару булочки.

神经网络.jpg

4.5 активация функция активации

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

Линейная задача — это задача, которую можно решить одной линией. Может прийтиИгровая площадка TensorFlowтестировать.

При линейном мышлении нейронная сеть может быстро различать два образца.relu.gif

Но если это пример ниже, рисование прямой линии не решит эту проблему.

QQ截图20211023164946.jpg

Если используется функция активации relu, ее легко отличить.

relu4.gif

Это то, что делает функция активации.

Обычно используются следующие, следующие его функции и графика.

未标题-1.jpg

Мы использовали relu и сигмоид.

  • relu: выпрямленная линейная единица, наиболее часто используемая функция активации.
  • сигмовидная: также называемая логистической функцией, она может отображать действительное число в интервал (0,1).

Dense(1, activation='sigmoid')Для последнего Dense мы используем сигмовидную, потому что 0 — плохой отзыв, а 1 — хороший отзыв в нашем наборе данных, и мы ожидаем, что выходное значение модели будет между 0 и 1, чтобы мы могли судить, является ли оно хорошим. ближе к хорошему обзору или плохому обзору. .

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

4.1 фитнес-тренировка

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

model.fit(training_padded, training_labels, epochs=num_epochs,
    validation_data=(testing_padded, testing_labels), verbose=2)
# 保存训练集结果
model.save_weights('checkpoint/checkpoint')

После запуска печать журнала выглядит так:

Epoch 1/10 500/500 - 61s - loss: 0.6088 - accuracy: 0.6648 - val_loss: 0.5582 - val_accuracy: 0.7275 
Epoch 2/10 500/500 - 60s - loss: 0.4156 - accuracy: 0.8130 - val_loss: 0.5656 - val_accuracy: 0.7222 
Epoch 3/10 500/500 - 60s - loss: 0.2820 - accuracy: 0.8823 - val_loss: 0.6518 - val_accuracy: 0.7057

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

Наконец, вызовите save_weights, чтобы сохранить результат.

5. Автоматический анализ результатов

5.1 предсказать предсказание

sentences = [
    "很好,演技不错",
    "要是好就奇怪了",
    "一星给字幕",
    "演技好,演技好,很差",
    "演技好,演技好,演技好,演技好,很差"
]

# 分词处理
v_len = len(sentences)
for i in range(v_len):
    sentences[i] = " ".join(jieba.cut(sentences[i]) )

# 序列化
sequences = tokenizer.texts_to_sequences(sentences)
# 填充为标准长度
padded = pad_sequences(sequences, maxlen= max_length, padding='post', truncating='post')
# 预测
predicts = model.predict(np.array(padded))
# 打印结果
for i in range(len(sentences)):
    print(sentences[i],   predicts[i][0],'===>好评' if predicts[i][0] > 0.5 else '===>差评')

model.predict()Он вернет прогнозируемое значение, которое является не категориальным значением, а значением регрессии (оно также может быть категориальным значением, например, вывод 1 или 0, но мы хотели бы наблюдать разницу между 0,51 и 0,49). Мы предполагаем, что 0,5 — это пороговое значение, выше — положительные отзывы, а ниже — отрицательные.

Наконец, распечатайте результат:

很好,演技不错 0.93863165 ===>好评 
要是好就奇怪了 0.32386222 ===>差评 
一星给字幕 0.0030411482 ===>差评 
演技好,演技好,很差 0.21595979 ===>差评 
演技好,演技好,演技好,演技好,很差 0.71479297 ===>好评

Эта статья предназначена для начинающих. Для облегчения понимания некоторые детали намеренно опущены, а показанные точки знаний являются относительно поверхностными. Она направлена ​​на ознакомление с процессом и принципами и предназначена только для ознакомительных целей. Полный код выложен на github, адрес здесьGitHub.com/HollywoodIndustry/Все поставили…