Изменения

Перейти к: навигация, поиск

Рекурсивные нейронные сети

4645 байт добавлено, 19:30, 13 апреля 2020
Примеры кода
При обучении последовательных структур и деревьев в задачах обработки естественного языка, фразы и предложения моделируются через векторное представление слов. 
Базовая структура сети является бинарным деревом, состоящим из родительского компонента (корня), и дочерних компонентов (листьев) Каждая группа . Каждый компонент - набор нейронов, размер которого зависит от сложности входных данных. Входная последовательность данных подаются подаётся на листья, а корень использует классификатор для определения класса и меры (score)
Рекурсивная нейронная сеть использует следующую формулу для вычисления родительского вектора:
*<math>f</math> — нелинейную функция активации типа гиперболического тангенса
*<math>bias</math> - cмещение, оно может быть добавлено в качестве дополнительного столбца к <math>W</math>, если к конкатенации входных векторов добавляется 1.
Родительские векторы должны иметь одинаковую размерность, чтобы быть рекурсивно совместимыми и использоваться в качестве входных данных для следующей композиции.
Последующие шаги получают на вход score меру предыдущего корня и следующее слово последовательности, таким образом пока в сети не будет сформировано дерево со всеми словами в последовательности.
Деревья могут иметь разную структуру, выбор лучшей подструктуры дерева для сети основывается на их мере. Мера дерева - сумма мер на каждом узле:
==Примеры кода==
[[File:Rntn-layer.png|450px|thumb| Визуализация тензорной нейронной сети]]
 
Опишем здесь пример построения сети, опустив построение дерева.
[https://github.com/yc930401/RecNN-pytorch Полный листинг кода для анализа тональности текста на PyTorch] (из статьи [https://nlp.stanford.edu/~socherr/EMNLP2013_RNTN.pdf Socher et al.(2013c)])
 
class RNTN(nn.Module):
def __init__(self, word2index, hidden_size, output_size):
super(RNTN,self).__init__()
<font color="green"># Для рекурсивной нейронной сети обязательно нужно для векторное представление слов</font>
self.word2index = word2index
self.embed = nn.Embedding(len(word2index), hidden_size)
self.V = nn.ParameterList([nn.Parameter(torch.randn(hidden_size * 2, hidden_size * 2)) for _ in range(hidden_size)]) <font color="green"># Тензор</font>
self.W = nn.Parameter(torch.randn(hidden_size * 2, hidden_size))
self.b = nn.Parameter(torch.randn(1, hidden_size)) <font color="green"># bias</font>
self.W_out = nn.Linear(hidden_size, output_size)
<font color="green"># инициализация весов</font>
def init_weight(self):
nn.init.xavier_uniform(self.embed.state_dict()['weight'])
nn.init.xavier_uniform(self.W_out.state_dict()['weight'])
for param in self.V.parameters():
nn.init.xavier_uniform(param)
nn.init.xavier_uniform(self.W)
self.b.data.fill_(0)
<font color="green"># прямое распространение</font>
def tree_propagation(self, node):
recursive_tensor = OrderedDict()
current = None
if node.isLeaf:
tensor = Variable(LongTensor([self.word2index[node.word]])) if node.word in self.word2index.keys() \
else Variable(LongTensor([self.word2index['<UNK>']]))
current = self.embed(tensor) # 1xD
else:
recursive_tensor.update(self.tree_propagation(node.left))
recursive_tensor.update(self.tree_propagation(node.right))
concated = torch.cat([recursive_tensor[node.left], recursive_tensor[node.right]], 1) <font color="green"># 1x2D</font>
xVx = []
for i, v in enumerate(self.V):
xVx.append(torch.matmul(torch.matmul(concated, v), concated.transpose(0, 1)))
xVx = torch.cat(xVx, 1) # 1xD
Wx = torch.matmul(concated, self.W) # 1xD
current = F.tanh(xVx + Wx + self.b) # 1xD
recursive_tensor[node] = current
return recursive_tensor
 
def forward(self, Trees, root_only=False):
propagated = []
if not isinstance(Trees, list):
Trees = [Trees]
for Tree in Trees:
recursive_tensor = self.tree_propagation(Tree.root)
if root_only:
recursive_tensor = recursive_tensor[Tree.root]
propagated.append(recursive_tensor)
else:
recursive_tensor = [tensor for node,tensor in recursive_tensor.items()]
propagated.extend(recursive_tensor)
propagated = torch.cat(propagated) # (num_of_node in batch, D)
return F.log_softmax(self.W_out(propagated),1)
 
===Обучение===
 
HIDDEN_SIZE = 30
BATCH_SIZE = 20
EPOCH = 20
LR = 0.01
LAMBDA = 1e-5
RESCHEDULED = False
for epoch in range(EPOCH):
losses = []
<font color="green"># learning rate annealing</font>
if RESCHEDULED == False and epoch == EPOCH // 2:
LR *= 0.1
optimizer = optim.Adam(model.parameters(), lr=LR, weight_decay=LAMBDA) <font color="green"># L2 нормализация</font>
RESCHEDULED = True
for i, batch in enumerate(getBatch(BATCH_SIZE, train_data)):
if ROOT_ONLY:
labels = [tree.labels[-1] for tree in batch]
labels = Variable(LongTensor(labels))
else:
labels = [tree.labels for tree in batch]
labels = Variable(LongTensor(flatten(labels)))
model.zero_grad()
preds = model(batch, ROOT_ONLY)
loss = loss_function(preds, labels)
losses.append(loss.data.tolist()[0])
loss.backward()
optimizer.step()
if i % 100 == 0:
print('[%d/%d] mean_loss : %.2f' % (epoch, EPOCH, np.mean(losses)))
losses = []
 
 
Примеры кода на TensorFlow:
*https://github.com/bogatyy/cs224d/tree/master/assignment3

Навигация