论文阅读(40)Explainability Methods for Graph Convolutional Neural Networks

1. 论文相关

Explainability Methods for Graph Convolutional Neural Networks [](javascript:;)
图卷积神经网络的可解释性方法
CVPR2019

2. 摘要

随着图形卷积神经网络(GCNNS)的日益广泛应用,对其进行解释的需求也越来越迫切。本文介绍了GCNNS的可解释性方法。我们开发了卷积神经网络三种显著解释方法的图形类似物(graph analogues of three prominent explainability methods):基于对比梯度的显著性图、类激活图(CAM)和激发反向传播图(EB)及其变体、梯度加权CAM(grad cam)和对比EB(c-EB)(con-trastive gradient-based (CG) saliency maps, Class Activation Mapping (CAM), and Excitation Backpropagation (EB) and their variants, gradient-weighted CAM (Grad-CAM) and contrastive EB (c-EB))。我们展示了这些方法在视觉场景图和分子图(visual scene graphs and molecular graphs.)两个应用领域的分类问题的概念证明(proof-of-concept)。为了比较这些方法,我们确定了解释的三个理想特性:(1)它们对分类的重要性,通过阻塞(occlusions)的影响来衡量;(2)它们对不同类别的对比度;(3)它们在图上的稀疏度。我们将相应的定量指标称为保真度、对比度和稀疏度(fidelity, contrastivity, and sparsity),并对每种方法进行评估。最后,我们分析了从解释中得到的显著子图(salient subgraphs),并报告了频繁发生的模式(report frequently occurring patterns)。

2.2 贡献

我们采用了三种常见的解释方法,最初是为CNN设计的,并将它们扩展到GCNNS。这三种方法是基于梯度的显著性映射[32]、类激活映射(cam)[39]和激发反向传播(eb)[39]。此外,我们还采用了两种变体:梯度加权CAM(Grad-CAM)[31]和对比EB。我们在两种不同应用上评估了改编的方法:视觉场景图和分子图。对于GCNNS,我们使用Kipf等人提出的公式架构(formulation)〔18〕。我们在这项工作中的具体贡献如下:
(1)将CNN的可解释性方法改编为GCNN,
(2)演示两个图形分类问题的可解释性技术:视觉场景图和分子
(3)使用保真度、对比度和稀疏度指标描述每种方法的权衡(trade-offs)。

2.3 论文结构

本文的其余部分结构如下。在第二部分,我们讨论了可解释性和GCNN的相关工作。在第三节中,我们回顾了GCNN的数学定义和CNN上的可解释性方法,然后定义了GCNN上类似的可解释性方法。在第4节中,我们详细介绍了我们对视觉场景图和分子的实验,并给出了示例结果。此外,我们还定量地评估了这四种方法在三个方面的性能,即保真度、对比度和稀疏度,每种方法都旨在捕捉解释的某些理想特性。我们使用这些指标来评估每个方法的优点。最后,在实验部分,我们分析了Grad-Cam识别的显著子结构的频率,并报告了每个数据集的顶部结果(top result)。

3. 方法

比较了在图卷积神经网络(GCNNS)中应用的常用的解释性方法。此外,我们还探讨了这些方法的一些增强的好处。

3.1 CNN的可解释性(Explainability for CNNs)

常用的三种解释方法主要是对比梯度法、类激活映射法和激发反向传播法(contrastive gradients, Class Activation Mapping, and Excitation Backpropagation)。

基于对比梯度的显著性图(Contrastive gradient-based saliency maps)[32]可能是最直接、最成熟的方法。在这种方法中,我们简单地将模型的输出与模型输入区分开来(differentiates),从而创建一个热图(heat-map),其中输入变量上梯度的范数表示它们的相对重要性。输入空间中产生的梯度指向对应于模型输出中最大正变化率的方向。因此,放弃梯度中的负值,只保留有助于(positively contribute)解决方案的输入部分:

image.png

其中y^c是Softmax层之前的类c的分数,x是输入。虽然很容易计算和解释,显著性图(saliency maps)通常比新技术(如CAM, Grad-CAM和EB)表现差,而且最近有人认为显著性图倾向于代表噪音而不是信号[17]。

类激活映射(Class Activation Mapping)通过最后一个卷积层识别类特定特征(class-specific features)的重要性,而不是输入空间,改进了卷积神经网络的显著性映射(saliency maps),包括GCNN。众所周知,这些特征在语义上更有意义(例如,面而不是边,faces instead of edges)。CAM的缺点是它要求在Softmax分类器(输出层)前面的层是卷积层,然后是全局平均池(GAP)层。这就排除了(precludes)使用更复杂的异构网络(heterogeneous networks),例如那些在Softmax层之前包含多个全连接层的网络。

为了计算CAM,让F_k∈R^{u*v}表示在Softmax层之前的卷积层的第k个特征图。用F_k表示的全局平均池化(global average pool,GAP):

image.png

其中Z= uv。然后,一个给定的类分数y^c,可以定义为:

image.png

其中权重w_k^c是根据网络的输入输出行为来学习的。权重w_k^c编码特征k用于预测类c的重要性。通过将每个特征映射向上扩大(upscaling)到输入图像的大小(以抵消池化层的效果),像素空间中的类特定热图(class-specific heat-map in the pixel-space)将变为:

image.png

Grad-CAM通过放宽倒数第二层(penultimate layer)必须是卷积层的结构限制改进了CAM。这是通过使用基于反向传播梯度(back-propagated gradients)的特征映射权重\alpha_k^c来实现的。具体来说,Grad-CAM定义权重根据如下公式:

image.png

根据CAM方程式(4)的直觉,根据Grad-CAM计算像素空间中的热力图(heat-map in the pixel-space)公式,如下所示:

image.png

其中ReLU函数确保只有对类预测有积极影响的特征是非零的。

激励反向传播(Excitation Backpropagation)是一种直观简单,但经验有效的解释性方法。在[28]中,有人论证并通过实验证明,可解释性方法,如忽略反向通过网络的非线性(nonlinearitie)的EB[39],能够生成热图,为预测任何特定类别的网络“保存”证据,。让a_i^l成为一个神经网络第l层的第i个神经元,a_j^{l-1}是神经网络第(L-1)的神经元。 定义神经元a_j^{l-1}相对于神经元a_i^l对激活y_i^l \in R的影响,其中:

image.png

W^{l-1}是层(l-1)和层l之间的网络连接的权重( synaptic weights),是对(l-1)层上神经元的概率分布P(a_j^{l-1})。这种概率分布可以分解为(factored as):

image.png

张等[39]然后将条件概率(conditional probability)P(a_j^{l-1}|a_i^l)定义为

image.png

Z_i^{(l-1)}是一个标准化因子(normalization factor),如\sum_j P(a_j^{l-1}|a_i^l) = 1
对于给定的输入(例如图像),EB通过在输出层从P(a_i^L=c)=1开始并递归应用方程(7),在像素空间生成关于(w.r.t.,with respect to)类c的热图。

这些经过回顾(reviewed)的可解释性方法最初是为CNN设计的,CNN是为统一的方格网(uniform square grid)上的信号定义的。在这里,我们对非欧几里得结构(non-Euclidean structures)支持的信号感兴趣,如:图(graph)。接下来,我们首先简要地讨论了GCNNS,然后描述了这些可解释性方法对GCNNS的扩展。为了直观起见,我们注意到图像可以被概念化为以像素值作为节点特征的点阵形图。从这个意义上讲,GCNNs归纳 CNN以适应节点之间的任意连接。

image.png

3.2 图卷积神经网络(Graph Convolutional Neural Networks)

用节点属性X∈R^{N\times d_{in}}及其邻接矩阵A∈R^{N\times N}(加权或二进制)定义一个有N个节点的属性图。此外,定义度矩阵(degree matrix)为D_{ii} = \sum _j A_{ij}。跟随Kipf和Welling的工作,我们定义了图卷积层为:

image.png

式中F^ll层上的卷积激活,F^0=x\tilde{A} = A+I_N是加上自连接(self connections)的邻接矩阵,式中I_N∈R^{N\times N}为单位矩阵(identity matrix)。\tilde{D}_{ii} = \sum _j \tilde{A}_{ij}W^l \in R^{d_l \times d_{l+1}}是可训练的卷积权重。σ(·)是元素方向(element-wise)的非线性激活函数。图1显示了本工作中使用的GCNN结构,其中层l=1,2,3中的激活遵循等式(9),这是图上局部光谱滤波器(localized
spectral filters on graphs)的一阶近似值(first-order approximation)。

对于分子分类,每个分子可以表示为属性图G_i=(X_i,A_i),其中节点特征X_i概括了分子中原子的局部化学环境,包括原子类型、杂交类型和价结构(35),邻接矩阵编码原子键并证明整个分子的连接性。(见图1)。对于给定的标签分子数据集D={\{G_i=(X_i,A_i),y_i\}}_{i=1}^M,标签y_i指示某种化学性质,例如:血脑屏障穿透性或毒性,任务是学习将每个分子映射到其相应标签的分类器:$g:(X_i,A_i)\to y_i。

考虑到我们的任务是对具有潜在不同节点数的单个图(即分子)进行分类,我们使用几个图卷积层,然后在图节点(如原子)上使用全局平均池化(global average pooling,GAP)层。在这种情况下,所有图都将用固定大小的向量表示。最后,将GAP特征输入(feed)分类器。为了使CAM[42]的适用性,我们在GAP层之后使用了一个Softmax分类器。

3.3. 图卷积神经网络的可解释性

在本小节中,我们描述了CNN可解释性方法在GCNNs中的扩展。将l层的第k个图卷积特征图(graph convolutional feature map)定义为:

image.png

其中表示W_k^l表示矩阵W^l的第k列,以及V= \tilde{D}^{-\frac{1}{2}} \tilde{A} \tilde{D}^{-\frac{1}{2}}(见等式(8))。在这个符号中,对于节点n,第l层的第k个特征用F_{k,n}^l表示。最后,卷积层后的GAP特征L计算为:

image.png

类得分(class score)计算为,y^c = \begin{matrix} \sum_{k} w_k^c e_k \end{matrix}。使用此符号,我们将可解释性方法扩展到GCNN,如下所示:

3.3.1 基于梯度的节点n上的热图是:
image.png
3.3.2 CAM热图计算如下:
image.png
3.3.3 Grad-CAM

Grad-CAM在l层和特征k上的对于类c得类特定权重(class specific weights)由以下公式计算:

image.png

l的热图计算为:

image.png

Grad-CAM使我们能够生成网络不同层的热图。此外,对于图1所示的模型,最终卷积层的Grad-CAM和CAM等效L_{Grad-CAM}^c[L,n]=L_{CAM}^c[n](有关详细信息,请参见[31])。在这项工作中,我们报告了−L_{Grad-CAM}^c[L,n]的结果,变量Grad-CAM Avg定义如下:

image.png
3.3.4 EB

通过对Softmax分类器、GAP层和几个图卷积层的反向传递,计算了模型的激活反向传播热图。通过Softmax分类器和GAP层的向后传递方程如下:

image.png

其中p(c)=1表示感兴趣的类别,否则为零。然而,反向传播通过图卷积层的过程更为复杂。为了表示简单,我们将一个图卷积算子分解为:

image.png

其中,第一个方程是原子的局部平均值(V_{n,m}大于等于0),第二个方程是应用于每个原子的固定感知器(类似于CNN中的一个接一个卷积)。这两个函数对应的反向传播可以定义为:

image.png

我们通过网络递归反向传播并平均输入上的反向传播概率热图,在输入层上生成热图:

image.png

L_{EB}^c的对比扩展如式(8)在[39],我们称之为对比变体(contrastive variant),c-EB。

4. 实验

本节介绍我们的实验和对具体类的解释的分析。我们在视觉场景图和分子两个应用领域进行了实验。此外,我们还对补充资料中的可解释性方法识别的图形子结构进行了频率分析。

4.1 场景图解释(Explanations on Scene Graphs)

我们的目标是训练GCNN进行场景图分类,并使用我们提出的解释方法对这些GCNN进行解释。场景图是一种图形结构数据,其中节点是场景中的对象,边是对象之间的关系。我们从视觉基因组数据集(Visual Genome dataset)[20]中获得第一个实验的数据。视觉基因组数据集由图像和场景图对组成。对象和关系有多种类型,数据是从众包工作人员的自由文本响应中收集的。对象具有由边界框定义的图像关联区域。

我们从视觉基因组构建了两个二元分类任务:乡村与城市,室内与室外(country vs. urban, and indoor vs outdoor)。我们用一组关键字对这些词进行建模,这些关键字用于查询视觉基因组数据,以确定图像的任何属性是否匹配。类的图像集是为每个关键字返回的图像集的联合(union,并集)。此外,类对之间的任何交集都被删除。用于定义每个类的关键字如下:

(1)“乡村”:乡村、农村、农场、农村、奶牛、农作物、绵羊

(2)“城市”:城市、城市、市中心

(3)“室内”:室内、房间、办公室、卧室、浴室

(4)“室外”:室外、自然、室外

image.png

关键词是不全面的,并没有声称包含每个词的全部含义。相反,它们是为了研究图的解释方法而设计的合成结构。由于这项工作的目的是研究解释,类定义的确切细节与目前的工作并不密切。选择关键词来给出分类对之间大致平衡的类。每个数据集的类比率在表1中报告。

image.png

为简单起见,在不丧失一般性的情况下,我们将所有关系折叠为单一类型,这表示两个对象之间的通用关系。我们注意到,对于关系边[29]的图,GCNNs的各种扩展都存在,因此本文开发的可解释性方法可以用于这些图。

场景图中有一个与每个对象(即节点)关联的边界框(bounding box)。我们使用一个预训练的InceptionV3网络,提取潜在图像的深层特征,作为场景图所有节点的边界框。最后一个池化层被用作视觉特征(visual feature),其中每个裁剪(crop)都被零填充到一个固定的大小。从每个边界框中提取的特征的大小为d=2048维。因此,我们得到的场景图由关系数据和可视数据组成。最后的任务是将场景图分为城市与乡村和室内与室外两类。

4.2. 分子图解释(Explanations on Molecular Graphs)

我们研究了第二个应用领域:识别有机分子上的官能团的生物分子性质。我们用三个二元分类分子数据集BBBP、BACE和TOX21[35]中的任务NR-ER对解释性方法进行了评估。每个数据集包含由实验确定的小有机分子的二元分类。BBBP数据集包含了一个分子是否渗透到人脑血屏障的测量,对药物设计有重要意义。BACE数据集包含一种分子是否抑制人体酶β-分泌酶(enzyme β-secretase)的测量。Tox21数据集包含对几种毒性目标分子的测量。我们从这些数据中选择了NR-ER任务,这与雌激素受体的激活有关[24]。这些数据集不平衡。分类比率见表1。

此外,我们遵循了[35]中的建议,这是描述分子数据集的原始文件,用于训练/测试划分。特别是对于BACE和BBBP,由[35]推荐所谓的“scaffold”划分,它根据分子的结构来划分分子,即结构相似的分子划分在同一个分区中。我们强调,训练GCNN和传统的数据集分割不是我们论文的贡献,我们只是遵循这些数据集的标准实践。

4.3. 训练和评估

我们将数据集划分为80:20的训练/测试集。对于所有数据集,我们使用如图1所述的GCNN + GAP架构,配置如下:三个大小分别为128、256和512的图卷积层,后面是一个间隙层(GAP layer)和一个Softmax分类器。使用学习率为0.001,β1=0.9,β2=0.999的Adam优化器对模型进行25个epochs的训练。这些模型在带有TensorFlow后端的Keras中实现[5]。各数据集训练模型的评价指标AUC-ROC和AUC-PR见表1。

一些分子分类结果被观察到具有更高的平均测试与训练性能。尽管这是不寻常的,但结果与[35]中报告的结果一致。

4.4. 解释方法分析(Analysis of Explanation Methods)

在为每个数据集训练模型之后,我们将每个解释方法应用于所有样本,并在节点上获得一组scalars,即heatmap。

我们在图3和图4中显示了选定的结果。在图中,标量重要性(scalar importance)值编码为边界框轮廓的颜色(红色:低,黄色:中,绿色:高)。在图4中,标量重要性(scalar importance)值编码为每个原子上蓝色圆盘的强度(白色:低,蓝色:高)。

计算出正类和负类的热图,并对每个分子在类和节点上进行归一化,以在输入节点上形成概率分布。通过比较一个方法中不同类之间的解释可以看出类的特殊性,即当一个类激活的节点往往对另一个类不活动时。

接下来,我们报告了三个量化指标,它们捕获了令人满意的解释方面:保真度、对比度和稀疏度。

通过计算保真度来捕捉通过解释识别出的显著特征的遮挡会降低分类精度的直觉。更准确地说,我们将保真度定义为通过遮挡(occluding)显著性值大于0.01的所有节点(在0到1的范围内)获得的精度差异。然后我们对每个方法跨类的保真度得分进行平均。我们在表2中报告了这些值。对比梯度法显示出最高的保真度。

对比度的设计是为了捕捉这样一种直觉,即通过解释方法强调的特定于类的特征在类之间应该是不同的。更准确地说,我们将对比度定义为正负两类热映射图m_0,m_1之间的汉明距离之比,通过任一方法识别的原子总数进行归一化,

image.png

我们在表中报告这个指标2。Grad-CAM的对比度最高。

稀疏度是用来测量解释的局部化程度的。稀疏解释对于研究大型图尤其有用,因为在这些图中,所有节点的手动检查都是不可行的。更准确地说,我们将此度量定义为1减去解释中标识的对象数$$,再除以图中节点总数|V|

我们在表2中报告了这些值。c-EB方法的激活率最低(sparsest activations)。

对比度和稀疏度的描述性图形见附录。

使用这些指标,我们比较了每种解释方法的质量,并演示了每种方法的权衡。简而言之,我们得出三个要点:(1)Grad-CAM的对比度最大,保真度次之,但稀疏度较低。这种方法通常是适用的,但在大图上可能有问题。(2)c-EB最稀疏,但保真度低,对比度次之。因此,该方法最适合于以低保真度为代价的大型图形分析。(3)对比度梯度(Contrastive gradient,CG)的保真度最高,但稀疏度低,对比度低。对比度的缺乏使得这种方法不适合于具体的类解释。

4.5. 子图频率分析

如上所述,GCNN的解释方法识别了输入图上的显著结构。数据集中标识的显著子结构集合为进一步分析提供了机会。我们分析此集合中是否存在重复出现的子结构,目的是进一步洞察数据。简而言之,我们计算了数据集中每个显著结构的流行率,并将其与正标记数据集中的流行率进行了比较。我们在下文中作了简要说明,并请读者参阅补充资料以了解更多详情。

为了识别图中的显著子结构,我们首先收集显著值大于某个阈值(这里是0)的顶点集,我们称之为激活顶点(activated vertices)。然后我们收集由这个顶点集产生的连接组件。对数据集中的所有图重复此操作将生成一组显著的子图。然后,我们计算在(1)解释集,(2)正标记数据,(3)负数据中每个已识别子图s的频率,我们将其表示为N^s _e , N^s_p and N^s_n。我们使用这些计数来规范从解释中获得的计数,并构造三个比率:

image.png

比率N^s_e度量子图在解释中的普遍性。比率N^s_p 和 N^s_n分别测量正标签数据和负标签数据中子结构出现的频率,并作为第一个数据的基线。请注意,对于显著子图s,高N^s_p 和 N^s_n或对应于高类特异性。

我们根据GradCAM获得的分子数据集和视觉基因组数据集的比率N^s_e报告了图中的顶部结构。

在分子的情况下,我们注意到显著的子图被解释为官能团,即在确定分子性质(例如毒性)中起作用的子结构。图2中的顶部结果包括酰胺、三氯甲烷、磺酰胺和芳香结构。这些结果作为官能团的有效性仍有待实验验证。

其他功能组的算法识别工作包括[10]和[8]。两者都是基于规则的方法,而我们的方法是学习的。[8]讨论了算法识别功能团的一些局限性。功能组的概念没有被精确定义。[8]指出,每一位药物化学家可能都有自己的功能组概念。我们并不认为我们的方法是正确的官能团定义。然而,考虑到卷积神经网络在视觉和语言中其他直观概念建模方面的成功,我们设想在这一领域的实际应用潜力。补充部分显示了进一步的子图结果。

image.png

图2:cam/gradcam标识的每个类/属性的前两个子结构。

image.png
image.png
image.png

5. 总结

在这项工作中,我们将为CNN设计的解释性方法扩展到了GCNNS,并对这些方法进行了定性和定量的比较。我们展示了两个应用领域的扩展方法:视觉场景图和分子图。

我们用三个指标来描述每种方法得到的解释:保真度、对比度和稀疏度。Grad-CAM的对比度最高,其次是c-EB。而c-EB的激活率最低(the sparsest activations)。最后,CG的保真度最高,对比度最低,稀疏度次之。然而,当找到特定于类的解释时,对比度是一个关键要求,这将取消CG的资格。

研究表明,Grad-CAM最适合解释中等尺寸图形。但是,我们提醒读者选择一种最适合其应用的方法。如果解释的稀疏性是高度关注的,例如,在解释大型图的情况下,那么c-EB可能是更好的选择。

在场景图和分子图上,我们识别了与给定分类相关的图形子结构,例如,识别出室内场景。这种方法对于自动挖掘分子的相关官能团是有用的。然而,需要进行额外的实验来确认已识别的子结构的化学有效性。

这项工作演示了解释GCNNS和挖掘输入图的子结构模式的工具,包括场景图、分子、社交网络和电网。在今后的工作中,我们计划研究新的图形解释方法,并利用可解释性来提高视觉场景图形的质量。

参考资料

参考论文

[1] Visual interpretability for deep learning: a survey

论文下载

[1] Explainability Methods for Graph Convolutional Neural Networks

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342