SiameseNet研究意义:
1、基于LSTM的孪生网络结构,为后来研究打下良好的基础,有很深远的影响
2、提出了几种文本增强的思路
注:
孪生网络指的是输入是成对的,并且两部分的网络结构和参数都是一样的,也就是只有一个网络
伪孪生网络是指模型输入相同,模型结构相同,但模型参数不共享
本文主要结构如下所示:
一、Abstract
摘要部分主要讲解本篇论文提出一个基于字符级别变长序列的双向LSTM网络结构,并且文中提出多种文本增强的思路,模型不仅能学到不同词之间的语义差异性与语义不变性
二、Introduction
主要介绍本文表示在自然语言处理中扮演者重要的角色,并且有很多的应用场景,并且说出了文本的语义表示,即不同的文本但是存在意思是一样的,如: 12pm、noon、12.00h,最后介绍了本文中的模型在岗位分类任务上的效果。
三、Related Work
主要介绍相关的工作,包括神经网络以及词表示最近几年在nlp任务中的发展,以及孪生网络的发展和应用,最后介绍相同语义的不同表示方法归一化问题
四、Siamese Recurrent Neural Network
主要讲解孪生网络的模型输入数据、相关参数矩阵介绍、对比损失函数公式介绍
五、Experiments
实验部分主要首先讲解了baseline模型n-gram matcher,然后介绍了文本数据增强的方法,主要有随机替换字符和一定比例的拼写错误、同义词替换、添加多余信息可以增加鲁棒性、以及人工反馈。
六、Discussion
最后一部分对本文进行总结,并提出了未来可以优化的方向
创新点: 利用孪生网络接收数据,双向LSTM网络提取特征,对比损失函数优化模型,并且提出多种文本数据增强的方法
启发点: 循环神经网络结构处理文本语义特征拥有比较好的表现
七、Code
# -*- coding: utf-8 -*-
# @Time : 2021/2/12 下午6:57
# @Author : TaoWang
# @Description : 定义网络结构
import torch
import torch.nn as nn
class SiameseNet(torch.nn.Module):
def __init__(self):
super(SiameseNet, self).__init__()
self.embedding = nn.Embedding(char_size, embedding_size)
self.embedding.weight.data.copy_(torch.from_numpy(embedding))
self.bi_lstm = nn.LSTM(embedding_size,
lstm_hidden_size,
num_layers=2,
dropout=0.3,
batch_first=True,
bidirectional=True)
self.dense = nn.Linear(linear_hidden_size, linear_hidden_size)
self.dropout = nn.Dropout(0.3)
def forward(self, a, b):
"""
:param a:
:param b:
:return:
"""
embedding_a = self.embedding(a)
embedding_b = self.embedding(b)
lstm_a, _ = self.bi_lstm(embedding_a)
lstm_b, _ = self.bi_lstm(embedding_b)
avg_a = torch.mean(lstm_a, dim=1)
avg_b = torch.mean(lstm_b, dim=1)
out_a = self.dropout(torch.tanh(self.dense(avg_a)))
out_b = self.dropout(torch.tanh(self.dense(avg_b)))
cos_dis = torch.cosine_similarity(out_a, out_b, dim=1, eps=1e-9)
return cos_dis
# 定义模型损失函数
class ContrastiveLoss(nn.Module):
def __init__(self):
super(ContrastiveLoss, self).__init__()
def forward(self, Ew, y):
"""
:param Ew:
:param y:
:return:
"""
L_1 = 0.25 * (1.0 - Ew) * (1.0 - Ew)
L_0 = torch.where(Ew < m * torch.ones_like(Ew), torch.full_like(Ew, 0), Ew) \
* torch.where(Ew < m * torch.ones_like(Ew), torch.full_like(Ew, 0), Ew)
loss = y * 1.0 * L_1 + (1 - y) * 1.0 * L_0
return loss.sum()