pytorch入坑笔记1: 从ResNet出发引发的几点思考

3 篇文章 0 订阅
订阅专栏

终于转到pytorch的学习了,也算是开启了一个新的篇章了。

1. 基本的学习资料

    网上的学习资料很多, 基本的语法这里也就不介绍了,推荐几个个人感觉比较好的文章或者网站。

  1. pytorch官网
  2. pytorch中文网站
  3. 莫烦pytorch教程
  4. pytorch discuss

网上pytorch教程、博客都是很多,有问题就请Google啦~

2. 一个简单的例子: ResNet

ResNet是Kaiming He 在《Deep Residual Learning for Image Recognition》上发表的文章,截止到现在在google学术上已经有14737次引用,不用多说就知道这篇文章的分量了。这里不对原始论文做过多的解读,这里侧重是使用pytorch实现这个网络。

2.0 先导

如果多Resnet还不是太懂的同学,可以参考

  1. Deep Residual Learning for Image Recognition
  2. Deep Learning-TensorFlow (14) CNN卷积神经网络_深度残差网络 ResNet
  3. 深度学习——残差神经网络ResNet在分别在Keras和tensorflow框架下的应用案例

把ResNet主要的思想看一下在看我们的文章可能会好一点。

2.1 网络架构

在这里插入图片描述
    这个就是这篇文章最重要的图了,其实resnet出发点还是比较简单的,就是我们不去学习x->F(x)的直接映射,而是去学习x到残差的映射关系。在某乎看到这样一篇博客,说是:残差网络让我们对微小的扰动敏感性更高,也更容易训练,更适合deeper网络。 至于这里我们选择identity映射,或者为什么采用这种结构,在作者后面文章 Identity Mappings in Deep Residual Networks, 经过实践发现这种架构是最好的~

    接下来我们用pytorch实现我们resnet网络。由于这篇文章出来的也是比较早,这里我们就不造轮子了,而是站在巨人的肩膀上,重点解释一下为什么这么写。

    我们参考的resnet博客是这篇 Pytorch实战2:ResNet-18实现Cifar-10图像分类(测试集分类准确率95.170%), 这里作者实现的是ResNet-18,下面贴一下网络和作者的代码。
ResNet18

2. 2 ResNet代码

这里我们主要是详解代码为什么这么写,以及自己的几点思考,训练部分代码就不做过多的介绍了,常规操作~

import torch
import torch.nn as nn
import torch.nn.functional as F

class ResidualBlock(nn.Module):
    def __init__(self, inchannel, outchannel, stride=1):
        super(ResidualBlock, self).__init__()
        self.left = nn.Sequential(
            nn.Conv2d(inchannel, outchannel, kernel_size=3, stride=stride, padding=1, bias=False),
            nn.BatchNorm2d(outchannel),
            nn.ReLU(inplace=True),
            nn.Conv2d(outchannel, outchannel, kernel_size=3, stride=1, padding=1, bias=False),
            nn.BatchNorm2d(outchannel)
        )
        self.shortcut = nn.Sequential()
        if stride != 1 or inchannel != outchannel:
            self.shortcut = nn.Sequential(
                nn.Conv2d(inchannel, outchannel, kernel_size=1, stride=stride, bias=False),
                nn.BatchNorm2d(outchannel)
            )

    def forward(self, x):
        out = self.left(x)
        out += self.shortcut(x)
        out = F.relu(out)
        return out

class ResNet(nn.Module):
    def __init__(self, ResidualBlock, num_classes=10):
        super(ResNet, self).__init__()
        self.inchannel = 64
        self.conv1 = nn.Sequential(
            nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False),
            nn.BatchNorm2d(64),
            nn.ReLU(),
        )
        self.layer1 = self.make_layer(ResidualBlock, 64,  2, stride=1)
        self.layer2 = self.make_layer(ResidualBlock, 128, 2, stride=2)
        self.layer3 = self.make_layer(ResidualBlock, 256, 2, stride=2)
        self.layer4 = self.make_layer(ResidualBlock, 512, 2, stride=2)
        self.fc = nn.Linear(512, num_classes)

    def make_layer(self, block, channels, num_blocks, stride):
        strides = [stride] + [1] * (num_blocks - 1)   #strides=[1,1]
        layers = []
        for stride in strides:
            layers.append(block(self.inchannel, channels, stride))
            self.inchannel = channels
        return nn.Sequential(*layers)

    def forward(self, x):
        out = self.conv1(x)
        out = self.layer1(out)
        out = self.layer2(out)
        out = self.layer3(out)
        out = self.layer4(out)
        out = F.avg_pool2d(out, 4)
        out = out.view(out.size(0), -1)
        out = self.fc(out)
        return out


def ResNet18():

    return ResNet(ResidualBlock)

   代码写的还是很漂亮的(漂亮警告~~)

2. 3 几点思考

因为接触pytorch没有太长时间,这里就把我学习过程产生的疑惑以及如何解决的和大家分享一下

2.3.1 其实pytorch的网络无非就是下面的范式:

import torch
import torch.nn as nn

class MyNetwork(nn.Module):
	def __init__(self):
		pass
	def forward(self, x):
		pass

  首先我们定义一个我们自己的类MyNetwork,然后它继承了nn.Module这个类, 我们可以转到nn.Module这个父类,发现里面会有很多方法,其中就有__init__(self)forward(self) 这两个函数,这样就很明白了,这不就是c++的重写嘛(override), 那么我们就重写就好了。 Python中self用法详解

   但是如果想要一些自己定义的一些外面参数,那么我们就需要在__init__(self)中添加一些外部参数,然后变成这样def __init__(self, inchannel, outchannel, stride=1),很方便的,但是我们仍然需要继承nn.Module.__init__(self)的相关方法啊,有同学就想这还不简单,我们直接显示调用一下就好了啊,对于这个例子是没错的, 但是实际中并不这么写,而是使用super(ResidualBlock, self).__init__(), 至于为什么这么写,这里还是有一点原因的。

   比如下面这个图,存在多继承的问题。
在这里插入图片描述
如果不使用super而显示调用父类的初始化函数,就会出现多次初始化的问题,具体的细节可以参考这篇文章 Python super(钻石继承)。其实super本质上使用一种mromromethod resolution order的缩写,表示了类继承体系中的成员解析顺序。使用super帮助我们解决了两大问题:

  1. 查找顺序问题。从Leaf的mro顺序可以看出,如果Leaf类通过super来访问父类成员,那么Medium1的成员会在Medium2之前被首先访问到。如果Medium1和Medium2都没有找到,最后再到Base中查找。

  2. 钻石继承的多次初始化问题。在mro的list中,Base类只出现了一次。事实上任何类都只会在mro list中出现一次。这就确保了super向上调用的过程中,任何祖先类的方法都只会被执行一次。

至于mro的生成算法,可以参考这篇wiki: C3 linearization

2.3.2 为什么需要__init__和forward?

其实从直观说还是比较简单的。init()相当于是我们的名词,然后forward()是我们的动作,就比如定义一个网络,init()定义我们的网络有哪些层,但是没有定义我们的网络是如何定义的,而forward()定义我们的网络是如何连接起来的。

2.3.3. 为什么nn.ReLU()出现inplace=True?

ReLU函数有个inplace参数,如果设为True,它会把输出直接覆盖到输入中,这样可以节省内存/显存。之所以可以覆盖是因为在计算ReLU的反向传播时,只需根据输出就能够推算出反向传播的梯度。但是只有少数的autograd操作支持inplace操作(如tensor.sigmoid_()),除非你明确地知道自己在做什么,否则一般不要使用inplace操作。

在 pytorch 中, 有两种情况不能使用 inplace operation:

  1. 对于 requires_grad=True 的 叶子张量(leaf tensor) 不能使用 inplace operation
  2. 对于在 求梯度阶段需要用到的张量 不能使用 inplace operation

参考:

  1. pytorch-book/chapter4-神经网络工具箱nn/chapter4
  2. pytorch 学习笔记(二十二):关于 inplace operation

2.3.4 pytorch是如何实现shortcut的?

   在第一次看到这个代码实现shortcut的时候自己真的没有看的太明白,想当然的就认为残差不就是 F ( x ) + x F(x)+x F(x)+x 嘛, 也就是上面这句代码out += self.shortcut(x)表述的这样。但是为什么还会出现下面奇怪的代码:

 self.shortcut = nn.Sequential()
        if stride != 1 or inchannel != outchannel:
            self.shortcut = nn.Sequential(
                nn.Conv2d(inchannel, outchannel, kernel_size=1, stride=stride, bias=False),
                nn.BatchNorm2d(outchannel)
            )

后来在这一篇文章 深度学习——残差神经网络ResNet在分别在Keras和tensorflow框架下的应用案例我才恍然大悟,发现这句代码的精妙之处。

  对于开始的Resnet-18结构来说,shortcut存在二种不同的类型,一种是经过网络之后输出和输入尺寸是一样的,还有一种输出和输入的维度不匹配,这个时候我们通过Conv + BN的方法将输入的尺寸变成输出尺寸!

  1. 这是输入和输出维度匹配的情况:
    在这里插入图片描述

  2. 这是输入和输出维度不匹配的情况(需要借助conv+bn将输入尺寸降低)
    在这里插入图片描述

2.3.5 nn.Sequential(*layers)为什么需要加一个*

如果*号加在了是实参上,代表的是将输入迭代器拆成一个个元素

参考文章:

  1. Pytorch中nn.ModuleList 和 nn.Sequential的不同
  2. Pytorch 容器
  3. When should I use nn.ModuleList and when should I use nn.Sequential?

2.3.6 为什么在__init__中使用nn.Relu,而在forward中使用F.relu,这两个有什么区别吗?

其实这个问题和pytorch discuss有一个问题很像 How to choose between torch.nn.Functional and torch.nn module?

    In PyTorch you define your Models as subclasses of torch.nn.Module.
    In the init function, you are supposed to initialize the layers you want to use. Unlike keras, Pytorch goes more low level and you have to specify the sizes of your network so that everything matches.
    In the forward method, you specify the connections of your layers. This means that you will use the layers you already initialized, in order to re-use the same layer for each forward pass of data you make.
torch.nn.Functional contains some useful functions like activation functions a convolution operations you can use. However, these are not full layers so if you want to specify a layer of any kind you should use torch.nn.Module.
    You would use the torch.nn.Functional conv operations to define a custom layer for example with a convolution operation, but not to define a standard convolution layer.

大概什么意思哩,也就是说__init__定义的是标准层,比如这里nn.Relu是标准层。而在forward里面用户F.relu更像是一种操作,不改变网络的参数权值什么的。

2.3.7 net.train()和net.eval()区别

使用PyTorch进行训练和测试时一定注意要把实例化的model指定train/eval,eval()时,框架会自动把BN和DropOut固定住,不会取平均,而是用训练好的值,不然的话,一旦test的batch_size过小,很容易就会被BN层导致生成图片颜色失真极大。原因就是对于BN层来说,它在训练过程中,是对每一个batch去一个样本均值和方差,然后使用滑动指数平均所有的batch的均值和方差来近似整个样本的均值和方差。对于测试阶段,我们固定我们样本和方差,bn相当于一个线性的映射关系。所以说对于pytorch来说,在训练阶段我们net.train相当于打开滑动指数平均按钮,不断的更新;测试阶段我们关闭它,相当于一个线性映射关系。dropout类似的。

参考文章:

  1. CSDN: 使用PyTorch进行训练和测试时一定注意要把实例化的model指定train/eval
  2. 知乎:为什么batch normalization在训练和测试时使用的均值和方差的计算方式不同?
  3. pytorch discuss: Trying to understand the meaning of model.train() and model.eval()
  4. pytorch discuss: Model.train() and model.eval() vs model and model.eval()

Over~好吧,以上就是目前的感想,以后还有新的见解在继续添加吧~

Pytorch修改ResNet模型全连接层进行直接训练实例
09-18
在本篇文章里小编给大家整理的是关于Pytorch修改ResNet模型全连接层进行直接训练相关知识点,有需要的朋友们参考下。
pytorch_resnet:ResNetPyTorch实施
05-15
ResNetPyTorch实施 用法 $ python main.py --block_type basic --depth 110 --outdir results CIFAR-10的结果 模型 测试错误(3次运行的中位数) 测试错误(纸上) 训练时间 ResNet-110 6.52 6.43(最佳),...
深度学习系列5——Pytorch 图像分类(ResNet)
霁风AI
02-08 5650
深度学习系列5——Pytorch 图像分类(ResNet)
深度学习——残差网络(ResNet)原理讲解+代码(pytroch)
m0_74055982的博客
04-18 3067
残差的思想都是去掉相同的主体部分,从而突出微小的变化。从信息论的角度讲,由于DPI(数据处理不等式)的存在,在前向传输的过程中,随着层数的加深,Feature Map包含的图像信息会逐层减少,而ResNet的直接映射的加,保证了 l+1 层的网络一定比 l 层包含更多的图像信息。原因:反向传播的时候的链式法则,越是浅层的网络,其梯度表达式可以展现出来连乘的形式,而这样如果都是小于1的,这样的话,浅层网络参数值的更新就会变得很慢,这就导致了深层网络的学习就等价于了只有后几层的浅层网络的学习了。
pytorch(3)--VGG block和 Resnet block
AP1005834的博客
03-22 3635
一、前言 本篇记录 VGG Block和Resnet Block 经典结构 二、VGGblock VGG Block 可由两层conv3或三层conv3组成,两层的感受野和一层conv5一样,三层conv3的感受野和一层conv7是一样的,但是能够减少计算量,以下为不同的VGGblock搭配的VGG网络 包含两层conv3的VGG block 代码如下,CBR-CBR,无池化层 class VGGBlock(nn.Module): def __init__(self,...
Resnet的跳转连接实现 (pytorch)
ytusdc的博客
08-20 3691
在原论文中,残差路径可以大致分成2种,一种有bottleneck结构,即下图右所示,其中两个1×1卷积层,用于先降维再升维,主要出于降低计算复杂度的现实考虑,称之为“bottleneck block”,另一种没有bottleneck结构,如下图左所示,称之为“basic block”。basic block由2个3×3卷积层构成 shortcut路径大致也可以分成2种,取决于残差路径是否改变了feature map数量和尺寸,一种是将输 x 原封不动地输出,另一种则需要经过 1×1 卷积来升...
pytorch基础学习1
weixin_46248767的博客
10-29 258
pytorch之二维卷积 文章目录pytorch之二维卷积一、 卷积简述二、部分参数 一、 卷积简述 通常对于由多个维度组成的输信号可以用二维卷积。较为简单的模式是,输大小为(N,C,H,W),卷积过后的输出为(N,C,H,W)。N是每个批次的样本数目,C是输样本的通道数目,H是输样本的高度,W是输样本的宽。 二、部分参数 stride:步长,控制卷积核每经一次卷积计算后移动的长度; padding(int or tuple, optional) :填补,输的每一
PyTorch 七:模块与nn.Module学习
鲁点点的博客
09-21 1517
模型创建概述 本章开始正式整理深度学习网络相关基础知识。 模型创建分为两个部分:模型结构创建和权值初始化。 模型结构创建从粒度上讲:有层layer和网络Net 两个粒度。前者是指构成CNN的基础结构,如卷积层、池化层、BN层、激活函数层、损失函数层等;后者是指实现某一功能的网络结构如LeNet,AlexNet和ResNet等。 创建好模型后,需要对模型进行权值初始化,pytorch提供了丰富的初始化方法,Xavier,Kaiming,均匀分布,正态分布等。好的权重初始化有以下几点优点: 加速网络收敛 解更
CIFAR10图像分类ResNet模型实战(pytorch
Bryce-HJ
07-25 4403
CIFAR10图像分类ResNet模型实战(pytorch)1 ResNet18网络实现及略微改进2 学习过程中的部分问题总结:2.1 为什么nn.ReLU() 设置 inplace=True?2.2 nn.Sequential(*layers)加了一个\*2.3 net.train()/ net.eval()2.4 用到的argsparse模块2.5创建记录数据的txt文件2.6 sum_loss 、 predicted 、total 、correct (重点理解)2.7 __init__中使用nn.Re
Facebook计算机视觉开源框架Detectron2学习笔记 --- 从demo到训练自己的模型
weixin_42174674的博客
04-30 2541
开始之前首先声明一下,我刚深度学习,甚至可以说刚计算机,这一系列博客仅仅是我个人的一个学习笔记,主要面向新手。因为现在很多 Detectron2 的分析其实都是面向老手(实际上刚的新人也不会上来就接触 Detectron2 这种框架),很多细节部分可能大佬们觉得很简单就略过了,但是对于新手而言要费很长时间研究。因此这一系列文章仅仅记录一下我使用 Detectron2 过程中的学习历程以及踩过得,如果哪里有问题欢迎指正! 刚深度学习不久,始终在研究CV的目标检测任务,现在常见的单阶段检测器
老潘的AI部署以及工业落地学习之路
老潘的博客
08-08 1580
Hello我是老潘,好久不见各位。 最近在复盘今年上半年做的一些事情,不管是训练模型、部署模型搭建服务,还是写一些组件代码,零零散散是有一些产出。 虽然有了一点点成果,但仍觉着缺点什么。作为深度学习算法工程师,训练模型和部署模型是最基本的要求,每天都在重复着这个工作,但偶尔静下心来想一想,还是有很多事情需要做的: 模型的结构,因为上线业务需要,更趋向于稳定有经验的,未探索一些新的结构 模型的加速仍然不够,还没有压榨完GPU的全部潜力 深感还有很多很多需要学习的地方啊。 既然要学习,那么学习路线就显得比
pytorch-deeplab-resnetpytorch中的DeepLab resnet v2模型
02-05
pytorch-deeplab-resnet 模型实现。 deepLab-ResNet的体系结构已完全复制自caffe实现。 该体系结构可在多个比例(1x,0.75x,0.5x)上计算输图像上的损耗。 在这三个等级上分别计算损失。 除了这3个损失外,在将3...
pytorch_notebooks::fire:用于学习和练习深度学习的PyTorch笔记本集合
02-03
pytorch_notebooks::fire:用于学习和练习深度学习的PyTorch笔记本集合
Pytorch实现:使用ResNet18网络训练Cifar10数据集,测试集准确率达到95.46%(从0开始
10-19
Pytorch实现:使用ResNet18网络训练Cifar10数据集,测试集准确率达到95.46%(从0开始,不使用预训练模型).zip
卷积神经网络ResNet50训练CIFAR-100图像分类Pytorch实现
07-03
1. 使用pytorch调用CIFAR-100数据集,首次训练自动下载; 2. 包含训练代码,调用resnet50模型进行训练,使用交叉熵损失和SGD优化器; 3. 包含训练了50 epochs的模型,在CIFAR-100测试集上准确率62%; 4. 包含两版...
pycharm不认识numpy?_深度学习(CV方向)不完全指南
weixin_39845406的博客
11-21 218
  前言:这篇文章算是我研究生期间在深度学习这块摸爬滚打收获到的一点皮毛之见。对于刚刚接触这一块,尤其是计算机视觉这块的萌新而言,或许有一定的参考价值。因为这篇文章算是对一些基础知识点的汇总,主要目的在于建立一套完整的知识体系,对具体某个知识点不会做太多深的讲解。因此对于某个具体知识点不了解的童鞋,不妨充分发挥自己的主观能动性,充分利用互联网来学习相关知识点~01.框架选择:Pytor...
【python深度学习】——torch.min()
steptoward的博客
05-28 490
当传两个张量时,torch.min() 会比较两个张量中的每个位置的元素,并返回对应位置的最小值。当指定 dim 参数时,torch.min() 会返回沿指定维度的最小值以及对应的索引。不指定维度时, torch.min() 输出整个张量中所有元素的最小值。
动手学深度学习4.7 前向传播、反向传播和计算图-笔记&练习(PyTorch
最新发布
scdifsn的博客
05-29 1106
李沐老师《动手学深度学习(Pytorch版)》4.7 前向传播、反向传播和计算图-笔记&练习详解
pytorch中贝叶斯优化算法加resnet
09-03
PyTorch中使用贝叶斯优化算法来调整超参数并加ResNet模型,可以通过以下步骤实现: 1. 首先,确保已经安装了Ax库。Ax是一个用于优化参数的Python库,可以在PyTorch中使用贝叶斯优化算法。 2. 导所需的库和...

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
写文章

分类专栏

  • 自监督学习 1篇
  • FSL 1篇
  • VLM 1篇
  • 目标检测 8篇
  • OCR 2篇
  • 图像超分辨率重建 9篇
  • caffe 3篇
  • 文献管理 1篇
  • vtk学习 5篇
  • LeetCode 8篇
  • 图像超分辨率重建 10篇
  • MRI图像处理 2篇
  • GAN 2篇
  • Python学习 26篇
  • 深度学习 5篇
  • Pytorch 3篇
  • Theano 1篇
  • Tensorflow 2篇
  • C++ 49篇
  • Java 3篇
  • Matlab 3篇
  • Linux 7篇
  • 硬件 1篇
  • Git学习 2篇
  • Latex 1篇
  • VTK 4篇
  • ITK 5篇
  • 生活 1篇
  • 刷题 9篇
  • Docker 4篇

最新评论

  • Latex排版大括号让其左对齐

    12-14: 不错,解决了问题!

  • matlab报错:尝试将 SCRIPT xxx 作为函数执行

    次声电磁波整人术: 两个文件名字相同了

  • Win10+VS2017安装FFTW库

    进阶的程序媛: 成功了,谢谢

  • 解决Docker不能stop或者kill一个容器方法

    早期看太阳: 前面都是白忙,直接到最后一步,把改容器对应的进程kill掉,就可以正常的stop和rm了,感谢

  • matlab报错:尝试将 SCRIPT xxx 作为函数执行

    木木好乖: 不用一个一个,直接在omp和ksvd两个private子目录下用命令行窗口输入make运行,自动帮所有的都编译好

最新文章

  • VLM系列文章导言
  • 小样本学习(FSL)系列文章
  • 自监督(SSL)系列文章导言
2024年3篇
2021年2篇
2020年16篇
2019年71篇
2018年65篇

目录

目录

评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值

两个鬼故事网站取名起名大全网起什么名字好 五行缺土亿万懦夫起名字专业水产公司起名大全免费观看女鞋店起名简洁大气沙盘公司名字起名大全电子邮箱163商标起名注意事项合肥起名春天的古诗大全300首曹起名男生名字大全鬼来咬搞笑动态qq表情江汉路万达广场医疗器械公司起名大全大全双包胎起名杭州火车票代售点朝花夕拾简介好汉字起名水产店 起名劭是凶字不能用于起名11月22英雄无敌3末日之刃五行缺火女孩起名用字姓张怎么取名起名大全中国字典大全起名字小吃加盟一点通项羽简介姓刘狗年宝宝起名字少年生前被连续抽血16次?多部门介入两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”淀粉肠小王子日销售额涨超10倍高中生被打伤下体休学 邯郸通报单亲妈妈陷入热恋 14岁儿子报警何赛飞追着代拍打雅江山火三名扑火人员牺牲系谣言张家界的山上“长”满了韩国人?男孩8年未见母亲被告知被遗忘中国拥有亿元资产的家庭达13.3万户19岁小伙救下5人后溺亡 多方发声315晚会后胖东来又人满为患了张立群任西安交通大学校长“重生之我在北大当嫡校长”男子被猫抓伤后确诊“猫抓病”测试车高速逃费 小米:已补缴周杰伦一审败诉网易网友洛杉矶偶遇贾玲今日春分倪萍分享减重40斤方法七年后宇文玥被薅头发捞上岸许家印被限制高消费萧美琴窜访捷克 外交部回应联合利华开始重组专访95后高颜值猪保姆胖东来员工每周单休无小长假男子被流浪猫绊倒 投喂者赔24万小米汽车超级工厂正式揭幕黑马情侣提车了西双版纳热带植物园回应蜉蝣大爆发当地回应沈阳致3死车祸车主疑毒驾恒大被罚41.75亿到底怎么缴妈妈回应孩子在校撞护栏坠楼外国人感慨凌晨的中国很安全杨倩无缘巴黎奥运校方回应护栏损坏小学生课间坠楼房客欠租失踪 房东直发愁专家建议不必谈骨泥色变王树国卸任西安交大校长 师生送别手机成瘾是影响睡眠质量重要因素国产伟哥去年销售近13亿阿根廷将发行1万与2万面值的纸币兔狲“狲大娘”因病死亡遭遇山火的松茸之乡“开封王婆”爆火:促成四五十对奥巴马现身唐宁街 黑色着装引猜测考生莫言也上北大硕士复试名单了德国打算提及普京时仅用姓名天水麻辣烫把捣辣椒大爷累坏了

两个鬼故事 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化