Рубрики
Без рубрики

Определение пола персонажа фильма с глубоким обучением

Если бы вам дали одну строку из фильма, вы бы смогли определить пол Чаракта … Tagged с глубоким обучением, Python, Machine Learning, Tuperial.

Если бы вам дали одну строку из фильма, сможете ли вы определить пол персонажа, который доставил линию? Если вы не запомнили много сценариев фильмов, вероятно, нет. К счастью для вас, вам не нужно делать это, пока у нас есть компьютеры! Поле обработки естественного языка (NLP) нас покрывает. Применяя глубокое обучение в НЛП и создав текстовый классификатор, мы можем обучить компьютер, чтобы определить, была ли линия из фильма доставлена мужским или женским персонажем!

Если вы получите ценность из этого поста, рассмотрите следствие меня на Twitter и Подписка на мою электронную рассылку Анкет

Настройка вашей среды

Колаба

Глубокое обучение обычно требует большого количества вычислительной мощности и твердого графического процессора, NLP глубокого обучения не является исключением. Раньше это был барьер для входа в поле, но благодаря Google Colaboratory, это больше не так. Google Colab – это платформа, которая позволяет вам обучать модели на графических процессоров, которые находятся в облаке с ноутбуками Jupyter полностью бесплатно! Вы будете следить за этим руководством по Colab.

Чтобы начать работу с Google Colab, все, что вам нужно сделать, это перейти к https://colab.research.google.com/ и войдите в свою учетную запись Google. После того, как вы это сделаете, вы можете сделать тетради Jupyter и использовать их, как обычно. Обычно вы захотите прочитать и написать на свой Google Drive, чтобы вы могли фактически использовать данные и сохранить свои результаты. Чтобы сделать это, добавьте следующий блок кода в качестве первой ячейки в каждой ноутбуке Colab, который вы создаете.

from google.colab import drive
drive.mount('/content/gdrive', force_remount=True)
root_dir = "/content/gdrive/My Drive/pathtofolderwithfileshere"

Теперь у вас есть отличная среда для обучения ваших моделей!

Установка библиотек

Одна из лучших вещей в Colab-это то, что он поставляется со всеми библиотеками науки о больших данных, такими как Pytorch, Tensorflow, Numpy, Matplotlib и Scikit-Learn из коробки! На самом деле, он также поставляется с NLTK и Spacy, двумя наиболее важными библиотеками NLP. Короче говоря, вам не нужно устанавливать какие -либо библиотеки, чтобы следовать этим уроку, если вы используете Colab.

Получение данных

Данные, которые использует этот урок, поступают из корпуса фильма «Корнелл», в котором содержатся информация о 617 голливудских фильмах. Данные этой статьи касается разговорных данных, которые являются лишь строками, предоставленными персонажами фильма и полами персонажа. Для этой цели я извлек все соответствующие данные и объединил их в один файл для удобного использования, который вы можете найти здесь: https://drive.google.com/file/d/1pd6u40qvz6bhelguumh2ernzv4f-byz_/view?usp=sharing Анкет Этот файл данных содержит много строк из фильмов с связанной информацией о персонажах, включая пол персонажей, что имеет большое значение для создания классификатора. После загрузки файла данных загрузите его в папку с именем данных, которая находится в вашем root_dir Как определено выше на Google Drive. Когда вы закончите, вы готовы перейти к стадии предварительной обработки учебника.

Предварительная обработка данных

Первый шаг, который предпринимает в большинстве проектов по науке о данных любого рода, – это изучить данные, с которыми они работают, а затем предварительно обрабатывать их. Для тех из вас, кто не знаком с термином предварительной обработки, все, что он на самом деле просто делает данные пригодными для любой задачи, которую вы намерены выполнить с ним. Различные задачи предварительной обработки варьируются в зависимости от поля, и этот раздел будет охватывать несколько общих задач предварительной обработки НЛП, которые помогут с большей целью Глубокого обучения НЛП.

Предварительный анализ набора данных

Прежде чем начать проект по науке о данных, всегда приятно взглянуть на то, как на самом деле выглядит ваш набор данных. Мы знаем, что у нас есть только два класса для классификации: мужчин и женщин. Следовательно, вам также нужно искать дисбаланс Между двумя классами, что является просто причудливым способом сказать, что вам нужно увидеть, является ли количество точек данных для каждого класса примерно одинаково. К счастью, чтобы получить быстрый обзор данных, вам просто нужно использовать маленький Python! В то время как вы проводите предварительный анализ данных, вы также будете создавать два новых файла, male.txt и fome.txt , что облегчит, когда мы тренируем наши модели. Прежде чем выполнить следующие шаги, создайте новую ноутбук и позвоните в нее Предварительная обработка в Колаба. После того, как вы сделаете это, и ячейку, которая поднимает ваш диск на Colab, вы можете следовать вместе с остальной частью этого раздела.

Первое, что вы должны сделать, это открыть COLTATED_DATA.TXT Файл и посмотрите на его формат. Вы заметите, что он использует «+++ $ +++» в качестве разделителя, что именно то, что он использует для разделения различных значений данных, в CSV разделитель – это запятая. Вы также заметите, что в каждой строке есть 7 различных фрагментов информации, чтобы это: номер строки, идентификатор персонажа, идентификатор фильма, имя персонажа, пол персонажа, текст строки и позицию персонажа в титрах. Вы также можете увидеть, что есть? Вместо пола персонажа в некоторых местах, и это потому, что люди, которые объединяют набор данных, не смогли выяснить пол персонажа.

Теперь, когда вы кратко рассмотрели свои данные, вам необходимо разделить данные на основе пола символов. Это можно сделать в базовом питоне без помощи каких -либо библиотек. Следуйте этим шагам:

  1. Добавьте следующую ячейку в свой блокнот, Все, что он делает, – это инициализировать список, который будет содержать текст строк, доставленных мужчинами, а затем другой список для женщин.
   male_lines = []
   female_lines = []
  1. Затем вам нужно пройти через файл данных и добавить текст в список мужского или женского пола в зависимости от пола динамика. Вы можете сделать это с основными операциями файла и условными операторами. Обратите внимание, что root_dir определяется в первой ячейке, обсуждаемой в этом уроке, и в которой в этом каталоге должен присутствовать COLTATED_DATA.TXT.
with open(root_dir+'collated_data.txt', encoding="charmap") as data:
    for line in data:
        line_no, chr_id, mov_id, chr_name, gender, text, credit = line.strip().split("+++$+++")
        if(gender.strip().lower() == 'm'):
            male_lines.append(text)
        elif(gender.strip().lower() == 'f'):
            female_lines.append(text)      

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

  1. Теперь вы проведете некоторый предварительный анализ набора данных, который просто сводится к рассмотрению количества мужских и женских линий. Это просто требует использования Len () функция
print(len(male_lines)) #Output: 170768  
print(len(female_lines)) #Output: 71255

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

  1. Написав мужские и женские строки, чтобы отделить файлы, вы будете делать себе одолжение и облегчая повторное использование данных для будущих проектов.
with open(root_dir+'male.txt', mode='w+') as male:
    for line in male_lines:
        male.write(line + '\n')
with open(root_dir+'female.txt', mode='w+') as female:
    for line in female_lines:
        female.write(line + '\n')

Приведенные выше блоки кода отделены, потому что я призываю вас поместить их в разные ячейки вашего ноутбука ради ясности. Теперь, когда вы закончили с какой -то очень основной предварительной обработкой, пришло время выполнять некоторые задачи предварительной обработки, которые являются эксклюзивными для NLP.

Введение в термины NLP и предварительную обработку

Существует много информации, которая получена от слов на английском языке, однако вам часто не нужны все предложение, чтобы иметь возможность установить его значение. В NLP обычно есть много неважных данных, которые мы можем очистить, чтобы уменьшить шум в входе в нашу модель. Наиболее распространенные из этих шагов предварительной обработки включают: Токенизация , Стоп слов удаление и Stemming Анкет Однако эти шаги не всегда применяются, потому что иногда они удаляют полезные данные. На самом деле, к этому набору данных не будет применено снятие стоп -слов из -за важной информации, которая может быть удалена этими этапами. Вот некоторые определения каждого из этих шагов.

Токенизация

Токенизация – это разрушение предложения или документа в отдельные токены, которые по сути являются просто словами. Это можно сделать с помощью функции из библиотеки NLTK под названием nltk.tokenize.tokenize () Анкет Вы также можете сделать это Pytorch, когда вы загружаете данные в свою модель, и это то, что вы будете делать, когда пишете модель LSTM. Превращая предложения в отдельные токены, вы создаете последовательные данные, которые очень полезны для LSTM.

Стоп слов удаление

Удаление стоп -слов – это процесс удаления общих слов на английском языке из текста. Часто это делается так, что модели не весят чрезвычайно распространенные слова непропорционально по сравнению с более редкими словами на английском языке, которые чаще появляются в этом конкретном тексте. Тем не менее, для этого проекта не должно быть сделано удаление стоп -слов, поскольку линии фильмов уже довольно короткие, а все токены ценны.

Stemming

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

Разделение данных на наборы обучения и тестирования

Одним из наиболее важных этапов предварительной обработки в машинном обучении в целом является разделение вашего набора данных на наборы обучения и тестирования. Помните, что существует гораздо больше точек данных мужского пола, чем женские точки данных, что означает, что вам придется как -то исправить этот дисбаланс. Имейте это в виду, когда вы начинаете разделять данные. Следующий код по -прежнему будет частью Предварительная обработка ноутбук. Ваша главная цель – создать файл, который будет содержать учебные данные, и файл, который будет содержать данные тестирования.

При создании наборов обучения и тестирования вы должны помнить, что количество точек данных для каждого класса должно быть примерно одинаковым как в наборах обучения, так и в тестировании. Набор тестирования, как правило, будет намного меньше, чем обучающий набор, после разделения 80/20 всех данных. Scikit-Learn имеет встроенную функцию, которая разбивает данные в обучение и тестирование для вас! Прежде чем разделить данные, отбросьте свой разум к дисбалансу в данных, которые мы видели. Существует гораздо больше точек данных мужского пола, чем женские точки данных. Вы можете бороться с этим либо случайным образом заглаживания, либо случайным образом недостаточны нашему обучению. Благодаря случайной перегрузке набора поезда вы увеличите количество женских точек данных, используя некоторые из них несколько раз, пока число женских линий не соответствовает количеству мужских линий в наборе поезда. Благодаря случайному недостатке набора поездов вы уменьшите количество точек данных мужского пола, чтобы соответствовать количеству женских линий в наборе данных. Часто случайным образом недостаточное количество приводится к более низкой точке для модели, потому что просто недостаточно данных, и по этой причине вы будете случайным образом перегружать набор поездов.

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

Хорошо, достаточно теории! Пришло время написать код. Давайте иметь около 10% данных для тестирования, а 90% будут для обучения. Чтобы правильно разделить ваши данные на обучение и тестирование, следуйте этим шагам.

  1. Сначала создайте набор тестирования, просто взяв первые 10000 строк из списков мужского и женского пола.
male_test = male_lines[:10000]
female_test = female_lines[:10000]
X_test = male_test + female_test
  1. Теперь, когда существует x часть набора тестирования, необходимо построить этикетки. Наши этикетки в этом случае будут 0, если линия была доставлена мужчиной, а 1, если линия была доставлена женщина. Это может быть достигнуто с двумя простыми для петель.
Y_test = []
for x in male_test:
    Y_test.append(0)
for x in female_test:
    Y_test.append(1)
  1. Тестовый набор теперь завершен, пришло время для создания набора поездов. Во -первых, возьмите все, что не использовалось в тестовом наборе, и поместите это в два новых списка: male_train и fome_train Анкет
male_train = male_lines[10000:]
female_train = female_lines[10000:]
X_train = male_train + female_train
  1. Теперь вам нужно создать Y_train , который будет содержать метки для линий в x_train. Это тот же процесс, который использовался для изготовления меток для тестового набора.
Y_train = []
for x in male_train:
    Y_train.append(0)
for x in female_train:
    Y_train.append(1)
  1. Поскольку количество мужских линий значительно превосходит количество женских линий в наборе поездов, вам нужно переоборудовать женские линии. Это можно сделать с помощью библиотеки под названием Imblearn, которая включена в вашу среду Colab. Вам также нужно импортировать Numpy. Следующий код переворачивает до тех пор, пока число женских линий не будет равным количеству мужских линий.
import numpy as np
from imblearn.over_sampling import RandomOverSampler
oversample = RandomOverSampler(sampling_strategy='minority')
X_train, Y_train = oversample.fit_resample(np.array(X_train).reshape(-1,1), Y_train)
  1. X_train Это создано в приведенном выше блоке кода, на самом деле является списком списков с одним элементом, где один элемент – линия фильма. Это должен быть просто список строк. Это простое преобразование с быстрым для цикла и индексации списка.
male_lines = []
for phrase in X_train:
    male_lines.append(phrase[0].strip())
X_train = male_lines
  1. Теперь, когда как обучение, так и тестовые наборы полностью построены, их необходимо преобразовать в DataFrames Pandas, а затем сохранить в виде CSV. DataFrames будет иметь два столбца: Текст и цель , где Текст это линия фильма и цель является либо 0, либо 1 в зависимости от пола говорящего. Чтобы сделать все это, панды должны быть импортированы, но сам код довольно прост. Вы создадите два DataFrames и заполните их в списках поезда и испытаний, которые были созданы, а затем сохраните их до root_dir Анкет
import pandas as pd
train_df = pd.DataFrame()
test_df = pd.DataFrame()

train_df['text'] = X_train
train_df['target'] = Y_train

test_df['text'] = X_test
test_df['target'] = Y_test

train_df.to_csv(root_dir + 'train.csv')
test_df.to_csv(root_dir + 'test.csv')

Удивительно! Теперь вы очистили данные и набор обучения и тестирования! Фактическое создание моделей займет у вас меньше времени, чем этап предварительной обработки, и это часто относится к реальным научным проектам. Без лишних слов пришло время перейти к созданию классификаторов.

LSTMS для классификации текста

Как работает повторяющаяся нейронная сеть (RNN)?

Длинные краткосрочные сети памяти (LSTMS) являются версией RNNS. Чтобы правильно понять, как работают LSTM, нужно знать, как работают RNN. Что замечательно в RNNS, так это то, что у них есть внутренняя память, которой нет других нейронных сетей. Люди используют RNN, когда они имеют дело с последовательными данными, такими как язык! В этом объяснении работы RNN предполагается, что вы знаете, как работают основные сети кормления.

В RNN входные данные в цикле в цикле, когда приходит время принять решение, что RNN учитывает текущий вход и вход, который был до него. Нормальный RNN имеет кратковременную память, которая является одной из причин, по которой необходимо использовать LSTM, так что в сети также есть долговременная память. По сути, RNN имеет два входа: текущий вход и последние входы. Это обеспечивает преимущество при выполнении языковых задач. Кроме того, в отличие от сетей подачи, которые могут отображать только один вход с одним выходом, RNN могут выполнять один на многие, многие и многие и многие к одному. Это краткое изложение RNN, и есть много углубленной математики, в которую можно попасть, и я бы посоветовал вам прочитать об этом, чтобы получить действительно тщательное понимание сети.

Перчатки векторы

Векторы перчаток – это то, что мы будем использовать в качестве входов в нашу модель. Перчатки обозначает глобальные векторы для представления слов и используется для создания встроенных слов. Вставки Word часто служат входными данными для моделей NLP глубокого обучения и являются просто способом преобразования текстовой информации, такой как предложения в числовые данные, такие как данные. Это делает ввод понятным для моделей глубокого обучения. Этот раздел проведет вас через первые несколько этапов написания LSTM в Pytorch, который на самом деле просто загружает данные и создает перчатки.

Сначала вам нужно будет создать новую тетрадь на Colab, чтобы фактически записать LSTM. Вы, вероятно, должны называть это чем -то вроде Genderclassifierlstm.ipynb . Прежде чем набрать любые строки кода, обязательно измените время выполнения своей ноутбука и убедитесь, что он использует графический процессор. Чтобы сделать это, нажмите на время выполнения> изменить тип времени выполнения, а затем измените аппаратный ускоритель на графический процессор. Чтобы загрузить в данные и установить базу для вашего LSTM, следуйте этим шагам.

  1. Установите свой Google Drive в Колабе
from google.colab import drive
drive.mount('/content/gdrive', force_remount=True)
root_dir = "/content/gdrive/My Drive/pathtoyourdatahere"
  1. Импортировать все необходимые библиотеки. Не бойтесь за все, что здесь импортируется, вы будете знать, что все означает к концу. Некоторые быстрые моменты заключаются в том, что мы используем Pytorch, Numpy, Pandas и Scikit-Learn. Документация Pytorch – это то, на что вам нужно постоянно смотреть, и вы можете найти ее в https://pytorch.org/docs/stable/index.html .
import torch
import torch.nn as nn 
import torch.nn.functional as F
import torchtext 
import numpy as np
import pandas as pd
from torchtext import data
from torch.utils.data import Dataset, DataLoader
from torch.nn.utils.rnn import pack_padded_sequence, pad_packed_sequence 
from sklearn.metrics import mean_squared_error
  1. Теперь пришло время загрузить в данные, которые у вас есть, довольно простая задача.
train_df = pd.read_csv(root_dir + 'train.csv')
test_df = pd.read_csv(root_dir + 'test.csv')
  1. Теперь, когда вы загружаете CSV в COLAB, вначале вы получите дополнительный столбец в начале, и вам нужно исправить, что вам нужно реконструировать оба train_df и test_df Анкет Способ сделать это – просто извлечь соответствующие столбцы, а затем поместить их в новые DataFrames.
X_train = train_df['text']
Y_train = train_df['target']
X_test = test_df['text']
Y_test = test_df['target']
  1. Еще один момент, который вы должны изучить, поскольку последний бит предварительной обработки – удаление значений NAN из ваших данных. Простой способ сделать это – просто удалить все типы данных, которые плавают из ваших списков, потому что при работе с текстовыми данными только NAN будут плавать.
indices = []
for i in range(len(X_train)):
  if (isinstance(X_train[i], float)):
    indices.append(i)

for index in sorted(indices, reverse=True):
    del X_train[index]
    del Y_train[index]

indices = []
for i in range(len(X_test)):
  if (isinstance(X_test[i], float)):
    indices.append(i)

for index in sorted(indices, reverse=True):
    del X_test[index]
    del Y_test[index]
  1. Теперь вы посетите свой ноутбук, чтобы вы получили одинаковые результаты каждый раз, когда запускаете ноутбук.
SEED = 42

torch.manual_seed(SEED)
torch.backends.cudnn.deterministic = True
torch.backends.cudnn.benchmark = False
  1. Теперь, если вы помните, одной из важных частей предварительной обработки текстовых данных является токенизация. Pytorch позволяет нам делать это, когда мы создаем поля модели, из которых у нас есть два: Текст и Ярлык которые являются самоэкспланирующими.
TEXT = data.Field(tokenize = 'spacy', include_lengths = True)
LABEL = data.LabelField(dtype = torch.float)

Как вы можете видеть, мы создаем два поля, используя встроенные поля, которые torch.utils.data имеет. Затем текст токенизируется с использованием Spacy, которая является одной из библиотек обработки текста, которая используется в таких проектах.

  1. При работе с NLP Deep Learning в Pytorch и любым другим типом глубокого обучения вам обычно нужно писать классы для размещения пользовательских наборов данных и убедиться, что вы можете загрузить его в свою модель. В этом случае вы будете писать пользовательский класс, который будет представлять собой DataFrame.
class DataFrameDataset(data.Dataset):

    def __init__(self, df, fields, is_test=False, **kwargs):
        examples = []
        for i, row in df.iterrows():
            label = row.target if not is_test else None
            text = row.text
            examples.append(data.Example.fromlist([text, label], fields))

        super().__init__(examples, fields, **kwargs)

    @staticmethod
    def sort_key(ex):
        return len(ex.text)

    @classmethod
    def splits(cls, fields, train_df, val_df=None, test_df=None, **kwargs):
        train_data, val_data, test_data = (None, None, None)
        data_field = fields

        if train_df is not None:
            train_data = cls(train_df.copy(), data_field, **kwargs)
        if val_df is not None:
            val_data = cls(val_df.copy(), data_field, **kwargs)
        if test_df is not None:
            test_data = cls(test_df.copy(), data_field, True, **kwargs)

        return tuple(d for d in (train_data, val_data, test_data) if d is not None)

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

  1. Следующий шаг – сделать набор данных поезда и тестирования для модели, которую вы создадите, и сделать это, вы будете использовать метод разделения в классе DataFramedataset, который вы написали.
fields = [('text',TEXT), ('label',LABEL)]
train_ds, test_ds = DataFrameDataset.splits(fields, train_df=train_df, val_df=test_df)

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

  1. При построении векторов перчаток вам придется определить размер своего словаря, и в этом случае это будет размер вектора X_TRAIN. Вы также должны определить размер вектора или сколько измерений он будет иметь. 200 измерений являются стандартными. В следующем блоке кода вы создаете словарный запас для своего текста. Как вы можете видеть, размер вашего словаря – это количество строк в списке X_TRAIN.
MAX_VOCAB_SIZE = len(train_df['text'])

TEXT.build_vocab(train_ds, 
                 max_size = MAX_VOCAB_SIZE, 
                 vectors = 'glove.6B.200d',
                 unk_init = torch.Tensor.zero_)
  1. Построив словарный запас для текста, вам нужно будет сделать то же самое для своих лейблов, но вы не будете использовать перчатки.
LABEL.build_vocab(train_ds)

Хорошо! Вы закончили всю необходимую предварительную обработку, и установили основу для написания LSTM. Пришло время узнать больше о чуде, которое является долгосрочной сетью памяти.

Что такое LSTMS?

LSTM – это улучшение на RNN. Ранее было упомянуто, что RNN имеют кратковременную память, которая является одним из их преимуществ, и это улучшается в LSTMS. LSTM могут сохранить воспоминания в долгосрочной перспективе, что значительно повышает их производительность.

LSTM сосредоточены вокруг того, что называется клеточным состоянием, которое обычно рассматривается как конвейерная лента. Эта конвейерная лента проходит через цепь модулей нейронной сети. Информация обычно проходит через цепь без изменений и непрерывной. Тем не менее, LSTM может изменить информацию, которую содержание ячейки имеет с помощью «ворот». Ворота изготовлены из точковой операции умножения и сигмоидного нейронного чистого слоя. Если вы знакомы с глубоким обучением, вы узнаете, что Sigmoid -слой просто выводит числа между нулем и одним. Это соответствует тому, сколько из каждого компонента следует пропустить. Как вы можете предположить, 0 означает, что ничего не следует пропустить, а 1 означает, что все должно пропустить. У LSTM есть три таких ворота, и именно так они контролируют поток информации в сетях. Я бы посоветовал вам прочитать больше о математике, стоящей за длинными краткосрочными сетями памяти после того, как вы его реализуете, и это поможет вам лучше понять сеть.

Достаточно теории! Время для реализации этого в Pytorch. Следуйте этим шагам, и вы будете золотыми в следующий раз, когда захотите реализовать LSTM.

  1. Прежде чем вы действительно приступите к написанию LSTM, есть некоторые вещи, которые вам нужно сделать, которые являются обычным явлением среди большинства реализаций нейронной сети Pytorch. А именно, убедитесь, что вы будете использовать графический процессор для обучения и выбора некоторых гиперпараметров. Еще одна важная вещь, которую вы делаете, – это объявление Train_iterator и valive_iterator Анкет Они будут использоваться при обучении и тестировании модели соответственно, как следует из названия, итерация через данные.
BATCH_SIZE = 256

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

train_iterator, valid_iterator = data.BucketIterator.splits(
    (train_ds, test_ds), 
    batch_size = BATCH_SIZE,
    sort_within_batch = True,
    device = device)
  1. Хорошо, единственный гиперпараметр, который определяется до сих пор, – это batch_size. Есть много других важных гиперпараметров, которые следует обсуждать. Все они находятся в кодовом блоке ниже с сопровождающими объяснениями.
# Hyperparameters
num_epochs = 25 #This is the number of epochs and dictates how long the model trains for
learning_rate = 0.001 #This essentially determines how quickly a model trains

INPUT_DIM = len(TEXT.vocab) #As the name suggests this is the input dimension
EMBEDDING_DIM = 200 #The GloVe Embedding dimensions which is 200
HIDDEN_DIM = 256 #The number of hidden dimensions
OUTPUT_DIM = 1 #The number of output dimensions: 1 (either 0 or 1)
N_LAYERS = 4 #The number of layers in the neural network.
BIDIRECTIONAL = True #LSTMs are Bidirectional so don't change this hyperparameter
DROPOUT = 0.2 # Dropout is when random neurons are ignored, the higher the dropout the greater percentage of neurons are ignored.
PAD_IDX = TEXT.vocab.stoi[TEXT.pad_token] # padding makes it so that sequences are padded to the maximum length of any one of the sequences, in this case that would be the longest utterance delivered by a movie character.
  1. Теперь наступает захватывающая часть, на самом деле написание LSTM. Вы будете создавать класс под названием Lstm_net Это наследует от Pytorch’s нн Модуль Анкет Как и в любом классе, который пишет в Python, первое, что нужно сделать, это написать __init__ метод
class LSTM_net(nn.Module):
    def __init__(self, vocab_size, embedding_dim, hidden_dim, output_dim, n_layers, 
                 bidirectional, dropout, pad_idx):

        super().__init__()

        self.embedding = nn.Embedding(vocab_size, embedding_dim, padding_idx = pad_idx)

        self.rnn = nn.LSTM(embedding_dim, 
                           hidden_dim, 
                           num_layers=n_layers, 
                           bidirectional=bidirectional, 
                           dropout=dropout)

        self.fc1 = nn.Linear(hidden_dim * 2, hidden_dim)

        self.fc2 = nn.Linear(hidden_dim, 1)

        self.dropout = nn.Dropout(dropout)

Если вы посмотрите на параметры, которые __init__ Метод принимает, вы заметите, что они являются гиперпараметрами, которые мы уже установили, и что они используются для построения LSTM. Метод начинается с классической черты наследования в Python, которая вызывает Super () .__ init__ Чтобы вызвать метод init nn. Класс модуля, для которого вы должны посмотреть на документацию. Далее встраивание для LSTM строится с использованием размер слока, встраивания размеров и прокладки. Это вкладывает просто простой таблицу поиска, в которой хранятся встроенные встроенные словаря и размер и используются для хранения встроенных слов перчатки.

Вы также заметите, что RNN используется в качестве основания LSTM с некоторыми из гиперпараметров, которые уже были определены. Вы можете быть смущены двумя переменными, называемыми self.fc1 и self.fc2 , но не бойтесь, это всего лишь два слоя активации LSTM, а первый – больше второго. ФК является сокращением для полностью подключенного слоя. Последняя инициализированная переменная, – это отсечение сети, которая обсуждалась ранее.

  1. Теперь пришло время перейти на второй из двух методов, которые будет иметь этот класс: forward () который кодирует вперед проход для сети.
def forward(self, text, text_lengths):  
        embedded = self.embedding(text)

        packed_embedded = nn.utils.rnn.pack_padded_sequence(embedded, text_lengths)
        packed_output, (hidden, cell) = self.rnn(packed_embedded)

        # concat the final forward (hidden[-2,:,:]) and backward (hidden[-1,:,:]) hidden layers
        # and apply dropout
        hidden = self.dropout(torch.cat((hidden[-2,:,:], hidden[-1,:,:]), dim = 1))
        output = self.fc1(hidden)
        output = self.dropout(self.fc2(output)) 
        #hidden = [batch size, hid dim * num directions] 
        return output

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

  1. Хорошо, теперь, когда класс LSTM был создан, вам нужно сделать экземпляр класса.
#creating instance of our LSTM_net class

model = LSTM_net(INPUT_DIM, 
            EMBEDDING_DIM, 
            HIDDEN_DIM, 
            OUTPUT_DIM, 
            N_LAYERS, 
            BIDIRECTIONAL, 
            DROPOUT, 
            PAD_IDX)
  1. Настало время хранить встраиваемые в переменной, удобно помеченной Pretried_embeddings а затем передать эти знания модели.
pretrained_embeddings = TEXT.vocab.vectors
model.embedding.weight.data.copy_(pretrained_embeddings)
  1. Чтобы сделать заполнение сети, вам необходимо заполнить ее кучей нуля, что можно сделать с помощью следующей строки кода.
model.embedding.weight.data[PAD_IDX] = torch.zeros(EMBEDDING_DIM)
  1. Чтобы убедиться, что модель тренируется на GPU, используйте следующую строку кода.
model.to(device)
  1. Все нейронные сети нуждаются в функции потери и оптимизаторе! Добавьте их со следующим блоком кода.
# Loss and optimizer
criterion = nn.BCEWithLogitsLoss()
optimizer = torch.optim.Adam(model.parameters(), learning_rate)
  1. Затем вы будете писать функцию, которая рассчитает точность прогнозов вашей модели с некоторой основной логикой. Обратите внимание на комментарии, чтобы понять, что происходит!
def binary_accuracy(preds, y):
    """
    Returns accuracy per batch, i.e. if you get 8/10 right, this returns 0.8, NOT 8
    """

    #round predictions to the closest integer
    rounded_preds = torch.round(torch.sigmoid(preds))
    correct = (rounded_preds == y).float() #convert into float for division 
    acc = correct.sum() / len(correct)
    return acc

Обучение LSTM

Вот, как будто! Вы до сих пор много работали, и вы почти в конце дороги! Пришло время тренировать и проверить модель!

  1. Вам нужно будет написать функцию, которую вы используете для обучения модели.
def train(model, iterator):
    epoch_loss = 0
    epoch_acc = 0

    model.train()

    for batch in iterator:
        text, text_lengths = batch.text
        optimizer.zero_grad()
        predictions = model(text, text_lengths).squeeze(1)
        loss = criterion(predictions, batch.label)
        acc = binary_accuracy(predictions, batch.label)

        loss.backward()
        optimizer.step()

        epoch_loss += loss.item()
        epoch_acc += acc.item()

    return epoch_loss / len(iterator), epoch_acc / len(iterator)

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

  1. Вам также понадобится функция, которую вы используете для оценки производительности модели.
def evaluate(model, iterator):

    epoch_loss = 0
    epoch_acc = 0
    model.eval()

    with torch.no_grad():
        for batch in iterator:
            text, text_lengths = batch.text

            predictions = model(text, text_lengths).squeeze(1)
            loss = criterion(predictions, batch.label)
            acc = binary_accuracy(predictions, batch.label)

            epoch_loss += loss.item()
            epoch_acc += acc.item()

    return epoch_loss / len(iterator), epoch_acc / len(iterator)

Эта функция проходит через тестовые данные, подает их в модель, а затем измеряет прогноз против фактической метки. Затем он выводит потери и точность для эпохи.

  1. Это будет последний блок кода, который вы пишете, это то, что на самом деле будет обучать модель. Это довольно простой питон и требует одного импорта, время Библиотека, которая уже включена в Colab, поэтому вам не нужно ничего устанавливать.
import time

t = time.time()
loss=[]
acc=[]
val_acc=[]
val_losses=[]

for epoch in range(num_epochs):
    train_loss, train_acc = train(model, train_iterator)
    val_loss, valid_acc = evaluate(model, valid_iterator)
    print("Epoch " + str(epoch) + " :")
    print(f'\tTrain Loss: {train_loss:.3f} | Train Acc: {train_acc*100:.2f}%')
    print(f'\tVal Loss: {val_loss:.3f} | Val. Acc: {valid_acc*100:.2f}%')
    print('\n')
    loss.append(train_loss)
    acc.append(train_acc)
    val_acc.append(valid_acc)
    val_losses.append(val_loss)
print(f'time:{time.time()-t:.3f}')

Блок кода, выше, отслеживает потерю и точность для каждой эпохи, а затем хранит их в списке, который вы можете использовать для графика и увидеть производительность модели в эпохи. Это также отслеживает время, которое модель требует, чтобы тренироваться на каждую эпоху. С текущими гиперпараметрами вы закончите с точностью проверки в диапазоне 70% и временем обучения 30 минут. Регулируя гиперпараметры, вы можете повысить производительность модели, но Это может прийти за счет более высокого обучения.

Вывод

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

Если вы получили ценность из этого поста, рассмотрите следствие меня на Twitter и Подписка на мою электронную рассылку Анкет Каждое воскресенье я посылаю информационный бюллетень, в котором содержатся лучшие программы и контент, связанный с обучением, который я видел на прошлой неделе вместе с моими собственными мыслями о событиях недели. Основная цель информационного бюллетеня-приносить значимые и наводящие на размышления идеи в ваш почтовый ящик каждое воскресенье. Подумайте о том, чтобы подписаться, если вам интересно.

Оригинал: “https://dev.to/siddhantdubey/identifying-the-gender-of-a-movie-character-with-deep-learning-n91”