AI 助理
备案 控制台
开发者社区 大数据与机器学习 文章 正文

Transformer中高级位置编码的介绍和比较:Linear Rope、NTK、YaRN、CoPE

本文涉及的产品
实时数仓Hologres,5000CU*H 100GB 3个月
推荐场景:
轻松玩转一站式实时仓库
智能开放搜索 OpenSearch行业算法版,1GB 20LCU 1个月
推荐场景:
搭建高质量商品搜索服务
实时计算 Flink 版,5000CU*H 3个月
推荐场景:
实时发现最热Github项目
简介: 在NLP中,位置编码如RoPE、CoPE等增强模型对序列顺序的理解。RoPE通过旋转矩阵编码位置,适应不同距离的相对位置。线性旋转、NTK和YaRN是RoPE的变体,优化长序列处理。CoPE是动态的,根据序列内容调整位置编码,改善长距离依赖的捕捉。这些技术提升了模型在处理复杂语言任务时的性能。

在处理诸如文本之类的序列时,排序信息显然是至关重要的。为了结合排序信息而不是将序列视为集合,对位置信息进行编码是至关重要的。位置编码通过为每个位置分配嵌入向量并将其添加到相应的标记表示来实现这一点。绝对和相对位置编码是最常见的两种位置编码方式,但是本文将要比较更高级的位置编码方法:

1、RoPE 位置编码及其变体

2、CoPE

旋转位置编码

旋转位置编码(Rotary Positional Encoding,RoPE)是一种在自然语言处理(NLP)中处理序列数据时使用的技术。它旨在通过旋转方式将位置信息编码到输入的表示中,使得模型能更好地理解序列中元素的位置关系。关键思想是通过将上下文表示与旋转矩阵相乘来编码相对位置。RoPE随相对距离的增加而衰减。

RoPE 的核心思想是通过在每个位置应用一个旋转矩阵到每个词元的嵌入上,从而将位置信息融入到词元的表示中。这种编码方式允许模型在处理序列数据时,能够更好地利用位置信息,提升语义理解和语言生成的质量。

我们简单的实现一下RoPE:

 defapply_rope(k, q, cis):
     # Idea suppose vector v = [x,y,x1,y1,...] # v.shape = dim
     # convert vetor into complex num # ie two vec one real, one imagery
     # [x,y,x1,y1,...] -> x+iy, x1+iy1
     # Multiplying by complex num == roatate vector
     # => (x + iy) * (cos + isin) -> x'+iy'
     # restack
     # x'+iy' -> [x',y',x1',y1'...]
     # you roated vector in chunks of two lfg!!!
     _, seq_len, _, _=q.shape
     freqs_cos, freqs_sin=cis
     freqs_cos, freqs_sin=freqs_cos[:seq_len], freqs_sin[:seq_len]
     #  rehsape a shape (...,n )-> (..., n//2,2)
     q_cis=q.float().reshape(
         q.shape[:-1] + (-1, 2)
     )  # (B,T,nhead,C) -> (B,T,nhead,Cc,2) # Cc = C//2
     k_cis=k.float().reshape(k.shape[:-1] + (-1, 2))  # (B,T,nhead,C) -> (B,T,nhead,Cc,2)
     xq_r, xq_i=q_cis.unbind(-1)  # (B,T,nhead,Cc,2) -> ((B,T,Cc), (B,T,Cc)) split into two tuple
     xk_r, xk_i=k_cis.unbind(-1)  # (B,T,nhead,Cc,2) -> ((B,T,Cc), (B,T,Cc))
     freqs_cos=reshape_for_broadcast(freqs_cos, xq_r)  # freqs.shape = (1,T,1,Cc)
     freqs_sin=reshape_for_broadcast(freqs_sin, xq_r)
     xq_out_r=xq_r*freqs_cos-xq_i*freqs_sin  # (ac-bd)   # shape =  # (B,T,nhead,Cc)
     xq_out_i=xq_r*freqs_sin+xq_i*freqs_cos  # (ad+bc) * i
     xk_out_r=xk_r*freqs_cos-xk_i*freqs_sin  # (ac-bd)
     xk_out_i=xk_r*freqs_sin+xk_i*freqs_cos  # (ad+bc) * i
     # now we stack r,i -> [r,i,r2,i2]
     xq_out=torch.stack([xq_out_r, xq_out_i], dim=-1)  # (B,T,nhead,Cc,2)
     xk_out=torch.stack([xk_out_r, xk_out_i], dim=-1)  # (B,T,nhead,Cc,2)
     # flatten last two dimensions
     xq_out=xq_out.flatten(3)  # (B,T,nhead,C)
     xk_out=xk_out.flatten(3)  # (B,T,nhead,C)
     returnxq_out.type_as(q), xk_out.type_as(q)

这是我们下面介绍的一些变体的基础,所以实现的比较简单。下面我们主要介绍一些变体:

基于旋转矩阵/旋转角度以及如何预先计算cos和sin频率,RoPE有三种变体。为了将模型的上下文长度扩展到预训练的极限之外,还会引入一些方法相关的函数。

线性旋转位置编码

在线性旋转位置编码中,通过引入以下方法相关函数g(m)和h(θ_d)来修改RoPE方程:

其中s为比例因子(扩展上下文长度与原始上下文长度之比),θ_d定义如下,b为底数(10000)

最后将波长(与频率成反比)描述为在维度d上嵌入RoPE以执行完整旋转(2π)所需的token长度。

实现如下:

 defprecompute_freqs_cis_linear(dim: int, end: int, theta: float=10000.0):
     freqs=1.0/ (theta** (torch.arange(0, dim, 2)[: (dim//2)].float() /dim))
     # [: (dim // 2)] for odd number truncation
     t=torch.arange(end, device=freqs.device)
     freqs=torch.outer(t, freqs).float()  # gives diffrent angle vector
     freqs_cos=torch.cos(freqs)  # real
     freqs_sin=torch.sin(freqs)  # imaginary

     returnfreqs_cos, freqs_sin

NTK

神经切线核(Neural Tangent Kernel,简称NTK)是一种在深度学习领域中被广泛研究的概念,它提供了一种框架来分析和理解神经网络训练过程中的动态行为。NTK是在无限宽度极限下的神经网络中定义的,即当网络的层宽度趋向于无限大时,网络的行为可以通过一个固定的核函数来描述。

NTK 核贡献在于将传统的神经网络训练过程与核方法联系起来。在无限宽度的假设下,神经网络在初始化后的行为可以被描述为一个线性模型,其权重通过NTK进行更新。这意味着,在这种情况下,神经网络的学习动态可以通过解析形式来精确计算,而这通常在有限宽度的网络中是不可能的。

NTK 感知插值解决了在插值RoPE嵌入时丢失高频信息的问题,通过减少对高频的缩放,增加对低频的缩放,这与将RoPE的每个维度均匀地缩放一个因子s不同,所以只需对θ的值执行基本变化即可完成,代码如下:

 defprecompute_freqs_cis_ntk(dim: int, end: int, theta: float=10000.0, alpha: int=16):
     theta=theta*alpha** (dim/ (dim-2))
     freqs=1.0/ (theta** (torch.arange(0, dim, 2)[: (dim//2)].float() /dim))\
     t=torch.arange(end, device=freqs.device)
     freqs=torch.outer(t, freqs).float()
     freqs_cos=torch.cos(freqs)  # real
     freqs_sin=torch.sin(freqs)  # imaginary
     returnfreqs_cos, freqs_sin

YaRN

YaRN(Yet another RoPE extensioN)是通过一种高效的计算方法来扩展模型的上下文窗口,比以前的方法减少10倍的令牌和2.5倍的训练步骤。它引入了一个ramp函数,并将该函数合并到方法依赖函数中,如下所示:


 defprecompute_freqs_cis_yarn(dim: int, original_max_position_embeddings: int, theta: float=10000.0, scale: int=16, beta_fast:int=32, beta_slow:int=1, mscale: float=0.707,  max_position_embeddings: int=2048):
     pos_freqs=theta** (torch.arange(0, dim, 2)[: (dim//2)].float() /dim)
     inv_freq_extrapolation=1.0/pos_freqs
     inv_freq_interpolation=1.0/ (scale*pos_freqs)
     low=max(math.floor(dim*math.log(original_max_position_embeddings/(beta_fast*2*math.pi)))/(2*math.log(theta)),0)
     high=min(math.ceil(dim*math.log(original_max_position_embeddings/(beta_slow*2*math.pi)))/(2*math.log(theta)),dim-1)
     linear_func= (torch.arange(dim//2, dtype=torch.float32) -low) / (high-low)
     ramp_func=torch.clamp(linear_func, 0, 1).float().to(device=pos_freqs.device)
     inv_freq_mask=1-ramp_func
     inv_freq=inv_freq_interpolation* (1-inv_freq_mask) +inv_freq_extrapolation*inv_freq_mask
     _mscale=float((0.1*math.log(scale) +1.0) *mscale)
     t=torch.arange(max_position_embeddings, device=inv_freq.device, dtype=inv_freq.dtype) # torch.Size([2048])
     freqs=torch.outer(t, inv_freq) # torch.Size([2048, 48]) 
     dtype=torch.get_default_dtype()
     freqs_cos=freqs.cos() *_mscale
     freqs_sin=freqs.sin() *_mscale

     returnfreqs_cos, freqs_sin

上下文位置编码(CoPE)

上下文位置编码(Contextual Positional Encoding,简称CoPE)是一种在处理序列数据时用于提高模型性能的技术。这种编码方法在自然语言处理(NLP)和其他需要处理时间序列数据的任务中尤其重要,因为它可以更好地捕获序列中元素的上下文关系。

传统的位置编码(如Transformer中使用的正弦位置编码)通常是静态的,即对于给定的位置,位置编码总是相同的,不考虑序列的具体内容。而上下文位置编码(CoPE)则试图根据序列中的实际内容动态调整位置编码,使编码反映出序列中每个元素的上下文环境。

门控机制

门控决定包含哪些令牌,以便使用它们的上下文向量来计算位置编码,并为每个查询键对计算一个门控值。:

值为1表示标记号在位置计数中被考虑,而值为0表示它被忽略。

计算位置嵌入

要计算位置嵌入,需要添加当前令牌和之前所有令牌之间的门值。每个位置可以表示给定序列中的一个记号/单词/句子号。

为了计算有限的位置,即如果门是稀疏激活的(当计算句子时),可以用更少的位置覆盖序列长度T的整个上下文,并将每个位置夹在最大可能的位置内。

因为添加了sigmoid输出[0,1],得到的每个第i个位置值都是[0,i]内的浮点数。所以位置是不可学习的,不能由嵌入层计算。

位置嵌入的插值

为了克服上述由于位置值浮动而导致的学习嵌入层的限制,会对序列中的每个整数位置分配一个可学习的位置嵌入e[p],第ij个元素的位置嵌入将是由上述计算的分数位置值加权的两个最接近的整数嵌入之间进行简单的插值。

最后通过添加关键向量中的位置嵌入来计算注意力。

CoPE的实现

为了节省内存和计算,q.e[p]矩阵会被预先计算,这样可以进一步进行插值,然后添加到上下文中。插值计算如下:

 classCoPE(nn.Module):
     def__init__(self, npos_max, head_dim):
         super().__init__()
         self.npos_max=npos_max
         self.pos_emb=nn.Parameter(torch.zeros(1, head_dim, npos_max))

     defforward(self, query, attn_logits):
         # Compute positions
         gates=torch.sigmoid(attn_logits)
         pos=gates.flip(-1).cumsum(dim=-1).flip(-1)
         pos=pos.clamp(max=self.npos_max-1)

         # Interpolate from integer positions
         pos_ceil=pos.ceil().long()
         pos_floor=pos.floor().long()

         logits_int=torch.matmul(query, self.pos_emb)
         logits_ceil=logits_int.gather(-1, pos_ceil)
         logits_floor=logits_int.gather(-1, pos_floor)

         w=pos-pos_floor
         returnlogits_ceil*w+logits_floor* (1-w)

给定查询矩阵和查询键乘积,CoPE类的前向传播可以返回内插的位置嵌入。下面就是要将它们添加到Attention类中的attn_mtx上下文中。

 classAttention(nn.Module):
     def__init__(self, model_args: MOEConfig):
         super().__init__()
         d_model=model_args.d_model
         self.num_heads=model_args.num_heads
         self.head_dim=model_args.d_model//model_args.num_heads
         self.num_kv_heads= (
             model_args.num_headsifmodel_args.num_kv_heads==0elsemodel_args.num_kv_heads
         )
         assertself.num_heads%self.num_kv_heads==0
         self.num_queries_per_kv=self.num_heads//self.num_kv_heads
         self.cope=CoPE(model_args.seq_len,self.head_dim)
         self.key=nn.Linear(d_model, self.head_dim*self.num_heads)
         self.query=nn.Linear(d_model, self.head_dim*self.num_kv_heads)
         self.value=nn.Linear(d_model, self.head_dim*self.num_kv_heads)
         self.proj=nn.Linear(d_model, d_model, model_args.bias)
         self.attn_dropout=nn.Dropout(model_args.dropout)
         self.res_dropout=nn.Dropout(model_args.dropout)
         self.flash_attn=hasattr(torch.nn.functional, "scaled_dot_product_attention")
     defforward(self, x: torch.Tensor, mask: torch.Tensor, freqs_cis) ->torch.Tensor:
         batch, seq_len, d_model=x.shape
         k: torch.Tensor  
         q: torch.Tensor  
         v: torch.Tensor
         k=self.key(x)
         q=self.query(x)
         v=self.value(x)
         k=k.view(
             batch, seq_len, self.num_heads, self.head_dim
         )  # shape = (B, seq_len, num_heads, head_dim)
         q=q.view(batch, seq_len, self.num_heads, self.head_dim)
         v=v.view(batch, seq_len, self.num_heads, self.head_dim)
         q, k=apply_rope(q, k, freqs_cis)
         # Grouped Query Attention
         ifself.num_kv_heads!=self.num_heads:
             k=torch.repeat_interleave(k, self.num_queries_per_kv, dim=2)
             v=torch.repeat_interleave(v, self.num_queries_per_kv, dim=2)
         k=k.transpose(1, 2)  # shape = (B, num_heads, seq_len, head_dim)
         q=q.transpose(1, 2)
         v=v.transpose(1, 2)
         attn_mtx=torch.matmul(q, k.transpose(2, 3)) /math.sqrt(self.head_dim)
         attn_mtx=attn_mtx+mask[:, :, :seq_len, :seq_len]
         print("Before:", attn_mtx[0, 0, :3, :3])
         attn_mtx+=self.cope(q,attn_mtx)
         print("AFTER:", attn_mtx[0, 0, :3, :3])
         attn_mtx=F.softmax(attn_mtx.float(), dim=-1).type_as(k)
         attn_mtx=self.attn_dropout(attn_mtx)
         output=torch.matmul(attn_mtx, v)  # (batch, n_head, seq_len, head_dim)
         # restore time as batch dimension and concat heads
         output=output.transpose(1, 2).contiguous().view(batch, seq_len, d_model)
         # final projection into the residual stream
         output=self.proj(output)
         output=self.res_dropout(output)
         returnoutput

attn_mtx += self.cope(q, attn_mtx)是将cope嵌入添加到上下文的地方。

CoPE通过引入与序列内容相关的动态位置信息,使模型能更准确地理解和处理语言中的长距离依赖关系,例如在复杂的句子或文档中正确解释词义和句子结构。在处理多样化或特定领域的数据时,CoPE可以通过适应不同的文本特征和结构,提高模型的灵活性和泛化能力。在一些需要高度上下文感知的任务中,如机器翻译、文本摘要或对话系统,CoPE能够显著提升模型的性能。

总结

以下是本文介绍的一些方法的论文,供参考:

https://avoid.overfit.cn/post/91fd4283a7944bebabb6017f5ee285e9

作者:Zain ul Abideen

Deephub
目录
相关文章
YOLO创新改进大师
|
5月前
|
机器学习/深度学习 计算机视觉
【YOLOv8改进】CoordAttention: 用于移动端的高效坐标注意力机制 (论文笔记+引入代码)
该专栏聚焦YOLO目标检测的创新改进与实战,介绍了一种新的移动网络注意力机制——坐标注意力。它将位置信息融入通道注意力,通过1D特征编码处理,捕获长距离依赖并保持位置精度。生成的注意力图能增强目标表示,适用于MobileNetV2、MobileNeXt和EfficientNet等网络,提高性能,且几乎不增加计算成本。在ImageNet分类和下游任务(目标检测、语义分割)中表现出色。YOLOv8中引入了CoordAtt模块,实现位置敏感的注意力。更多详情及配置见相关链接。
YOLO创新改进大师
259 0
阿旭算法与机器学习
|
4月前
|
机器学习/深度学习 Shell
【从零开始学习深度学习】22. 卷积神经网络(CNN)中填充(padding)与步幅(stride)详解,填充、步幅、输入及输出之间的关系
【从零开始学习深度学习】22. 卷积神经网络(CNN)中填充(padding)与步幅(stride)详解,填充、步幅、输入及输出之间的关系
阿旭算法与机器学习
94 3
YOLO创新改进大师
|
4月前
|
机器学习/深度学习 前端开发 计算机视觉
【YOLOv8改进】Explicit Visual Center: 中心化特征金字塔模块(论文笔记+引入代码)
YOLO目标检测专栏介绍了YOLO的有效改进和实战案例,包括卷积、主干网络、注意力机制和检测头的创新。提出中心化特征金字塔(CFP)解决特征交互和局部区域忽视问题。CFP通过空间显式视觉中心方案和全局集中特征规范增强模型表现,尤其在YOLOv5和YOLOX上表现提升。创新点包括轻量级MLP和并行视觉中心机制,以捕获全局和局部信息。YOLOv8引入EVCBlock整合这些改进。详细代码和配置见链接。
YOLO创新改进大师
158 3
拓端数据部落
|
5月前
【视频】线性混合效应模型(LMM,Linear Mixed Models)和R语言实现案例(四)
【视频】线性混合效应模型(LMM,Linear Mixed Models)和R语言实现案例
拓端数据部落
44 0
拓端数据部落
|
5月前
|
机器学习/深度学习 数据可视化 数据挖掘
【视频】线性混合效应模型(LMM,Linear Mixed Models)和R语言实现案例(一)
【视频】线性混合效应模型(LMM,Linear Mixed Models)和R语言实现案例
拓端数据部落
81 0
拓端数据部落
|
5月前
|
数据可视化 测试技术
【视频】线性混合效应模型(LMM,Linear Mixed Models)和R语言实现案例(三)
【视频】线性混合效应模型(LMM,Linear Mixed Models)和R语言实现案例
拓端数据部落
78 0
拓端数据部落
|
5月前
【视频】线性混合效应模型(LMM,Linear Mixed Models)和R语言实现案例(二)
【视频】线性混合效应模型(LMM,Linear Mixed Models)和R语言实现案例
拓端数据部落
37 0
虚心求知的熊
|
机器学习/深度学习 人工智能 自然语言处理
PyTorch 之 简介、相关软件框架、基本使用方法、tensor 的几种形状和 autograd 机制-1
PyTorch 是一个基于 Torch 的 Python 开源机器学习库,用于自然语言处理等应用程序。它主要由 Facebook 的人工智能小组开发,不仅能够实现强大的 GPU 加速,同时还支持动态神经网络,这一点是现在很多主流框架如 TensorFlow 都不支持的。
虚心求知的熊
230 0
虚心求知的熊
|
并行计算 PyTorch 测试技术
PyTorch 之 简介、相关软件框架、基本使用方法、tensor 的几种形状和 autograd 机制-2
由于要进行 tensor 的学习,因此,我们先导入我们需要的库。
虚心求知的熊
103 0
心无旁骛~
|
机器学习/深度学习
深度学习入门基础CNN系列——感受野和多输入通道、多输出通道以及批量操作基本概念
本篇文章主要讲解卷积神经网络中的感受野和通道的基本概念,适合于准备入门深度学习的小白,也可以在学完深度学习后将其作为温习。
心无旁骛~
165 0
深度学习入门基础CNN系列——感受野和多输入通道、多输出通道以及批量操作基本概念

大数据与机器学习

热门文章

最新文章

  • 1
    阿里云开源离线同步工具DataX3.0介绍
  • 2
    DataV 4.0 功能简介
  • 3
    大数据美食——寻找地图上的美味
  • 4
    阿里封神谈hadoop生态学习之路
  • 5
    【玩转数据系列十】利用阿里云机器学习在深度学习框架下实现智能图片分类
  • 6
    每个人都应该知道的25个大数据术语
  • 7
    你刚吃的兰州牛肉面,背后就藏着大数据
  • 8
    大数据环境下该如何优雅地设计数据分层
  • 9
    盘古:阿里云飞天分布式存储系统设计深度解析
  • 10
    odps是什么?
  • 1
    API和SDK的区别
    8
  • 2
    将word文档转换成pdf文件方法
    12
  • 3
    终极 Nginx 配置指南
    12
  • 4
    【10月更文挑战第13天】「Mac上学Python 24」小学奥数篇10 - 数列求和
    14
  • 5
    提高爬虫性能的 5 个关键技巧:从并发到异步执行
    10
  • 6
    淘宝API接口注意事项及要点
    9
  • 7
    常见的京东商品接口类型
    10
  • 8
    青否数字人直播间五大互动,承诺抖音封号即退款!
    7
  • 9
    《触手可及,函数计算玩转 AI 大模型》解决方案体验与部署评测
    9
  • 10
    阿里云实时计算Flink版评测报告
    15
  • 相关电子书

    更多
  • Quanta:Quora的HBase分层计数系统
  • 低代码开发师(初级)实战教程
  • 阿里巴巴DevOps 最佳实践手册
  • 相关实验场景

    更多
  • 【自由换模型】基于函数计算一键部署 Stable Diffusion
  • 下一篇
    AI助理化繁为简,速取代码参数——使用python SDK 处理OSS存储的图片

    玻璃钢生产厂家玻璃钢雕塑花纹马福州仿铜西式玻璃钢雕塑永安玻璃钢人像雕塑金华商场美陈龙岩模压法玻璃钢雕塑价格太原玻璃钢雕塑定制玻璃钢金属铸造雕塑玻璃钢雕塑石家庄苏州商场美陈布置太原卡通玻璃钢雕塑定做山东玻璃钢人像雕塑加工厂创意商场卫生间美陈宁波玻璃钢抽象动物雕塑厂家加工玻璃钢动物牛雕塑哪里有卖的汕头玻璃钢雕塑批发定制饶阳人物玻璃钢雕塑广东超市商场美陈多少钱封丘玻璃钢雕塑厂家双十一商场美陈效果图福建城市几何玻璃钢雕塑丽江市玻璃钢雕塑加盟商揭阳楼盘玻璃钢人物雕塑昆山玻璃钢雕塑多少钱广东加工玻璃钢动物雕塑安徽玻璃钢雕塑厂家工厂杭州销售玻璃钢面包雕塑江苏定做玻璃钢雕塑玻璃钢雕塑用什么才料原平市商场美陈玻璃钢丹顶鹤雕塑香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

    玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化