皓哥娱乐
当前位置:首页 - 小说 >

翻译 | 详解自然语言处理发展的点点滴滴

2019-07-22来源:艾肯家电网


Recent Trends in Deep Learning Based Natural Language Processing是一篇发表在IEEE Computational Intelligence Magazine 上的一篇论文,全文32页,详细讲述了有关自然语言处理发展的点点滴滴。

Recent Trends in Deep Learning Based Natural Language Processing》:https://arxiv.org/pdf/1708.02709.pdf

原文翻译链接:https://zhuanlan.zhihu.com/p/51479851

                         阅读该文大概需要15分钟左右。

Abstract

深度学习方法利用多层处理结构来学习数据中的层次化表示,在很多领域都得到了SOTA的结果。最近几年,NLP领域涌现了大量的深度学习模型和方法,这篇文章总结了一些比较重要的在NLP领域广泛应用的深度学习方法,并回顾其发展历程。通过总结和对比不同的模型,让我们对NLP中的深度学习有了一个更详细的了解。

Introduction

自然语言处理(NLP)是一门为了自动分析和表达人类语言的理论驱动的计算机技术。NLP的研究最早可以追溯到打孔卡和批处理时代,在当时,处理一句话就要7分钟,而现在,我们可以在1秒钟内处理上百万的网页[1]。NLP 使得计算机可以执行各种各样不同层次的自然语言相关任务,从词性标注到机器翻译到对话系统。

深度学习架构和算法已经在诸如计算机视觉和模式识别领域取得了令人瞩目的成果。在这一趋势下,最近NLP领域的研究也日益聚焦到深度学习方法(Fig. 1)。几十年来,针对NLP问题的机器学习方法都是基于高维稀疏特征训练浅层模型(如SVM和logistic regression),在过去几年中,基于神经网络的稠密向量表示已经在很多NLP任务上得到了更好的结果,主要是词向量[2, 3]的成功和深度学习方法[4]引领了这一趋势。与此对比的是,基于传统机器学习的NLP系统往往依赖于手工提取特征,不仅费时费力,而且往往不全。

Collobert et al [5] 用一个简单的深度学习框架就在诸如命名实体识别、语义角色标注和词性标注等NLP任务上打败了最先进的方法。从那开始,大量的复杂的基于深度学习的算法被提出来解决各种NLP任务。这篇文章总结了在NLP领域广泛应用的深度学习方法,包括CNN,RNN,同时也讨论了memory-augment strategies、注意力机制以及最近的无监督模型、强化学习方法、深度生成模型如何用在NLP相关任务中。

这篇文章结构如下:第二部分介绍复杂深度学习模型的基础——分布式表示的相关概念;第三、四、五部分主要讨论主流模型,包括CNN,RNN等;第六部分是关于强化学习在NLP中的应用以及无监督句子表示学习;然后,第七部分阐述了近年来深度学习模型与存储模块结合的发展趋势;最后,第八部分总结了一系列深度学习方法在相关NLP标准数据集上的表现。

Distributed Representation

A. Word Embeddings

分布式词向量(Fig. 2)本质上遵循这样一个假设,意思相近的词趋向于出现在相似的上下文中。因此,这些词向量试图捕捉相似词之间的特征,能学到词汇之间的相似性是词向量的一个主要优点。有了词向量之后,词之间的相似度就可以用词向量的相似度来度量,比如余弦距离。词向量一般用于NLP深度学习模型中的第一层。通常而言,词向量是在大规模无标注语料上预训练得到的,预训练目标一般是额外定义的,比如基于上下文预测词[8, 3],这样学到的词向量能够捕捉到通用的句法和语法信息。所以,词向量在捕捉上下文相似性、类比性方面非常有效,而且由于词向量维度低,所以计算效率也非常高。

这些年来,用于产生词向量的模型一直是浅层神经网络,并不需要特别复杂的深度学习模型来生成词向量,然而,基于深度学习的NLP模型无一例外都是用的这些词向量,用来表示词、短语、甚至句子。词向量实际上是基于词计数的传统模型和基于深度学习的NLP模型的主要差异。所以,实际上可以说是词向量的广泛应用导致了NLP领域很多SOTA的诞生[9, 10, 11, 12]。

举几个例子,Glorot et al [13] 将词向量加堆叠降噪自动编码机用于领域自适用情感分类,Blunsom[14] 提出了使用组合分类编码器来学习组合句子。从这些例子中也能看出词向量的有效性及其应用的广泛性。

词的分布式表示通常是从上下文中学到的。在上个世纪90年代,相关研究进展就奠定了分布式语义研究的基础。详细情况可以参考早期综述[16, 17]。在这基础上,后来发展出了主题模型(LDA)和语言模型。这些工作奠定了自然语言表示学习的基础。

2003年,Bengio et al [7] 提出了一种可以学习词的分布式表示的神经网络语言模型(Fig. 3)。作者认为,有了词的表示,可以按词序列的联合概率来表示句子,这样可以产生指数级数量的语义相近的句子。因此,可以提升模型的泛化能力,比如,对于没见过的句子,模型可以通过见到的类似的词组成的类似的句子来学到相关性。

Collobert 和 Weston [19] 是第一个证明词向量预训练效果的。他们提出了一种奠基性的神经网络架构。这个工作也确立了词向量作为NLP任务有用工具的地位。然而,词向量的广泛普及却是Mikolov 等人 [3] 的功劳,他们提出了CBOW和skip-gram模型来有效构建高质量的分布式向量表示。他们的词向量表现出来的组合特效(意料之外的副产物)促使其快速流行开来,例如,两个词向量相加得到的词向量是对应的两个词的语义组合对应的向量,例如:vec('man') + vec('royal') = vec('king')。最近,Gittens等人 [20] 给出了这种行为的理论依据,这种组合性只在一定的假设下才成立:词向量在表示空间的分布必须是均匀的。

Pennington等人 [21] 提出的GloVe是另一个有名的词向量算法,其本质上是一种基于词计数的方法。首先,对词的共现次数矩阵进行归一化和对数平滑操作,然后基于最小重构误差对矩阵进行分解得到词的低维分布式表示。

下面,我们对Mikolov等人 [3] 提出的word2vec 进行简单介绍。

B. Word2vec

Mikolov等人[3] 提出的CBOW和skip-gram模型彻底改变了词向量并使其广为流传。CBOW计算给定上下文时目标词的条件概率,skip-gram恰恰相反,计算给定中心词时上下文词的条件概率。上下文定义为中心词汇左右两边各k个词。在无监督的情况下,词向量的维度由预测的精度决定,一般而言,词向量维度越大,预测精度越高,直到收敛到某个点。

下面我们具体来看一个简化版的CBOW模型,我们只考虑一个词作为上下文,这本质上是一个二元语法模型。

如Fig. 4所示,CBOW模型仅仅只是一个包含单个隐含层的全连接神经网络。输入层一共V个结点,V是词表大小,输入one-hot编码的上下文词汇,隐含层一共N个结点,输出层使用softmax归一化得到预估的词的概率分布。输入层和隐含层之间连接矩阵W大小为V*N,隐含层和输出层之间连接矩阵W'大小为N*V。 每个词均对应2个向量,上下文向量和目标词向量,分别对应W和W' 中与该词相连的参数。根据这个结构,可以得到给定上下文c时出现目标词w的概率:

然后通过优化对数似然概率得到模型参数 

在通常的CBOW模型中,上下文词一般有多个,相当于输入向量中有多个1,隐含层h的结果就是所有上下文词向量的和,这样做的局限是由此得到句子的表示本质上是词袋模型,词之间组合、顺序都没法考虑。所以后来就有人提出了直接把ngram当成词来训练[23]。

由于词向量一般都是基于左右几个词作为上下文来训练,这样会导致另一个问题,比如“好”和“坏”的上下文可能差不多,最后就训练出来“好”和“坏”的词向量也近似[24],这种词向量用于情感分析就会出问题[25]。因此,Tang等人[26] 提出了sentiment specific word embedding,训练词向量的时候,在损失函数中引入情感极性作为监督信号来缓解该问题。

使用词向量时需要注意的是它们和具体任务高度相关,Labutov 和Lipson 等人[27] 提出了特定于任务的词向量,通过微调将词向量对齐到当前任务空间。由于从头开始训练词向量需要大量时间和资源,所以一般都是基于预训练的结果进行微调。为了缓解词向量训练慢的问题,Mikolov等人 [8] 提出了负采样的方法,训练模型的时候对负样本按频率采样。

传统的词向量算法一般都是每个词对应一个唯一的词向量,这也导致了无法处理一词多义的情况。在最近的研究中,Upadhyay等人[28] 提出了解决这一缺点的创新性方法。作者利用多语言平行语料来学习一词多义的词向量。比如,英语中的bank,翻译到法语就对应两个不同的词banc和banque,分别表示金融和地理学方面的含义,利用这种多语言分布信息有助于解决一词多义问题。

表I 列出了现有流行的词向量计算框架。

C. 字向量

虽然词向量可以捕捉句法和语义信息,但是对于像词性标注和命名实体识别这样的任务而言,单词内部形态和形状等信息也非常有用。就目前而言,基于字级别来构建自然语言理解系统已经吸引了一定的研究关注[29, 30, 31, 32]。在形态学信息丰富的语言上,在相关NLP任务上利用字的表征信息已经取得了更好结果。Santos 和 Guimaraes [31] 利用字的表示加上词向量在葡萄牙语和西班牙语命名实体识别上取得了最好的结果。Kim 等人[29] 仅利用字嵌入向量构建神经语言模型并取得了不错的结果。Ma 等人 [33] 在做命名实体识别的时候利用了好几种嵌入向量,包括trigram 字向量,将原始信息和分层信息结合起来用于训练label的嵌入表征。

对于词汇量大的语言来说,一个常见的现象是存在大量未登录词,也叫袋外词。基于字的表征天然就能处理这种情况,因为每个词都是由字构成的。在有些语言中,文本本身是由字构成的,词的语义由字的组合决定,比如中文,基于字的表征构建系统还可以避免分词的问题[34]。 因此,在这些语言上很多深度学习的工作都倾向于基于使用字向量[35]。比如,Peng等人 [36] 证明了radical-level processing可以显著提升情感分类性能,作者提出了两类中文radical-based分层嵌入,结合了radical和字级别的语义以及情感极性信息。Bojanowski等人 [37] 也尝试在形态学信息丰富的语言中用字的表示信息来改善词的表示。他们采用了skip-gram的方法将词表示为字符的ngram,因此他们的模型一方面具有skip-gram的优点,同时也解决了词向量中长期存在的问题。而且该方法速度快,可在大规模语料上快速训练模型,这就是著名的FastText,在速度、可伸缩性和有效性方面均优于之前的方法。

除了字向量之外,学者们也提出了很多其他方法来解决未登录词的问题。Herbelot和Baroni等人 [38] 提出了一种动态处理OOV的方法,将未登录词初始化为上下文词向量的和并且使用较大的学习率进行微调,然而,他们的方法有待在典型NLP任务上进行测试。Pinter等人 [39] 提出了一种有趣的方法,通过训练字向量来重建预训练的词向量,这使其可以学到从字组合成词的组合映射,从而可以处理未登录词问题。

尽管词向量越来越火,最近也出现了一些关于其relevance in the long run的讨论。例如,Lucy和Gauthier等人[40] 最近尝试评估词向量如何捕捉单词概念意义的必要方面,作者发现,词向量在感知理解单词背后的概念方面存在严重局限性,因为这些不是仅从分布语义表征就能推断。缓解这些缺陷的一个可能的方向是grounded learning,它在这个领域已经越来越流行。

D. Contextualized Word Embeddings

词向量的好坏一般体现在其捕捉句法信息及处理多义词的能力,这些能改善词向量的语义特性。最近有一些方法开始研究如何把上下文的信息融合进词向量,比如通过使用更深的网络将词向量表示为上下文的函数。

传统的词嵌入方法,比如Word2Vec和GloVe都是对每个词计算一个全局唯一的词向量,然而,一个词在不同的上下文中往往表达的语义也不同。比如,"The bank will not be accepting cash on Saturdays" 和 "The river overflowed the bank" 两句话里的bank语义明显不同。合理来讲,上面两句话中的bank应该需要两个不同的词向量。因此,新出现了一类词向量模型,与传统词向量模型的不同之处在于,每个词的表征不是全局静态的,而是与词所在的上下文相关的。

ELMo [41] 就是这类方法之一,ELMo 利用每个词所在的上下文来生成该词的词向量,因此可以表达词在不同句子中的不同意思,比如,对于在N句话中都出现过的词w而言,ELMo可以为w生成N个不同的词向量。

ELMo的计算主要是基于从双向语言模型中获得的表征。双向语言模型包括两个语言模型,一个前向的和一个后向的。每个语言模型都是L层的LSTM构成,每一层LSTM的输出都是输入层的deep contextual representation,最后计算词向量的时候,会用到词的原始表征以及两个语言模型的各个隐含层的表征,一共2L+1个

上式中 

是softmax归一化的权重,用来组合不同层的表征, 

是任务相关的超参数,主要是为了调整词向量的数值范围方便优化。据Peters 等人 [41] ,将ELMo和原词向量结合使用总能得到更好的结果。

在这不久之后,预训练语言模型就受到越来越多的关注[43]。因为语言模型具备自然语言理解和生成的多重特性,所以被选作预训练的目标。一个好的语言模型需要能学到语言的复杂特性,包括句法特征以及语义一致性。通过预训练语言模型,可以为词向量注入更丰富的语言特征,因此比随机初始化效果要好。生成式模型预训练一般需搭配判别式模型微调,因为预训练是无监督的、缺乏人工标注信息。

Radfrod等人 [44] 提出了一种类似的预训练模型,OpenAI-GPT,采用了Transformer的结构。最近,Devlin等人 [45] 提出了BERT,也是用的transformer网络结构,与ELMo和OpenAI-GPT不同的是,BERT在预训练的时候,按一定比例随机掩盖训练语料中的一些词,然后让模型来预测被掩盖的词,除此之外,还引入了另一个训练目标,给定当前的句子预测下一个句子,这个目标尝试对句子之间的关系进行建模,这是传统的语言模型预训练无法做到的。最终,BERT在诸如QA、NLI等一系列关键NLP任务上以显著优势击败了当前最优结果。

上述上下文相关的词向量能改善模型效果,预训练深度语言模型以迁移学习的方式为下游任务提供了一个良好的开端。这些方法在计算机视觉领域已经广为流行,这是否是NLP领域的未来趋势呢?研究人员在传统模型和这些新方法中如何抉择呢?未来见分晓。

Convolutional Neural Networks

随着词向量的普及,需要有一种有效的特征抽取函数,来从底层词向量提取高层次特征,然后这些高层特征可以用于各种NLP任务,比如情感分析、自动摘要、机器翻译和问答等。鉴于CNN在计算机视觉中的出色表现[46, 47, 48, 49],很自然的人们尝试将其用到NLP任务中。

将CNN用于句子建模最早可以追溯到Collobert和Weston等人 [19]的研究,他们利用多任务学习来预测多个NLP任务,包括词性标注、命名实体识别、语义角色标注和语言模型。他们首先利用查找表将词映射到向量(Fig. 5)。

这可以看成是一种原始的词向量方法,词向量是在模型训练的时候学到的。后来,Collobert [5] 对这个工作做了进一步拓展,提出了一个基于CNN的通用框架来解决各种NLP任务。这些工作引导了CNN在NLP研究者中的普及。鉴于CNN在计算机视觉中的出色表现,人们很容易相信将其用于NLP效果也会不错。

CNN可以从输入的句子中提取显著的n元语法特征,从而得到信息量丰富的潜在语义表征用于下游任务。Collobert [5],Kalchbrenner [49],Kim [50]等人率先将CNN用于NLP任务中,直接导致后续相关研究中出现了大量的基于CNN的网络结构,下面,我们简单描述基于CNN对句子建模的原理:

A. Basic CNN

1)句子建模:对于每个句子,记 

为句子中第i个词的词向量,其中d是词向量维度。假设句子中有n个词,那么句子就可以表示为 

 ,Fig. 6描述这样一句话是如何作为CNN框架的输入。

CNN的计算过程如下:

其中 

 是从i个词开始的连续h个词对应的词向量的拼接,h是CNN 卷积核的宽度,b是偏置项,最后将所有位置的输出拼起来就得到了特征映射向量 

  在CNN中,一般会用多个大小不同的卷积核,每个卷积核可以抽取特定的n元语法特征。卷积层后面一般会接上最大池化层,相当于在所有卷积核输出中选最大的,这样做主要有两个理由:

首先,经过最大池化后,可以得到长度固定的输出,一般做分类任务的都要求最后一层输出维度是固定的。通过池化层,输入长度不一样的句子,最后都能得到长度相同的向量。其次,最大池化可以有效降低输出维度同时保存最显著的n元语法特征。这是通过位置不变性来保证的,因为每个卷积核都可以从任何位置提取特征(比如,表示否定的词)然后加到最后的特征映射中。

词向量可以随机初始化也可以在大量无标注语料上预训练得到(如第二章所述),预训练的方式往往效果更好,特别是有标签样本特别少的时候[50],然后后面可以叠加卷积层和最大池化层,这样就得到了深度CNN网络。深度CNN网络有助于挖掘句子中包含丰富语义信息的高层抽象表示。越深层的卷积核可以覆盖更多的词直到覆盖整个句子,从而能得到句子全局特征表示。

2)基于窗口的方法:上面提到的CNN架构可以对整句话建模,然而,在很多NLP任务中,比如命名实体识别、词性标注以及语义角色标注中,我们需要对每个词都预测一个输出。为了将CNN用于这一类任务,基于窗口建模的方法被提出来了,这是基于这样一个假设:一个词对应的标注往往取决于其相邻的词。所以,基于窗口建模的方法,将每个词及其左右窗口内的词看成是一个子句,然后用句子建模的方法对这个子句建模。基于这种方法,Poria等人 [52] 利用多层次的深度CNN对句子中每个词进行标记,辅以一系列语言学特征,他们的集成模型在aspect detection上表现良好。

词级别的分类终极目标是输入一句话输出一个标签序列。在这种情况下,利用条件随机场之类的结构化方法往往能捕捉相邻标签之间的依赖关系,从而产生更一致的标签序列,最后得到路径最优的标签序列[53]。

为了覆盖更大的上下文范围,经典的窗口建模方法往往会结合时延神经网络(TDNN)[54],在整个序列的所有窗口上执行卷积操作,这些卷积通常具有固定宽度的卷积核。经典的窗口方法仅仅考虑要标记的单词周围的窗口中的单词,但时延神经网络可以同时考虑句子中所有单词窗口。需要的话,TDCNN也可以像CNN一样堆叠起来以提取底层局部特征和高层全局特征。

B. Applications

在这一部分,我们总结了将CNN用于NLP的一些关键工作,这些工作在提出来时都是最先进的。

Kim [50] 将上述CNN网络用于各种句子分类任务中,包括情感分类,实体分类和问题类别分类,最后都取得了有竞争性的结果。这个工作提出的模型结构非常简洁而且有效,所以马上就被很多研究者采纳。随机初始化的卷积核随着训练的进行,最终变成了有效的n元语法提取器(Fig. 7)。这个网络虽然很有效,但由于太简单也存在很多缺点,CNN无法有效建模长程依赖是主要问题。

Kalchbrenner等人[49]发表了一篇著名文章提出了动态卷积网络(DCNN)对句子语义建模,一定程度上缓解了上述问题。他们的主要策略是动态k最大池化(dynamic k-max pooling),对于给定的序列p,从中挑出k个最大特征,并且保持原来的顺序,如Fig. 8所示。基于时延网络的思想,加上k-max pooling,得到最后的模型。这种模型结构可以用较小的卷积核覆盖到较广的范围,有利于积累句子中的关键信息。从Fig. 8中能看出,高层特征覆盖的句子范围差异很大,有些可以聚焦在很少的词上,有些却能覆盖整个句子。他们的模型在大量任务上都取得了显著的结果,包括情感分类和句式分类。总体来讲,这项工作分析了单个卷积核在建模上下文语义的时候的覆盖范围并提出了一种扩展其覆盖范围的方法。

涉及到情感分析的任务往往需要提取和情感极性相关的特征 [55]。Ruder等人 [56] 利用CNN建模同时在输入中接上一个aspect vector最终取得了不错的结果。对于长文本和短文本,CNN建模的效果也有差异,比如Johnson和Zhang [56] 的研究中就发现在长文本上的表现优于短文本。Wang 等人 [57] 提出用CNN来对短文本建模,由于缺乏足够的上下文信息,往往需要引入额外信息来保证得到有效的句子表示,作者提出了一种语义聚类的方法,可以通过引入多尺度的语义单元作为附加信息辅助短文本CNN建模。实际上,需要丰富的上下文信息可以算是基于CNN模型的一个局限性。涉及到短文本的NLP任务使用基于CNN的模型时往往需要借助额外信息和外部知识才能获得预期表现。这一事实在另一个基于CNN做的推特文本讽刺检测[58]的研究中也得到了证明。要达到预期效果,一般都需要额外辅助信息,比如可以利用表情数据集、情感数据集或者个人数据集进行预训练。

CNN在其他NLP任务上也有广泛的应用。比如,Denil等人[59]将DCNN用于文本摘要,同时在句子级别和文章级别训练DCNN卷积核,多层次的训练可以融合底层词特征信息到高层语义概念中。这项工作的重点是介绍如何对学到的表示进行可视化,对模型学习过程和文本自动摘要都提供了有洞察性的见解。

CNN模型不仅可以用于句子分类任务,也可用于涉及到语义匹配的任务[60]。比如,信息检索的一项研究[61]就用到了和上述类似的CNN模型(Fig. 6),CNN用来将query和document映射到固定维度的语义空间,然后就可以用余弦相似度来做排序。该模型试图通过考虑单词序列中的时间上下文窗口来提取query和document中的丰富上下文结构。这捕获了单词n-gram级别的上下文特征。 然后通过卷积和最大池化层发现显著的单词n-gram,然后将其聚合以形成整个句子向量。

在问答领域,Yih等人[62]提出可以通过度量问题和知识库中条目的相似度来决定在回答问题时需要从知识库中寻找什么样的支撑事实,计算语义表示时用到了类似Fig. 6的CNN框架。和文本分类不同的是,监督信号来自于query-document正负样本对,而不是文本类别。随后,Dong等人[63]提出了multi-comumn CNN(MCCNNN)来从多个方面分析理解问题,MCCNN使用了多路网络结构从包含答案类型和输入问题上下文的方面提取信息,通过将知识库中的实体和关系用低维向量表示,然后用问题-答案对来训练CNN模型用来对候选答案排序。Severyn和Moschitti在建模问题和答案时也用到了CNN网络,他们还在词向量中加入了问题和答案词与词的匹配特征,这种基于CNN的简单网络最终得到了与最先进的方法相媲美的结果。

在CNN中,为了捕捉句子中最重要的信息,通常是在后面加最大池化层,然而,这种操作经常会丢失包含多个事实的句子中有价值的信息。为了克服多事件建模中信息丢失的问题,Chen等人[65]提出了改进版的池化策略:动态多路池化(DMCNN),在一般池化操作的基础上引入事件触发机制,以便从池化层保留更多关键信息。

CNN网络本质上提供了局部连接、权值共享、池化等特征,这在一定程度上提供了很多任务都需要的不变性。语音识别就需要类似的不变性,在语音信号中由于说话人不一样频率差异很常见,因此,Abdel-Hamid等人[66]使用了一个混合CNN-HMM模型,该模型对沿频率轴的频移提供了不变性,他们还用了有限的权值共享,这导致池化层的参数减少,从而降低了计算复杂性。Palaz等人[67]用原始语音作为输入,对基于CNN的语音识别系统进行了广泛的分析,他们展示了CNN直接建模原始语音输入和因素之间关系的能力,构建了一个健壮的语音识别系统。

类似机器翻译的任务依赖词之间的先后顺序以及长程依赖关系,因此,结构上不太适合CNN网络。随后,Tu等人[68]通过考虑翻译句对之间的语义相似性和各种的语境来解决这个问题,虽然没有解决词语保序的问题,但也能得到与其他基线差不多的结果。(译者注:transformer貌似就是做翻译的,attention is all you need)

总体来讲,CNN网络在挖掘上下文窗口的语义线索方面非常有效,然而,CNN模型参数多,需要大量训练数据,当数据不足时就有问题。CNN的另一个问题是无法对长程上下文信息建模,也无法在表示中保存顺序[49, 68],针对这类问题,其他的类似递归神经网络可能更适合。

Recurrent Neural Networks

递归神经网络(RNN)[69]使用了处理序列信息的思想,这里用了“递归”这个词,因为它们对序列的每个单元执行相同的操作,每个时刻的操作都依赖于上一时刻操作的结果。通常来讲,将序列中的基本单元一个接一个输入到递归神经网络就能得到长度固定的向量作为序 转载文章地址:http://www.orzojp.com/xiaoshuo/22087.html
(本文来自皓哥娱乐整合文章:http://www.orzojp.com)未经允许,不得转载!

标签:
相关推荐
网站简介 联系我们 网站申明 网站地图

版权所有:www.orzojp.com ©2017 皓哥娱乐

皓哥娱乐提供的所有内容均是网络转载或网友提供,本站仅提供内容展示服务,不承认任何法律责任。