RNN расшифровывается как Recurrent Neural Network. Это класс искусственных нейронных сетей, которые используют последовательные данные или данные временных рядов. В основном он используется для решения порядковых или временных проблем.
Синтаксис:
torch.nn.RNN(input_size, hidden_layer, num_layer, bias=True, batch_first=False, dropout = 0, bidirectional = False)
Параметры:
- input_size: во входных данных x количество ожидаемых функций.
- скрытый_слой: количество объектов в скрытом состоянии.
- num_layer: num_layer используется в качестве нескольких повторяющихся слоев.
- bias: если смещение имеет значение False, то слой не использует веса смещения.
- batch_first: если пакет_первый имеет значение True, то предоставляются входные и выходные тензоры(пакет, последовательность, функция) вместо(последовательность, пакет, функция). Значение по умолчанию пакетного_первого — False.
- dropout: если ненулевое значение, инициировать слой выпадения на выходе каждого уровня RNN, исключая последний слой, с вероятностью выпадения, равной выпадению. Значение отсева по умолчанию — 0.
- bidirectional: если True, то он становится двунаправленным RNN. Значение двунаправленной связи по умолчанию — False.
- Пример
- RNN-ячейка
- Функция активации
- Бинарная классификация
- Анализ настроений
- Языковая модель
- Загрузчик данных
Пример
Рекуррентная нейронная сеть — это своего рода нейронная сеть, в которой выходные данные предыдущего шага сохраняются в качестве входных данных для текущего шага.
Важной особенностью RNN является скрытое состояние, которое запоминает некоторую информацию о последовательности.
Код:
В следующем коде мы импортируем модуль факела, из которого мы сможем рассчитать выходные данные RNN.
- Recnn = nn.RNN(12, 22, 4) используется для работы над задачей прогнозирования последовательности с использованием
- РНН.
- inp = torch.randn(7, 5, 12) используется для генерации случайных чисел в качестве входных данных.
- outp, hn = Recnn(inp, h) используется для получения выходных данных.
- print(outp) используется для печати вывода на экран.
import torch import torch.nn as nn recnn = nn.RNN(12, 22, 4) inp = torch.randn(7, 5, 12) h = torch.randn(4, 5, 22) outp, hn = recnn(inp, h) print(outp)
Выход:
После запуска приведенного выше кода мы получаем следующий вывод, в котором видим, что значение PyTorch RNN печатается на экране.
RNN-ячейка
Ячейка RNN — это все, что имеет состояние и выполняет некоторые операции, которые принимают матрицу входных данных.
Клетки RNN отличаются от систематических нейронов в том смысле, что у них есть состояние и они могут запоминать информацию из прошлого.
синтаксис:
torch.nn.RNNCell(input_size, hidden_size, bias = True, nonlinearity = 'tanh', device = None, dtype = None)
Параметры:
- input_size количество ожидаемых функций во входных данных x.
- hidden_size — количество объектов в скрытом состоянии в виде h.
- bias. Если смещение имеет значение False, то слой не использует вес смещения. Значение смещения по умолчанию — True.
- nonlinearity: по умолчанию — tanh. Используется может быть как тан, так и релу.
Функция активации
Функция активации PyTorch RNN определяется как то, как взвешенная сумма входных данных преобразуется в выходные данные узла или узлов на уровне сети.
Код:
В следующем коде мы импортируем модуль факела, из которого начнет работать функция активации модели rnn.
- traindt = dtsets.MNIST(root=’./data’, train=True, Transform=transform.ToTensor(), download=True) используется в качестве набора данных.
- self.hidendim = скрытый размер используется как скрытое измерение.
- self.layerdim=layerdim используется как количество скрытых слоев.
- self.rnn = nn.RNN(inpdim,hidendim,layerdim,batt_first=True,nonlinearity=’relu’) используется для построения модели rnn.
- self.fc = nn.Linear(hidendim, outpdim) используется как слой считывания.
- h = torch.zeros(self.layerdim, y.size(0), self.hidendim).requires_grad_() инициализирует скрытое состояние нулями.
- outp = self.fc(outp[:, -1, :]) используется как индекс скрытого состояния объекта последнего времени.
- optim = torch.optim.SGD(mdl.parameters(), lr=l_r) используется для инициализации оптимизатора.
- imgs = imgs.view(-1, seqdim, inpdim).requires_grad_() используется для загрузки изображений в виде тензора с градиентом
- optim.zero_grad() используется как четкий градиент относительно параметра.
- loss = criter(outps, lbls) используется для расчета потерь.
- optim.step() используется как параметр обновления.
- outps = mdl(imgs) используется как прямой проход только для получения выходных данных.
- _, предсказанный = torch.max(outps.data, 1) используется для получения прогноза на основе максимального значения.
- ttl += lbls.size(0) используется как общее количество меток.
- crrct +=(predicted == lbls).sum() используется как общее количество правильных прогнозов.
- print(‘Итерация: {}. Потеря: {}. Точность: {}’.format(iter, loss.item(), accu)) используется для печати точности на экране.
import torch import torch.nn as nn import torchvision.transforms as transform import torchvision.datasets as dtsets traindt = dtsets.MNIST(root='./data', train=True, transform=transform.ToTensor(), download=True) testdt = dtsets.MNIST(root='./data', train=False, transform=transform.ToTensor()) batchsiz = 80 nitrs = 2800 numepoch = nitrs /(len(traindt) / batchsiz) numepoch = int(numepoch) trainldr = torch.utils.data.DataLoader(dataset=traindt, batch_size=batchsiz, shuffle=True) testldr = torch.utils.data.DataLoader(dataset=testdt, batch_size=batchsiz, shuffle=False) class rnn(nn.Module): def __init__(self, inpdim, hidendim, layerdim, outpdim): super(rnn, self).__init__() self.hidendim = hidendim self.layerdim = layerdim self.rnn = nn.RNN(inpdim, hidendim, layerdim, batch_first=True, nonlinearity='relu') self.fc = nn.Linear(hidendim, outpdim) def forward(self, y): h = torch.zeros(self.layerdim, y.size(0), self.hidendim).requires_grad_() outp, hx = self.rnn(y, h.detach()) outp = self.fc(outp[:, -1, :]) return outp inpdim = 28 hidendim = 80 layerdim = 1 outpdim = 10 mdl = rnn(inpdim, hidendim, layerdim, outpdim) criter= nn.CrossEntropyLoss() l_r = 0.01 optim = torch.optim.SGD(mdl.parameters(), lr=l_r) list(mdl.parameters())[0].size() seqdim = 28 itr = 0 for epoch in range(numepoch): for x,(imgs, lbls) in enumerate(trainldr): mdl.train() imgs = imgs.view(-1, seqdim, inpdim).requires_grad_() optim.zero_grad() outps = mdl(imgs) loss = criter(outps, lbls) loss.backward() optim.step() itr += 1 if itr % 500 == 0: mdl.eval() crrct = 0 ttl = 0 for imgs, lbls in testldr: imgs = imgs.view(-1, seqdim, inpdim) outps = mdl(imgs) _, predicted = torch.max(outps.data, 1) ttl += lbls.size(0) crrct +=(predicted == lbls).sum() accu = 100 * crrct / ttl print('Iteration: {}. Loss: {}. Accuracy: {}'.format(iter, loss.item(), accu))
Выход:
В следующем выводе мы видим, что точность модели rnn отображается на экране.
Бинарная классификация
Бинарная классификация может предсказывать один или два класса или классификацию нескольких классов, которая предполагает прогнозирование одного из более чем двух классов.
Код:
В следующем коде мы импортируем модуль факела, из которого мы сможем предсказать один или два класса с помощью двоичной классификации.
- устройство = torch.device(‘cuda’, если torch.cuda.is_available(), иначе ‘cpu’) используется в качестве конфигурации устройства.
- nn.Linear() используется для создания нейронной сети прямого распространения.
- modl = RNNModel(inpsize, hidsize, numlayrs, numclases).to(device).to(device) используется для инициализации модели RNN.
- optim = optim.Adam(modl.parameters(), lr = 0.01) используется для инициализации оптимизатора.
- print(f”num_epochs: {numepchs}”) используется для печати количества эпох.
import torch import torch.nn as nn from torchvision import datasets as dtsets from torchvision.transforms import ToTensor traindt = dtsets.MNIST( root = 'data', train = True, transform = ToTensor(), download = True, ) testdt = dtsets.MNIST( root = 'data', train = False, transform = ToTensor() ) from torch.utils.data import DataLoader ldrs = { 'train' : torch.utils.data.DataLoader(traindt, batch_size=100, shuffle=True, num_workers=1), 'test' : torch.utils.data.DataLoader(testdt, batch_size=100, shuffle=True, num_workers=1), } ldrs device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') device seqleng = 32 inpsize = 32 hidsize = 132 numlayrs = 6 numclases = 14 batchsiz = 100 numepchs = 6 l_r = 0.01 class RNNModel(nn.Module): def __init__(self, inpsiz, hidsize, numlayrs, numclases): super(RNNModel, self).__init__() self.hidden_size = hidsize self.num_layers = numlayrs self.lstm = nn.LSTM(inpsize, hidsize, numlayrs, batch_first=True) self.fc = nn.Linear(hidsize, numclases) modl = RNNModel(inpsize, hidsize, numlayrs, numclases).to(device).to(device) print(modl) losfunc = nn.CrossEntropyLoss() losfunc from torch import optim optim = optim.Adam(modl.parameters(), lr = 0.01) optim def train(numepchs, modl, ldrs): print(f"num_epochs: {numepchs}") print(f"model: {modl}") print(f"loaders['train']: {ldrs['train']}") train(numepchs, modl, ldrs)
Выход:
В следующем выводе мы видим, что двоичная классификация PyTorch RNN выполняется на экране.
Анализ настроений
Анализ настроений — это задача прогнозного моделирования, в которой модель обучается прогнозировать двойственность текстовых данных, таких как положительные, отрицательные или нейтральные.
Код:
- characts = set(».join(text)) используется для объединения всего предложения и извлечения уникального символа.
- int2char = dict(enumerate(characts)) используется для сопоставления целого числа с символом.
- inpseq.append(text[x][:-1]) используется для удаления последнего символа входной последовательности.
- targseq.append(text[x][1:]) используется для удаления первого символа из целевой последовательности.
- Features = np.zeros((batchsiz, seqleng, dicsiz), dtype=np.float32) создание многомерного массива с желаемыми выходными формами.
- Hiden = self.init_hidden(batchsiz) используется для инициализации скрытого состояния.
- modl = RNNModel(inpsize=dicsiz, outpsize=dicsiz, hiendim=12, nlayrs=1) создает экземпляр модели с гиперпараметром.
- optim = torch.optim.Adam(modl.parameters(), lr=l_r) используется для инициализации оптимизатора.
- print(‘Epochs: {}/{}………….’.format(epoch, nepchs), end=’ ‘) используется для печати эпох.
import torch from torch import nn import numpy as np text = ['hey Guides','How are you','Have a nice day'] characts = set(''.join(text)) int2char = dict(enumerate(characts)) char2int = {char: ind for ind, char in int2char.items()} maxleng = len(max(text, key=len)) for x in range(len(text)): while len(text[x])<maxleng: text[x] += ' ' inpseq = [] targseq = [] for x in range(len(text)): inpseq.append(text[x][:-1]) targseq.append(text[x][1:]) print("Input Sequence: {}\nTarget Sequence: {}".format(inpseq[x], targseq[x])) for i in range(len(text)): inpseq[i] = [char2int[character] for character in inpseq[x]] targseq[i] = [char2int[character] for character in targseq[x]] dicsiz = len(char2int) seqleng = maxleng - 1 batchsiz = len(text) def one_hot_encode(sequen, dicsiz, seqleng, batchsiz): features = np.zeros((batchsiz, seqleng, dicsiz), dtype=np.float32) for x in range(batchsiz): for y in range(seqleng): features[x, y, sequen[x][y]] = 1 return features inpseq = one_hot_encode(inpseq, dicsiz, seqleng, batchsiz) inpseq = torch.from_numpy(inpseq) target_seq = torch.Tensor(targseq) is_cuda = torch.cuda.is_available() if is_cuda: device = torch.device("cuda") print("gpu is available") else: device = torch.device("cpu") print("gpu is not available, CPU used") class RNNModel(nn.Module): def __init__(self, inpsize, outpsize, hidendim, nlayrs): super(RNNModel, self).__init__() # Defining some parameters self.hidendim = hidendim self.nlayrs = nlayrs #Defining the layers self.rnn = nn.RNN(inpsize, hidendim, nlayrs, batch_first=True) # Fully connected layer self.fc = nn.Linear(hidendim, outpsize) def forward(self, z): batchsiz = z.size(0) hiden = self.init_hidden(batchsiz) outp, hiden = self.rnn(z, hiden) outp = outp.contiguous().view(-1, self.hidendim) outp = self.fc(outp) return outp, hiden def init_hidden(self, batchsiz): hiden = torch.zeros(self.nlayrs, batchsiz, self.hidendim) return hiden modl = RNNModel(inpsize=dicsiz, outpsize=dicsiz, hidendim=12, nlayrs=1) modl.to(device) nepchs = 100 l_r=0.01 criter = nn.CrossEntropyLoss() optim = torch.optim.Adam(modl.parameters(), lr=l_r) for epoch in range(1, nepchs + 1): optim.zero_grad() inpseq.to(device) outp, hiden = modl(inpseq) loss = criter(outp, target_seq.view(-1).long()) loss.backward() optim.step() if epoch%10 == 0: print('Epochs: {}/{}.............'.format(epoch, nepchs), end=' ') print("Loss: {:.4f}".format(loss.item()))
Выход:
После запуска приведенного выше кода мы получаем следующий вывод, в котором видим, что эпохи и потери выводятся на экран.
Языковая модель
- Языковая модель RNN — это своего рода языковая модель нейронной сети, которая переносит модель RNN в сеть.
- RNN приемлем для моделирования последовательных данных, например, на естественном языке.
Код:
В следующем коде мы импортируем модуль torch, из которого мы знаем о модели обучения RNN.
- traindt = dtsets.MNIST(root=’dataset/’, train=True, Transform=transforms.ToTensor(), download=True) используется для загрузки набора данных.
- modl = RNNlM(inpsize, hidensize, numlayrs, numclasses, sequlen).to(device) используется для инициализации модели RNN.
- optim = optim.Adam(modl.parameters(), lr=l_r) используется для инициализации оптимизатора.
- print(f’Got {numcrct}/{numsmples} с точностью {float(numcrct)/float(numsmples)*100:.2f}’) modl.train() используется для печати точности модели.
import torch from tqdm import tqdm import torch.nn as nn import torch.optim as optim import torchvision.datasets as dtsets from torch.utils.data import DataLoader from torchvision.transforms import transforms device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') # Declaring Hyper-parameters inpsize = 28 sequlen = 28 numlayrs = 2 hidensize = 254 numclasses = 10 l_r = 0.001 batchsiz = 62 numepchs = 2 class RNNlM(nn.Module): def __init__(self, inpsize, hidensize, numlayrs, numclasses, sequlen): super(RNNlM, self).__init__() self.hidensize = hidensize self.numlayrs = numlayrs self.lstm = nn.LSTM(inpsize, hidensize, numlayrs, batch_first=True) self.fc = nn.Linear(hidensize*sequlen, numclasses) def forward(self, data): h = torch.zeros(self.numlayrs, data.size(0), self.hidensize).to(device) c = torch.zeros(self.numlayrs, data.size(0), self.hidensize).to(device) outp, _ = self.lstm(data,(h, c)) outp = outp.reshape(outp.shape[0], -1) outp = self.fc(outp) return outp traindt = dtsets.MNIST(root='dataset/', train=True, transform=transforms.ToTensor(), download=True) testdt = dtsets.MNIST(root='dataset/', train=False, transform=transforms.ToTensor(), download=True) trainldr = DataLoader(dataset=traindt, batch_size=batchsiz, shuffle=True) testldr = DataLoader(dataset=testdt, batch_size=batchsiz, shuffle=True) modl = RNNlM(inpsize, hidensize, numlayrs, numclasses, sequlen).to(device) criter = nn.CrossEntropyLoss() optim = optim.Adam(modl.parameters(), lr=l_r) # Training Loop ep = 1 for epoch in tqdm(range(numepchs), desc=f'Training model for epoch {ep}/{numepchs}', total=numepchs): for batch_idx,(data, trgt) in enumerate(trainldr): data = data.to(device).squeeze(1) trgts = trgt.to(device) scores = modl(data) loss = criter(scores, trgts) optim.zero_grad() loss.backward() optim.step() print(f'epoch: {epoch + 1} step: {batch_idx + 1}/{len(trainldr)} loss: {loss}') ep += 1 # Evaluating our RNN model def check_accuracy(ldr, modlrnnlm): if ldr.dataset.train: print('Check accuracy on training data') else: print('Check accuracy on test data') numcrct = 0 numsmples = 0 modlrnnlm.eval() with torch.no_grad(): for i,j in ldr: i = i.to(device).squeeze(1) j = j.to(device) score = modlrnnlm(i) _, predictions = score.max(1) numcrct +=(predictions == j).sum() numsmples += predictions.size(0) print(f'Got {numcrct}/{numsmples} with accuracy {float(numcrct)/float(numsmples)*100:.2f}') modl.train() check_accuracy(trainldr, modl) check_accuracy(testldr, modl)
Выход:
В следующем выводе мы видим, что точность данных поезда и тестовых данных выводится на экран.
Загрузчик данных
Набор данных загружает обучающие или тестовые данные в память, или загрузчик данных получает данные из набора данных и распределяет их по пакетам.
Код:
В следующем коде мы импортируем модуль факела, из которого мы сможем загрузить набор данных RNN.
- class RNN(nn.Module): используется для определения класса RNN.
- traindt = datasets.MNIST(root=’dataset/’, train=True, Transform=transforms.ToTensor(), download=True) используется в качестве набора данных.
- trainldr = DataLoader(dataset=traindt,atch_size=batchsiz, shuffle=True) используется для загрузки набора данных.
import torch from tqdm import tqdm import torch.nn as nn import torch.optim as optim import torchvision.datasets as datasets from torch.utils.data import DataLoader from torchvision.transforms import transforms device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') inpsize = 30 seqlen = 30 numlayrs = 4 hidensize = 258 numclasses = 12 lr = 0.001 batchsiz = 66 numepchs = 4 class RNN(nn.Module): def __init__(self, inpsize, hidensize, numlayrs, numclasses, seqlen): super(RNN, self).__init__() self.hidensize = hidensize self.numlayrs = numlayrs self.lstm = nn.LSTM(inpsize, hidensize, numlayrs, batch_first=True) self.fc = nn.Linear(hidensize*seqlen, numclasses) def forward(self, data): h1 = torch.zeros(self.numlayers, data.size(0), self.hidensize).to(device) c1 = torch.zeros(self.numlayers, data.size(0), self.hidensize).to(device) outp, _ = self.lstm(data,(h1, c1)) outp = outp.reshape(outp.shape[0], -1) outp = self.fc(outp) return outp traindt = datasets.MNIST(root='dataset/', train=True, transform=transforms.ToTensor(), download=True) testdt = datasets.MNIST(root='dataset/', train=False, transform=transforms.ToTensor(), download=True) trainldr = DataLoader(dataset=traindt, batch_size=batchsiz, shuffle=True) testldr = DataLoader(dataset=testdt, batch_size=batchsiz, shuffle=True)
Выход:
После запуска приведенного выше кода мы получаем следующий вывод, в котором видим, что данные модели RNN можно загрузить на экран.