введение
Эта статья законченаСерия курсов «PyTorch Introductory Course: Deep Learning on the Torch» от Jizhi AcademyПосле расчесывания.
Эта серия курсов содержит большое количество практических задач, таких как классификация текста, распознавание рукописных цифр, переводчики, композиторы, игры с искусственным интеллектом и многое другое. В практическую работу также включено большое количество базовых и классических знаний в области машинного обучения, таких как принцип обратного распространения ошибки, принцип анализа нейронов и область НЛП.RNN,LSTM,word2vec
, и домен изображения迁移学习,卷积神经网络
Подождите, он очень подходит для студентов, которые хотят начать работу с машинным обучением, и это единственный хороший курс в текущей сети.
Я получил много пользы после обучения, и я хотел бы выразить искреннюю благодарность Учителю Чжан Цзян.
Статьи из этой же серии:
- Используйте линейную регрессию, чтобы соответствовать случаю и полностью понять обратное распространение в глубоком обучении
- Ваша первая нейронная сеть — предиктор общего велосипеда
текст
Задача этой статьи состоит в том, чтобы реализовать модель нейронной сети на основе текстовых данных отзывов о продуктах электронной коммерции, чтобы определить, является ли отзыв хорошим или плохим. Эта задача по существу является проблемой бинарной классификации. Точно так же проблема бинарной классификации может также решать такие задачи, как фильтрация бессмысленных комментариев и определение того, что изображение принадлежит кошкам и собакам. Разница заключается в том, являются ли входные данные текстом, изображениями или другими типами данных.
Прежде чем я начну, позвольте мне сделать простой ключевой момент, чтобы каждый мог иметь предварительное представление о полном тексте. Суть того, что мы хотим выполнить для этой задачи, делится на два пункта:
Во-первых, это ссылка на обработку данных. существуетВаша первая нейронная сеть — предиктор общего велосипедаВ , я также потратил много места на обработку данных, включая горячую обработку, нормализацию и другие основные операции обработки данных. В этой задаче обработка данных еще более важна. В основном это связано с проблемой того, как позволить машине распознавать текст и использовать его для вычислений. Здесь мы в основном используем самые простые词袋模型(BOW)
. Среди них обработка китайского языка также необходимо использовать正则匹配
а такжеjieba分词工具
.
Во-вторых, это базовый шаг обучения нейронной сети, фактически этот шаг связан сВаша первая нейронная сеть — предиктор общего велосипедаШаги в этой статье в основном такие же, не более чем построение модели, ввод данных, получение прогнозируемого значения, обратное распространение для расчета потерь, затем выполнение операции градиента для корректировки веса и повторение всего процесса до тех пор, пока потери не исчезнут. дольше уменьшается, поэтому описание этапов обучения не будет подробно расширяться, и ученики, которые не разобрались, могут вернуться и прочитать предыдущую статью. Разница лишь в том, что задача классификации损失函数
В отличие от задачи регрессии, это будет подробно объяснено позже.
Давайте начнем формальную ссылку операции, давайте сначала посмотрим на обработку данных.
1. Предварительная обработка данных
Давайте сначала посмотрим на формат данных, который мы используем для моделирования. Он разделен на два текстовых файла, good.txt и bad.txt, в которых хранятся положительные и отрицательные комментарии соответственно, и каждая строка представляет собой комментарий. Данные с сайта JD.com (2013 г.), доступны по адресуГитхаб академии Цзижидля получения файла данных.
Читая файл построчно и сохраняя его последовательно, мы можем отфильтровывать знаки препинания и сегментировать предложения во время чтения. Таким образом, вы можете получить два массива: массив положительных текстов и массив отрицательных текстов.
Пунктуация фильтрации может использоваться напрямую正则表达式
, причастие может использоваться непосредственно结巴分词库
, этот инструмент может точно разбить предложение на несколько осмысленных слов. Предложение с большим количеством вхождений определенных слов, таких как «очень хорошо», «нравится» и т. д., обычно мы можем считать это предложение положительным комментарием. Таким образом, китайские слова — это наименьшая единица, которую мы хотим проанализировать.
import re #正则表达式的包
import jieba #结巴分词包
# 正向文本
with open('good.txt', 'r') as fr:
for idx, line in enumerate(fr):
if True:
#过滤标点符号
line = re.sub("[\s+\.\!\/_,$%^*(+\"\'“”《》?“]+|[+——!,。?、~@#¥%……&*():]+", "", line)
#分词
words = jieba.lcut(line)
if len(words) > 0:
all_words += words
pos_sentences.append(words)
# 负向文本处理方法相同,得到数组neg_sentences
ЛУК (Мешок слов)
Чтобы компьютер мог обрабатывать текст, он должен сначала найти способВекторизация текста. Метод BOW — это очень простой для понимания метод векторизации текста. Я приведу простой пример, чтобы все поняли с первого взгляда. Его идея состоит в том, чтобы в качестве размерности вектора использовать количество всех слов, содержащихся в тексте, а в качестве значения соответствующей позиции — частоту слова в текущем предложении.
句子1:“我喜欢跳舞,小明也喜欢。”
句子2:“我也喜欢唱歌。”
Выше приведены два предложения, и теперь мы хотим представить эти два предложения в виде векторов. Из этих двух предложений мы можем извлечь словарь, содержащий все слова в этих двух предложениях.
词典 = {1:“我”,2:“喜欢”,3:“跳舞”,4:“小明”,5:“也”,6:“唱歌”}
В качестве размерности вектора используется количество всех слов, содержащихся в тексте, а в качестве значения соответствующей позиции используется частота слова в текущем предложении. Затем мы сразу получаем векторное представление предложения.
句子 1:[1, 2, 1, 1, 1, 0]
句子 2:[1, 1, 0, 0, 1, 1]
вернуться к нашей миссии. В соответствии с приведенной выше идеей нам нужно создать большой словарь, содержащий все слова, и подсчитать частоту каждого слова, чтобы мы могли получить векторное представление каждого предложения. использовать здесьcollections
Инструменты могут упростить статистику частоты слов.
from collections import Counter #搜集器,可以让统计词频更简单
diction = {} # 要建立的大字典
cnt = Counter(all_words)
for word, freg in cnt.items():
diction[word] = [len(diction), freg] # 在字典中存储每个词语的编号,以及词频
После создания большого словаря приступайте к обработке текста комментария построчно.
dataset = [] # 所有句子的向量表示集合,即我们训练,测试要使用到的数据
# 处理正向评论
for sentence in pos_sentences:
new_sentence = []
for l in sentence:
if l in diction:
new_sentence.append(word2index(l, diction))
dataset.append(sentence2vec(new_sentence, diction))
labels.append(0) #正标签为0
sentences.append(sentence)
# 其中
# word2index是根据单词获得编码函数
# sentence2vec是把目标句子转化为向量函数
# 这里不详细展示,大家可以尝试自己编写
# 源代码可以从文章开头提到的集智学园github地址中下载
dataset
иlabel
Он содержит всю необходимую нам информацию, включая текстовые данные и соответствующие метки. Далее мы можем перейти к этапу обучения модели.
Далее можно приступать к обучению модели. Следующая часть кода относительно большая, опять же, подробное описание кода процесса обучения иВаша первая нейронная сеть — предиктор общего велосипедаЭта статья аналогична, поэтому эта статья и часть повторяющегося кода не будут подробно объясняться. Так что приведенный ниже код — просто бумажный тигр.
2. Начать обучение
2.1 Построить входную и целевую функции, построить модель
То есть исходные данные обрабатываются, и данные делятся на обучающий набор, проверочный набор и тестовый набор на основе набора данных и метки.
#对整个数据集进行划分,分为:训练集、校准集和测试集,其中校准和测试集合的长度都是整个数据集的10分之一
test_size = len(dataset) // 10
train_data = dataset[2 * test_size :]
train_label = labels[2 * test_size :]
valid_data = dataset[: test_size]
valid_label = labels[: test_size]
test_data = dataset[test_size : 2 * test_size]
test_label = labels[test_size : 2 * test_size]
Используйте pytorch для быстрого создания простой модели нейронной сети.
# 输入维度为词典的大小:每一段评论的词袋模型
model = nn.Sequential(
nn.Linear(len(diction), 10),
nn.ReLU(),
nn.Linear(10, 2),
nn.LogSoftmax(),
)
- Входной текстовый вектор, длина равна размеру словаря
- После слоя нелинейного преобразования relu
- После слоя линейного преобразования
- Нормализованный логSoftmax
Почему вывод здесь двумерный, разве наша метка не 1 или 0?
На самом деле, для удобства расчета здесь у нас есть горячее кодирование метки, о роли которого также упоминалось в предыдущей статье, потому что 0 и 1 здесь не имеют понятия «1 больше». чем 0". , точно так же, как Monday и Monday, все они являются переменными типа, чтобы избежать влияния числового размера переменных типа 0 и 1 на обучение нейронной сети.
2.1 Процесс обучения + проверки
код напрямую
# 损失函数为交叉熵
cost = torch.nn.NLLLoss()
# 优化算法为Adam,可以自动调节学习率
optimizer = torch.optim.Adam(model.parameters(), lr = 0.01)
records = []
#循环10个Epoch
losses = []
for epoch in range(10):
for i, data in enumerate(zip(train_data, train_label)):
x, y = data
x = torch.tensor(x, requires_grad = True, dtype = torch.float).view(1, -1)
y = torch.tensor([y], dtype = torch.long)
optimizer.zero_grad()
predict = model(x)
loss = cost(predict, y)
# 将损失函数数值加入到列表中
losses.append(loss.data.numpy())
# 开始进行梯度反传
loss.backward()
# 开始对参数进行一步优化
optimizer.step()
# 每隔3000步,跑一下校验数据集的数据,输出临时结果
if i % 3000 == 0:
rights = []
val_losses = []
for j, val in enumerate(zip(valid_data, valid_label)):
x, y = val
x = torch.tensor(x, requires_grad = True, dtype = torch.float).view(1, -1)
y = torch.tensor([y], dtype = torch.long)
predict = model(x)
# 调用rightness函数计算准确度
right = rightness(predict, y)
rights.append(right)
loss = cost(predict, y)
val_losses.append(loss.data.numpy())
# 将校验集合上面的平均准确度计算出来
right_ratio = 1.0 * np.sum([i[0] for i in rights]) / np.sum([i[1] for i in rights])
print('第{}轮,训练损失:{:.2f}, 校验损失:{:.2f}, 校验准确率: {:.2f}'.format(epoch, np.mean(losses), np.mean(val_losses), right_ratio))
records.append([np.mean(losses), np.mean(val_losses), right_ratio])
Здесь я хотел бы подчеркнуть следующие моменты:
Прежде всего, приведенный выше код немного отличается от предыдущей статьи.Процесс проверки и процесс обучения написаны вместе, но идея остается той же.Используйте данные набора проверки для запуска на обученной модели и наблюдайте за проверкой. Изменения в наборе val_loss. Результат будет более объективным.
Во-вторых, для задач классификации также может быть рассчитана точность правильности результатов. Рассчитайте точность прогноза, сравнив истинную метку с прогнозируемым значением. где истинные метки и прогнозируемые значения являются двумерными матрицами
def rightness(predictions, labels):
# """计算预测错误率的函数
# 其中predictions是模型给出的一组预测结果
# batch_size行num_classes列的矩阵
# labels是数据之中的正确答案""",
# 对于任意一行(一个样本)的输出值的第1个维度,求最大,得到每一行的最大元素的下标
pred = torch.max(predictions.data, 1)[1]
# 将下标与labels中包含的类别进行比较,并累计得到比较正确的数量
rights = pred.eq(labels.data.view_as(pred)).sum()
# 返回正确的数量和这一次一共比较了多少元素
return rights, len(labels)
И, наконец, самое главное, это функция потерьtorch.nn.NLLLoss(), что является перекрестной энтропией.
Формула кросс-энтропии для бинарной классификации выглядит следующим образом:
Этот метод также используется текущей задачей, где:
- y — представляет собой метку образца, положительный образец равен 1, отрицательный образец равен 0
- p - представляет вероятность того, что образец будет положительным.
Прогнозируемое значение нейронной сети для задач классификации обычно является вероятностью.В текущей задаче, например, предсказание выдает [0,8, 0,2], а это означает, что нейронная сеть имеет более высокую вероятность предсказать, что текущая выборка 1 (первое значение, скорее всего, будет 1. Большой). Перекрестная энтропия используется для расчета потери предсказания задач классификации, то есть, если реальная выборка равна 1, то сравните «разницу» между [0,8, 0,2] и [1,0], чем меньше значение «разницы», тем лучше прогноз ближе к реальности.
Когда потери больше не уменьшаются, модель в основном завершает обучение.На следующем рисунке показаны изменения потерь тренировочного набора, потерь проверочного набора и точности.
Мы можем думать, что эффект модели является лучшим в той части, где потеря проверочного набора и потеря обучающего набора перекрываются, а затем продолжить обучение.Хотя потеря обучающего набора продолжает снижаться, потеря верификационного множества не падает, а растет, в этот момент модель была переобучена.
3. Проверьте эффект модели.
Мы берем данные тестового набора и видим эффект предсказания модели.
rights = []
for i, data in enumerate(zip(test_data, test_label)):
x, y = data
x = torch.tensor(x, requires_grad = True, dtype = torch.float).view(1, -1)
y = torch.tensor([y], dtype = torch.long)
predict = model(x)
right = rightness(predict, y)
rights.append(right)
right_ratio = 1.0 * np.sum([i[0] for i in rights]) / np.sum([i[1] for i in rights])
print(' 测试准确率: {:.2f}'.format(right_ratio))
Окончательная точность вывода: 0,91.
На этом вся задача выполнена, мы получаем текстовый классификатор, умеющий различать положительные и отрицательные отзывы, и точность этого классификатора может достигать 91%
Заканчивать
Спасибо за то, что вы здесь. Яма текстового классификатора заполнена.
В будущем я также попробую реальные кейсы, такие как распознавание изображений, перевод текста и игры с искусственным интеллектом. Все примеры обучения взяты из PyTorch и курса глубокого обучения Чжан Цзяна.
Надеюсь поделиться со всеми вами.