如何使用 RNN 模型实现文本手动生成
优采云 发布时间: 2020-08-17 01:13如何使用 RNN 模型实现文本手动生成
在自然语言处理中,另外一个重要的应用领域,就是文本的手动撰写。关键词、关键词组、自动摘要提取都属于这个领域中的一种应用。不过这种应用,都是由多到少的生成。这里我们介绍其另外一种应用:由少到多的生成,包括短语的复写,由关键词、主题生成文章或者段落等。
基于关键词的文本手动生成模型
本章第一节就介绍基于关键词生成一段文本的一些处理技术。其主要是应用关键词提取、同义词辨识等技术来实现的。下面就对实现过程进行说明和介绍。
场景
在进行搜索引擎广告投放的时侯,我们须要给广告撰写一句话描述。一般情况下模型的输入就是一些关键词。比如我们要投放的广告为花束广告,假设广告的关键词为:“鲜花”、“便宜”。对于这个输入我们希望形成一定数目的候选一句话广告描述。
对于这些场景,也可能输入的是一句话,比如之前人工撰写了一个事例:“这个周末,小白花束只要99元,并且还包邮哦,还包邮哦!”。需要按照这句话复写出一定数目在抒发上不同,但是意思相仿的句子。这里我们就介绍一种基于关键词的文本(一句话)自动生成模型。
原理
模型处理流程如图1所示。
图1完成候选句子的提取以后,就要按照候选句子的数目来判定后续操作了。如果筛选的候选句子小于等于要求的数目,则根据语句相似度由低到高选定指定数目的短语。否则要进行短语的复写。这里采用同义词替换和按照指定模板进行改写的方案。
实现
实现候选句子估算的代码如下:
Map result = new HashMap();
if (type == 0) {//输入为关键词
result = getKeyWordsSentence(keyWordsList);
}else {
result = getWordSimSentence(sentence);
}
//得到候选集数量大于等于要求的数量则对结果进行裁剪
if (result.size() >= number) {
result = sub(result, number);
}else {
//得到候选集数量小于要求的数量则对结果进行添加
result = add(result, number);
}
实现句子相像筛选估算的代码如下。
for (String sen : sentenceList) {
//对待识别语句进行分词处理
List wordsList1 = parse(sentence);
List wordsList2 = parse(sen);
//首先判断两个语句是不是满足目标变换
boolean isPatternSim = isPatternSimSentence(wordsList1, wordsList2);
if (!isPatternSim) {//不满足目标变换
//首先计算两个语句的bi-gram相似度
double tmp = getBigramSim(wordsList1, wordsList2);
//这里的筛选条件是相似度小于阈值,因为bi-gram的相似度越小,代表两者越相似
if (threshold > tmp) {
result.put(sen,tmp);
}
}else {
result.put(sen,0.0);
}
}
拓展
本节处理的场景是:由文本到文本的生成。这个场景通常主要涉及:文本摘要、句子压缩、文本复写、句子融合等文本处理技术。其中本节涉及文本摘要和语句复写两个方面的技术。文本摘要如前所述主要涉及:关键词提取、短语提取、句子提取等。句子复写则按照实现手段的不同,大致可以分为如下几种。
基于统计模型和语义剖析生成模型的改写方式。这类方式就是按照语料库中的数据进行统计,获得大量的转换机率分布,然后对于输入的语料按照已知的先验知识进行替换。这类方式的语句是在剖析结果的基础上进行生成的,从某种意义上说,生成是在剖析的指导下实现的,因此,改写生成的诗句有可能具有良好的诗句结构。但是其所依赖的语料库是十分大的,这样就须要人工标明好多数据。对于这种问题,新的深度学习技术可以解决部份的问题。同时结合知识图谱的深度学习,能够更好地借助人的知识,最大限度地降低对训练样本的数据需求。RNN模型实现文本手动生成
6.1.2节介绍了基于短文本输入获得长文本的一些处理技术。这里主要使用的是RNN网路,利用其对序列数据处理能力,来实现文本序列数据的手动填充。下面就对其实现细节做一个说明和介绍。
场景
在广告投放的过程中,我们可能会遇见这些场景:由一句话生成一段描述文本,文本宽度在200~300字之间。输入也可能是一些主题的关键词。
这个时侯我们就须要一种依据少量文本输入形成大量文本的算法了。这里介绍一种算法:RNN算法。在5.3节我们早已介绍了这个算法,用该算法实现由拼音到汉字的转换。其实这两个场景的模式是一样的,都是由给定的文本信息,生成另外一些文本信息。区别是后者是生成当前元素对应的汉字,而这儿是生成当前元素对应的下一个汉字。
原理
同5.3节一样,我们这儿使用的还是Simple RNN模型。所以整个估算流程图如图3所示。
图3
代码
实现特点训练估算的代码如下:
public double train(List x, List y) {
alreadyTrain = true;
double minError = Double.MAX_VALUE;
for (int i = 0; i < totalTrain; i++) {
//定义更新数组
double[][] weightLayer0_update = new double[weightLayer0.length][weightLayer0[0].length];
double[][] weightLayer1_update = new double[weightLayer1.length][weightLayer1[0].length];
double[][] weightLayerh_update = new double[weightLayerh.length][weightLayerh[0].length];
List hiddenLayerInput = new ArrayList();
List outputLayerDelta = new ArrayList();
double[] hiddenLayerInitial = new double[hiddenLayers];
//对于初始的隐含层变量赋值为0
Arrays.fill(hiddenLayerInitial, 0.0);
hiddenLayerInput.add(hiddenLayerInitial);
double overallError = 0.0;
//前向网络计算预测误差
overallError = propagateNetWork(x, y, hiddenLayerInput,
outputLayerDelta, overallError);
if (overallError < minError) {
minError = overallError;
}else {
continue;
}
first2HiddenLayer = Arrays.copyOf(hiddenLayerInput.get(hiddenLayerInput.size()-1), hiddenLayerInput.get(hiddenLayerInput.size()-1).length);
double[] hidden2InputDelta = new double[weightLayerh_update.length];
//后向网络调整权值矩阵
hidden2InputDelta = backwardNetWork(x, hiddenLayerInput,
outputLayerDelta, hidden2InputDelta,weightLayer0_update, weightLayer1_update, weightLayerh_update);
weightLayer0 = matrixAdd(weightLayer0, matrixPlus(weightLayer0_update, alpha));
weightLayer1 = matrixAdd(weightLayer1, matrixPlus(weightLayer1_update, alpha));
weightLayerh = matrixAdd(weightLayerh, matrixPlus(weightLayerh_update, alpha));
}
return -1.0;
}
实现预测估算的代码如图下:
public double[] predict(double[] x) {
if (!alreadyTrain) {
new IllegalAccessError("model has not been trained, so can not to be predicted!!!");
}
double[] x2FirstLayer = matrixDot(x, weightLayer0);
double[] firstLayer2Hidden = matrixDot(first2HiddenLayer, weightLayerh);
if (x2FirstLayer.length != firstLayer2Hidden.length) {
new IllegalArgumentException("the x2FirstLayer length is not equal with firstLayer2Hidden length!");
}
for (int i = 0; i < x2FirstLayer.length; i++) {
firstLayer2Hidden[i] += x2FirstLayer[i];
}
firstLayer2Hidden = sigmoid(firstLayer2Hidden);
double[] hiddenLayer2Out = matrixDot(firstLayer2Hidden, weightLayer1);
hiddenLayer2Out = sigmoid(hiddenLayer2Out);
return hiddenLayer2Out;
}
拓展
文本的生成,按照输入方法不同,可以分为如下几种:
文本到文本的生成。即输入的是文本,输出的也是文本。图像到文本。即输入的是图象,输出的是文本。数据到文本。即输入的是数据,输出的是文本。其他。即输入的方式为非前面两者,但是输出的也是文本。因为这类的输入比较难归纳,所以就归为其他了。
其中第2、第3种近来发展得十分快,特别是随着深度学习、知识图谱等前沿技术的发展。基于图象生成文本描述的试验成果在不断被刷新。基于GAN(对抗神经网路)的图象文本生成技术早已实现了特别大的图谱,不仅还能依据图片生成非常好的描述,还能依据文本输入生成对应的图片。
由数据生成文本,目前主要应用在新闻撰写领域。中文和日文的都有很大的进展,英文的以路透社为代表,中文的则以腾讯公司为代表。当然这两家都不是纯粹地以数据为输入,而是综合了前面4种情况的新闻撰写。
从技术上来说,现在主流的实现方法有两种:一种是基于符号的,以知识图谱为代表,这类方式更多地使用人的先验知识,对于文本的处理更多地收录语义的成份。另一种是基于统计(联结)的,即按照大量文本学习出不同文本之间的组合规律,进而依据输入猜想出可能的组合形式作为输出。随着深度学习和知识图谱的结合,这三者有显著的融合现象,这应当是实现未来技术突破的一个重要节点。
编者按: 本书主要从语义模型解读、自然语言处理系统基础算法和系统案例实战三个方面,介绍了自然语言处理中相关的一些技术。对于每一个算法又分别从应用原理、数学原理、代码实现,以及对当前方式的思索四个方面进行讲解。
详情点击: