实验4:自然语言处理前馈网络

简单感知机可以用于解决二分类问题,但在线性不可分问题和多维度数据中存在短板,本次我们学习前馈神经网络,包括多层感知机和卷积神经网络。

1、前馈神经网络

1.1多层感知机

多层感知机相比简单感知机具有更强的计算能力,它引入了隐藏层来处理非线性问题。隐藏层的神经元可以学习到更复杂的特征表示,从而提升分类准确度。多层感知机通过反向传播算法来训练神经网络,不断优化权重和阈值,使得网络能够逐渐逼近目标函数。

1.1.1多层感知机结构

多层感知机包括三个层次,由输入层,隐藏层,输出层构成。每个层都由多个神经元组成,每个神经元与上一层的所有神经元相连接。多层感知机的基本原理是通过输入层接收输入数据,然后通过权重与偏置进行线性组合和激活函数处理,最终得到输出结果。

最简单的多层感知机由三个表示阶段和两个线性层组成。第一阶段是输入向量。这是给定给模型的向量。给定输入向量,第一个线性层计算一个隐藏向量——表示的第二阶段。隐藏向量之所以这样被调用,是因为它是位于输入和输出之间的层的输出。使用这个隐藏的向量,第二个线性层计算一个输出向量。

1.1.2多层感知机工作原理

输入传递:输入数据经过输入层传递到隐藏层,每个神经元对输入进行加权和,并将结果应用非线性激活函数(如Sigmoid、ReLU等),生成隐藏层的输出。

隐藏层传递:隐藏层的输出再传递到下一个隐藏层,依次类推,直到传递到输出层。每一层的输出作为下一层的输入,通过权重和激活函数处理。

输出生成:输出层接收最后一个隐藏层的输出,应用适当的激活函数(如Softmax用于分类任务、恒等函数用于回归任务),生成最终的预测结果。

1.1.3多层感知机优势

多层感知机通过多层隐藏层进行特征提取和抽象,提高了模型的表达能力和学习能力。MLP能够适应各种数据类型和问题,包括分类和回归任务,在合适的数据量和参数设置下能够表现出很好的泛化能力,成为解决实际问题的强大工具。

1.2卷积神经网络

卷积神经网络(Convolutional Neural Network,CNN)是一种深度学习模型,特别适用于处理具有网格结构(比如图像、音频)的数据。

1.2.1卷积

定义卷积核:卷积操作需要一个卷积核(也称为滤波器),它是一个小的矩阵,包含一些权重参数。

滑动窗口:将卷积核与输入数据进行卷积操作时,需要选择一个初始位置,然后按照一定的步幅(stride)和方向(水平、垂直)进行滑动,将卷积核的每个元素与输入数据中对应位置的元素相乘。

点积运算:将卷积核的每个元素与输入数据中对应位置的元素相乘后,再将所有乘积结果相加,得到一个数值。

输出特征图:将滑动窗口在输入数据上移动后,得到的所有数值放到一个新的矩阵中,即为输出特征图。

1.2.2卷积神经网络结构

输入层:接收原始数据,并将其转化为适合卷积操作的形式,通常是一个多维的数组。

卷积层:用于对输入数据进行特征提取。卷积层包含多个卷积核,每个卷积核与输入数据进行卷积操作,生成特征图。

池化层:用于对特征图进行下采样,减少特征图的尺寸和参数数量,常用的池化操作有最大池化和平均池化。

全连接层:将池化层输出的特征图转化为一个一维向量,并通过全连接层进行分类或回归等任务。

输出层:根据具体的任务,选择适当的激活函数来处理全连接层的输出,例如对于二分类任务可以使用Sigmoid函数,多分类任务可以使用Softmax函数。

2、多层感知机处理姓氏分类到其原籍国任务

我们用PyTorch的两个线性模块实例化了这个想法。线性对象被命名为fc1和fc2,它们遵循一个通用约定,即将线性模块称为“完全连接层”,简称为“fc层”。除了这两个线性层外,还有一个修正的线性单元(ReLU)非线性(在实验3“激活函数”一节中介绍),它在被输入到第二个线性层之前应用于第一个线性层的输出。由于层的顺序性,必须确保层中的输出数量等于下一层的输入数量。使用两个线性层之间的非线性是必要的,因为没有它,两个线性层在数学上等价于一个线性层4,因此不能建模复杂的模式。MLP的实现只实现反向传播的前向传递。这是因为PyTorch根据模型的定义和向前传递的实现,自动计算出如何进行向后传递和梯度更新。

2.1代码实现

class MultilayerPerceptron(nn.Module):
    def __init__(self, input_dim, hidden_dim, output_dim):
        """
        Args:
            input_dim (int): the size of the input vectors
            hidden_dim (int): the output size of the first Linear layer
            output_dim (int): the output size of the second Linear layer
        """
        super(MultilayerPerceptron, self).__init__()
        self.fc1 = nn.Linear(input_dim, hidden_dim)
        self.fc2 = nn.Linear(hidden_dim, output_dim)

    def forward(self, x_in, apply_softmax=False):
        """The forward pass of the MLP

        Args:
            x_in (torch.Tensor): an input data tensor.
                x_in.shape should be (batch, input_dim)
            apply_softmax (bool): a flag for the softmax activation
                should be false if used with the Cross Entropy losses
        Returns:
            the resulting tensor. tensor.shape should be (batch, output_dim)
        """
        intermediate = F.relu(self.fc1(x_in))
        output = self.fc2(F.dropout(intermediate, p=0.5))

        if apply_softmax:
            output = F.softmax(output, dim=1)
        return output

训练函数定义:

classifier = classifier.to(args.device)
dataset.class_weights = dataset.class_weights.to(args.device)

try:
    for epoch_index in range(args.num_epochs):
        train_state['epoch_index'] = epoch_index

        for batch_index, batch_dict in enumerate(batch_generator):
            # the training routine is these 5 steps:

            # --------------------------------------
            # step 1. zero the gradients
            optimizer.zero_grad()

            # step 2. compute the output
            y_pred = classifier(batch_dict['x_surname'])

            # step 3. compute the loss
            loss = loss_func(y_pred, batch_dict['y_nationality'])
            loss_t = loss.item()
            running_loss += (loss_t - running_loss) / (batch_index + 1)

            # step 4. use loss to produce gradients
            loss.backward()

        train_state['train_loss'].append(running_loss)
        train_state['train_acc'].append(running_acc)

        train_bar.n = 0
        val_bar.n = 0
        epoch_bar.update()
except KeyboardInterrupt:
    print("Exiting loop")

训练损失和准确率:

classifier.load_state_dict(torch.load(train_state['model_filename']))


for batch_index, batch_dict in enumerate(batch_generator):
    # compute the output
    y_pred =  classifier(batch_dict['x_surname'])
    
    # compute the loss
    loss = loss_func(y_pred, batch_dict['y_nationality'])
    loss_t = loss.item()
    running_loss += (loss_t - running_loss) / (batch_index + 1)

train_state['test_loss'] = running_loss
train_state['test_acc'] = running_acc

print("Test loss: {};".format(train_state['test_loss']))
print("Test Accuracy: {}".format(train_state['test_acc']))

一些关键函数:

def make_train_state(args):
    return {'stop_early': False,
            'early_stopping_step': 0,
            'early_stopping_best_val': 1e8,
            'learning_rate': args.learning_rate,
            'epoch_index': 0,
            'train_loss': [],
            'train_acc': [],}

def set_seed_everywhere(seed, cuda):
    np.random.seed(seed)
    torch.manual_seed(seed)
    if cuda:
        torch.cuda.manual_seed_all(seed)

def handle_dirs(dirpath):
    if not os.path.exists(dirpath):
        os.makedirs(dirpath)

2.2实验结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值