如何搭建一个简单的 NLP 神经网络?
假设我们一个变量名列表,根据这个变量名列表,学习其中的特征并生成新的变量名。训练一个模型用于预测下一个字符并生成新的变量名。使用一个单层的神经网络实现,假设我们的变量名只能用英文字母,作为网络的输入,使用 Onehot encoding,那么输入就是 (1, 27),使用 one hot 表示,添加一个特殊字符在作为开始和结束标志 “#”,首先用pytorh 创建 onehot。
# 例如我们有个名字的列表
names = ['one', 'two','three']
# XS 输入字符串为 #abc#
import torch
import torch.nn.functional as F
import matplotlib.pyplot as plt
xs = torch.tensor([0 ,1,2,3])
xenc = F.one_hot(xs, num_classes=27).float()
xenc
plt.imshow(xenc)
有了onehot 输入,我们添加一层神经元,wx + b,初始化 w,实现最简单的网络,这里的 b 就用 0,当层网络的数据就是 wx,wx 的输出是 Logits。
# 初始化 w
W = torch.randn((27, 1))
xenc @ w
这里使用 27 个神经元,因为要预测 27 种可能性。并将输出转为概率,目标是预测下一个字母,结果中表示每个输入对应 27 个字符输出的概率。
g = torch.Generator().manual_seed(2147483647)
W = torch.randn((27, 27), generator=g)
logits = xenc @ W # predict log-counts
counts = logits.exp() # counts, equivalent to N
probs = counts / counts.sum(1, keepdims=True) # probabilities for next character
之后,定义损失函数,使用 likelyhood 损失函数。在没有经过训练的情况下,loss 的值很高。
ys = torch.tensor([1,2,3,0])
loss = -probs[torch.arange(4), ys].log().mean()
loss
进行梯度计算,并调整 w。反向计算通过链式法则计算每个参数对loss 的影响并进行微调。
# backward pass
W.grad = None # set to zero the gradient
loss.backward()
W.data += -0.1 * W.grad
总结
本文创建了一个简单的神经网络,输入、输出、Loss 和反向计算实现一个简单的神经网络,通过整个流程可以了解神经网络的基本工作原理。