热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

图卷积网络进行骨骼识别代码_图卷积行为识别顶会文章解读及思路分析

脚本之家你与百万开发者在一起图卷积发展概述图卷积网络是近年来流行的一种在图上开展机器学习的神经网络模型,最早由JoanBruna于14年提出[7]空域和谱域两种不同的
c3c67f21d82c904351036b4cdf99a672.png

脚本之家

你与百万开发者在一起

14bc6352bee4736fb8dfc004dd1eb63c.gif

图卷积发展概述

图卷积网络是近年来流行的一种在图上开展机器学习的神经网络模型,最早由Joan Bruna于14年提出[7]空域和谱域两种不同的图机器学习思路,工作[11]提出了空域图卷积思路,工作[9]在工作[7]的基础上进一步设计了空域图卷积网络以及相应的谱方法,工作[8]运用谱图卷积的思想对邻接矩阵实现了归一化,提出了一种将空域和谱域融合的 GCN模型,这也是目前使用最为广泛的模型。最近H.Ferenc在工作[10]中对图卷积提出了异议,也给学者们提供了新的研究方向。以上5篇文章是图卷积网络领域的标杆论文,如果要深入了解图卷积,建议全部阅读。

图卷积网络

空域图卷积最早由工作[11]提出,其思想是将每个节点与其邻居节点的特征进行加权平均,然后传播到下一层,使用邻域来确定每个节点的加权平均范围(卷积范围),使用label策略来为参与卷积的节点分配权重,其层间传播公式为:

992a0a45da340c2032b367243ff41f66.png(1)

其中A是邻接矩阵,是图结构的一种常用数学表示,包含了邻居节点信息,通过矩阵乘法可以使得每个节点和其邻居节点特征进行聚合。W是权重矩阵,主要对边进行加权。这样的传播方法缺点是没有对邻接矩阵进行归一化,这使得A在传播过程中不断扩张(每次都乘矩阵A会导致特征值越来越大)。此外,由于A对角线元素为0,每个节点自身在进行卷积时不能将自己的特征计算在内。因此工作[8]提出了谱域图卷积的思想来解决这两个问题。

谱域图卷积的推导过程相对来讲要复杂很多,主要是借助于图的拉普拉斯矩阵和傅里叶变换来进行的,但是最后得到的层间传播公式并不复杂:

05c776948251cc4dc824bf8014219c16.png(2)

其中矩阵0f900dddd4c5c914658ff5795489e7d6.png用于对扩展邻接矩阵(A+I)进行归一化。

公式(2)所描述的图卷积模型可以从很直观的角度理解。首先和单纯的空域图卷积(1)相比,对邻接矩阵做了自环操作(A+I),通过加单位矩阵的方法,使得中心节点自身的特征能参与卷积。然后通过矩阵b653c65da3b3fecafb38b869beb800bc.png对邻接矩阵实现归一化,解决了A随层数不断增长的问题。其他的部分就和公式(1)完全一致了。因此我们可以说公式(2)是利用谱域图卷积的思想来弥补了空域图卷积的缺点,本质上是两种卷积思想的结合。公式(2)是层间传播公式的矩阵形式,相应的节点形式为:

86ab5f3ca18671ce10cd4fe0327b934c.png(3)

12def8e9447d162fc18f34dca2a4545d.png

其中c9586426e6fc4461be915ad6384c1ece.png是节点f195abde516c83d9da3cbda671e23e59.png的邻域,5b250b1bcfe0d93a94e892c2f4edda19.png是归一化因子,3a0115b891beef81209070880c749938.png是节点2082846c5108c5ce10b093f265a631ba.png输入该层的特征向量,5fbe054d84f66fe9331ce5f0e27e41bd.png是以节点f195abde516c83d9da3cbda671e23e59.png为中心按照label策略为2082846c5108c5ce10b093f265a631ba.png分配的label(K个label中的一个),4fe5bcbc7666c33210a6e9474977c27f.png是权重的集合(不同于(2)和(1)中的W),ab83ecb8ae01abcc5cd16eb6c2f85b18.png则是根据label分配的权重矩阵,每一列对应一个kernel的权重向量(在文献[6]的解读中会回答这个问题)。00d873a2bd33ebeb5849ca99b93dcfab.png是节点f195abde516c83d9da3cbda671e23e59.png在该层的输出特征值,通常还需要经过激活函数才会传播到下一层,作为下一层该节点的输入值。

谱域图卷积和空域图卷积是相辅相成的,空域图卷积提供了在图上开展机器学习的基本思想,谱域图卷积则是从图的拉普拉斯矩阵出发,推导出了和空域图卷积类似的卷积方法,并且解决了空域图卷积的两个问题。

公式(2)所描述的模型是目前使用最广泛的图卷积模型,由17年的工作[8]提出,因此从18年开始,许多行为识别领域的工作就开始围绕这种模型进行了。

图卷积在行为识别任务中的应用

行为识别是对包含有动作信息的数据进行分类,属于分类任务,通过时空特征来动作分类是该领域研究的主要思路。该领域研究按照输入数据形式主要分为三类:基于RGB图片或视频的行为识别,基于2D骨骼序列的动作识别,基于3D骨骼序列的动作识别。目前业界研究重点主要在第一和第三种数据,主要是这两种数据都有对应的大型数据集。基于RGB图片或视频的工作目前的主流方法是two-stream双流网络,一个流发掘空间特征,一个流发掘时间特征,而基于2D和3D骨骼序列的主流方法就是图卷积网络了。

骨骼序列就是将所有关节在每一时刻的空间位置层叠起来,排列成时间序列。由于人体骨骼结构可以用图结构来表示,顶点表示关节,边表示连接关节的肢节,因此可以用图卷积网络来发掘骨骼之间的空间联系。进一步的,如果我们能将图卷积操作拓展到时域上,就能同时发掘空间和时间特征。

[1] Spatial Temporal Graph Convolutional Networks for Skeleton-Based Action Recognition (AAAI, 2018)

ee8bce291a267d86d2681982ad9d8031.png

1.时空域中的邻域定义

我们熟知的图卷积网络都是在空域进行的,这是因为邻域的通常在空域中定义。为了让发掘骨骼动作序列中的时间特征,本文首先将同一个关节与该关节在前后时刻的位置相连,得到一个时空连接图,这样就可以将序列转化为一张时空域中的三维图,然后在这个时空域上重新定义了邻域:

81f36cb3356cd0440be31934f5e838b2.png

这里卷积中心点是12a8736350631b8cf4bb12af03c77b02.png,中间节点是0706909ed18eec047cf7de59e40efd05.png,待判断节点是3f2423d25aea12671c0f032b197393d4.png,待判断节点和中间节点是同一个关节的不同时刻(同一个关节j,不同时刻t和q),而中间节点和中心点是位于同一时刻的不同关节(同一个时刻t,不同关节i和j)。对于那些和中心点不在同一帧的待判断点,首先判断他们和中间节点的帧距离(时间距离)是否满足要求,其次判断中间节点和中心节点的空间距离是否满足要求,如果都满足要求,那么待判断节点就属于卷积中心点的邻域节点,参与卷积中心点的卷积操作。

2.权重分配策略

首先介绍一下权重分配策略。GCN使用label策略来分配权重,首先按照一定的规则邻域内的每个节点分配一个label:

98fb84492f7e2b68f5bd93200508f6a5.png(4)

然后根据每个节点的label为其分配一个权重:

12def8e9447d162fc18f34dca2a4545d.png(5)

其中aae460a9a9b9a767544c491065a33d57.png是一个权重矩阵。所以权重在所有节点之间都是共享的,只要label相同,两个节点的权重就相同。所以每一层所有节点共享一起权重矩阵集合,权重集合的大小,以及权重矩阵的维度都是事先设计好的,不会随训练过程改变而改变。因此图卷积网络可以在不同结构的图上训练和测试,这和传统CNN是相同的。

由于本文定义了时空域中的领域概念,因此就得重新定义相应的label策略:

fe7536e45595a5f50fd460eb8dc7563f.png

和邻域策略基本相同,通过计算待判断节点与中心节点在时空图中的距离来分配label。此外,本文还设计了三种不同的规则来分配label:

eb44c5898d0b7c9df5143590a3d7b043.png

图a:领域示意图

图b:第一种策略称为统一label划分,整个邻域内的节点包括中心节点共享一个label,因此这样的话权重矩阵实际上只有一个,在所有节点之间共享。

图c:第二种是基于距离的label划分,将节点的1邻域分为两个子集,即节点本身子集与邻节点子集,因此权重矩阵有两个。引入基于距离的划分使得我们可以分析骨架关键点之间的微分性质。

图d:空间构型划分。这种划分规则将节点的 1 邻域划分为 3 个子集,第一个子集为节点本身,第二个为空间位置上比本节点更靠近整个骨架重心的邻节点集合,第三个则为更远离重心的邻节点集合。建立这种划分规则在根据运动分析的研究中对向心运动与离心运动的定义。

3.单独的边权重

这是不同于一般GCN的一种学习思路,专门针对那些图结构不会发生变化的任务,非常重要的思路,只不过在本文中作者只是提了一下。

基于label的权重学习和分配策略让图中的所有节点都共享一个权重矩阵集合,使得图卷积网络能够在不同结构的图上训练和测试,然而在行为识别任务中,骨骼图的结构在同一个数据集中不会发生变化,对所有动作都是相同的,这使得为每个节点单独分配权重成为可能,更加细化的权重相对于共享权重而言,能精细的发掘每个关节对动作识别的贡献,从而取得更好的识别效果,当然,代价是参数数量的增加。那么如何在参数和性能之间做到平衡呢,这是一个永恒的话题,工作[6]为我们提供了一种不错的思路。

[6] Semantic Graph Convolutional Networks for 3D Human Pose Regression (ArXiv,2019)

这篇文章的主要是将图卷积用于姿态估计,所以,我们将重心放在该文设计的图卷积模型上。

在了解该文工作前,让我们先来回答前面提出的一个问题:为什么权重是矩阵的形式

我把公式(3)抄过来方便查看:

86ab5f3ca18671ce10cd4fe0327b934c.png(3)

我们假设3a0115b891beef81209070880c749938.png输入特征是一个1*M的向量,而我们希望在00d873a2bd33ebeb5849ca99b93dcfab.png的特征维度是N,因此00d873a2bd33ebeb5849ca99b93dcfab.png是一个1*N的向量,那么ab83ecb8ae01abcc5cd16eb6c2f85b18.png就应该是一个M*N的矩阵。所以分配给每个节点的权重都是矩阵形式的。通常我们将这个矩阵的每列都认为是一个卷积kernel,因此每一层的kernel数量决定了下一层的特征向量长度。

单边权重方案一

工作[1]中提到的单边权重,其实就是在共享权重的基础上再对每个节点分配一个标量值e884c92e7eb3107bb3f0a323698ed3e2.png作为该节点的独享权重,将独享权重与共享权重结合起来就得到了该节点的最终权重:

abeb9db35f412986cc53f8780ba6a00f.png(6)

d5a85c9458adec65f318b02457480251.png表示将e884c92e7eb3107bb3f0a323698ed3e2.png乘入矩阵ab83ecb8ae01abcc5cd16eb6c2f85b18.png中的每个元素,例如我们假设:

c062bb07ee4439bde6ff38293cf4a748.png

那么211c129a0c3f0946c5235d8b81b3e3e6.png就为:

c062bb07ee4439bde6ff38293cf4a748.png(7)

实际上就是对权重矩阵做了一个伸缩。这样网络每一层就需要额外再对每个节点学习一个单独的单边权重。我们假设网络有L层,每层有V个节点,那么总共多出来的(相对于传统的GCN)参数数量为:

L*V个

单边权重方案二

也就是本文工作[6]所提出的方案,作者指出,方案一采用的标量单边权重过于简单,不能很好地刻画一些关节的特异性,因此在方案一的基础上将e884c92e7eb3107bb3f0a323698ed3e2.png替换为一个向量062a21c4037c85fb64d05083ce64b62b.png:

88b2ad5df47ebf2a8cae6263c4adb21e.png,18e203231632cfb8c399d4a61f79e472.png

这种方案多出来的参数数量为49aaee3687573240dc3551d30283fa54.png,其中a6df0e0c16a8126e4d7ce78298fa83a5.png是第l层的输入特征维度。这种方案作者只在姿态估计任务中做了测试,目前还没有在行为识别任务中使用过。

单边权重方案三

这是最直观的一种方法,直接抛弃共享权重,权重在节点之间完全独立,每一层的每个节点都需要单独学习一个权重矩阵,那么总的权重矩阵数量为L*V,总的权重个数为:

0e526f025761ea5290c7773d16014320.png

我们假设传统的GCN的节点label有K类(通常K<&#61;3)&#xff0c;那么增加的参数数量为&#xff1a;

374049a149b6789a712c1c0ad0250147.png

显然&#xff0c;在大部分情况下V>>K&#xff0c;增加的参数数量也是最多的&#xff0c;不过好在行为识别中使用的图卷积网络通常都比较浅&#xff0c;因此L不会很大。这种方案是目前我正在探究的一种方案&#xff0c;当然我不会直接使用&#xff0c;会尝试一些方法来降低参数数量。

邻接矩阵学习策略

不同于传统的GCN预先设置邻接矩阵&#xff0c;本文认为邻接矩阵也可以通过网络来自动学习&#xff0c;因此对邻接矩阵中的每个元素都设置了一个权重&#xff0c;因此在每一层&#xff0c;网络除了学习一般的权重矩阵&#xff0c;还需要学习一个邻接矩阵的权重矩阵。如何通过反向传播来同时完成对两个权重矩阵的学习和迭代更新呢&#xff1f;作者没有解释&#xff0c;不过通过一定的推导是可以实现的&#xff0c;篇幅有限&#xff0c;如果想了解&#xff0c;可以继续关注我的后续文章。

分图卷积策略

Part-based Graph Convolutional Network for Action Recognition. (BMVC.2019)

这篇文章首先借鉴了时空图卷积的思路[1]&#xff0c;然后提出了一种较为复杂的图卷积思路&#xff1a;分图卷积。将人体骨骼图按照一定的先验知识划分为多个子图&#xff0c;在对每个节点及其邻域节点进行卷积时&#xff0c;分为两步&#xff1a;

首先将该节点与其他在同一个子图内的邻域节点进行卷积&#xff0c;也就是子图内的卷积&#xff1a;

c3e95be67a99b9667e24feb3cd4266f7.png

这里把权重矩阵放在了特征矩阵前面&#xff0c;和公式(3)本质上无区别&#xff0c;对矩阵做一个转置就可以达到相同的效果。我们将子图内的卷积值称为节点的基本卷积值。

对于那些属于其他子图的邻域节点&#xff0c;先计算这些节点的基本卷积值&#xff0c;然后将基本卷积值与中心节点的基本卷积值用一个函数融合&#xff1a;

9e176d498ca9a57a0cd971ea0091df9f.png

a8b12ec7883edf1d955095a2f2a33082.png

这样就能扩大子图边缘的节点的感受野&#xff0c;同时在一定程度上增加不同子图间信息传播的速度&#xff0c;也能强化同一个子图内的关节之间的联系。

这篇文章提供了多种分图策略。

总结

附录里面还给了一些其他的文章&#xff0c;不过大致思路都和上面介绍的三篇没有太大出入。总结一下&#xff0c;图卷积在行为识别领域的三个最主要的思路为&#xff1a;

1.如何设计权重分配策略&#xff0c;可以考虑不同的label策略&#xff0c;还可以考虑为每个节点单独学习独立权重。

2.如何设计邻接矩阵&#xff0c;可以是根据先验知识来调整邻接矩阵&#xff0c;也可以是让网络自己学习。

3.如何将图卷积扩展到时空域。

[1] Yan, S., Xiong, Y., & Lin, D. (2018). Spatial Temporal Graph Convolutional Networks for Skeleton-Based Action Recognition. AAAI.

[2] Tang, Y., Tian, Y., Lu, J., & Li, P. (2018). Deep Progressive Reinforcement Learning for Skeleton-based Action Recognition. CVPR.

[3] Thakkar, K. (2018). Part-based Graph Convolutional Network for Action Recognition. BMVC.

[4] Li, M., Chen, S., Chen, X., Zhang, Y., Wang, Y., Tian, Q., … Electric, M. (2019). Actional-Structural Graph Convolutional Networks for Skeleton-based Action Recognition. Ar.Xiv.

[5] Si, C., Chen, W., Wang, W., Wang, L., & Tan, T. (2019). An Attention Enhanced Graph Convolutional LSTM Network for Skeleton-Based Action Recognition. CVPR.

[6] Zhao, L. (n.d.).(2019). Semantic Graph Convolutional Networks for 3D Human Pose Regression. Ar.Xiv.

[7] Bruna, J., & Szlam, A. (2014). Spectral Networks and Deep Locally Connected Networks on Graphs. Ar.Xiv. #首次提出了空域和谱域两种不同的图卷积构建方式

[8] Kipf, T. N., & Welling, M. (2017). SEMI-SUPERVISED CLASSIFICATION WITH GRAPH CONVOLUTIONAL NETWORKS. ICLR.  #在图上开展半监督学习&#xff0c;取得了里程碑式的效果

[9] Michaël Defferrard, Bresson, X., & Vandergheynst, P. (2016). Convolutional Neural Networks on Graphs with Fast Localized Spectral Filtering. NIPS.

[10] Jegelka, S. (2019). HOW POWERFUL ARE GRAPH NEURAL NETWORKS.  ICLR. #分析图卷积的潜在缺点和限制

[11] Niepert, M., & Kutzkov, K. (2016). Learning Convolutional Neural Networks for Graphs. ICML.

本文作者&#xff1a;凯隐

声明&#xff1a;本文为 脚本之家专栏作者 投稿&#xff0c;未经允许请勿转载。

- END -

f23c22825c8198e96518f8da11acbac6.png

ed83831c68bde29f7bda913f9734386d.gif

● b27b731f7f29986f56fdf492e2fe28fd.gif 三招教你轻松扩展 git bash 命令(下)

● b27b731f7f29986f56fdf492e2fe28fd.gif 脚本之家粉丝福利&#xff0c;请查看&#xff01;

● b27b731f7f29986f56fdf492e2fe28fd.gif 地球程序员之神&#xff1a;没上过大学&#xff0c;曾拒盖茨的Offer&#xff0c;4代码农靠他吃饭

● 微软劝你别再使用 IE 浏览器

● 痛的不只是华为&#xff0c;这家西方公司卡住中国芯片的脖子

● 一个39岁程序员的应聘被拒

● 入行AI&#xff0c;程序员为什么要学习NLP&#xff1f;

●  五款主流Linux发行版性能对比&#xff0c;不求最强但求稳

d90bd069adbf762100ed98175a6ae7fd.gif

小贴士

返回 上一级 搜索“Java 女程序员 大数据 留言送书 运维 算法 Chrome 黑客 Python Javascript 人工智能 女朋友 MySQL 书籍 等关键词获取相关文章推荐。




推荐阅读
  • 在springmvc框架中,前台ajax调用方法,对图片批量下载,如何弹出提示保存位置选框?Controller方法 ... [详细]
  • Python语法上的区别及注意事项
    本文介绍了Python2x和Python3x在语法上的区别,包括print语句的变化、除法运算结果的不同、raw_input函数的替代、class写法的变化等。同时还介绍了Python脚本的解释程序的指定方法,以及在不同版本的Python中如何执行脚本。对于想要学习Python的人来说,本文提供了一些注意事项和技巧。 ... [详细]
  • 从零基础到精通的前台学习路线
    随着互联网的发展,前台开发工程师成为市场上非常抢手的人才。本文介绍了从零基础到精通前台开发的学习路线,包括学习HTML、CSS、JavaScript等基础知识和常用工具的使用。通过循序渐进的学习,可以掌握前台开发的基本技能,并有能力找到一份月薪8000以上的工作。 ... [详细]
  • 2018年人工智能大数据的爆发,学Java还是Python?
    本文介绍了2018年人工智能大数据的爆发以及学习Java和Python的相关知识。在人工智能和大数据时代,Java和Python这两门编程语言都很优秀且火爆。选择学习哪门语言要根据个人兴趣爱好来决定。Python是一门拥有简洁语法的高级编程语言,容易上手。其特色之一是强制使用空白符作为语句缩进,使得新手可以快速上手。目前,Python在人工智能领域有着广泛的应用。如果对Java、Python或大数据感兴趣,欢迎加入qq群458345782。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • 近年来,大数据成为互联网世界的新宠儿,被列入阿里巴巴、谷歌等公司的战略规划中,也在政府报告中频繁提及。据《大数据人才报告》显示,目前全国大数据人才仅46万,未来3-5年将出现高达150万的人才缺口。根据领英报告,数据剖析人才供应指数最低,且跳槽速度最快。中国商业结合会数据剖析专业委员会统计显示,未来中国基础性数据剖析人才缺口将高达1400万。目前BAT企业中,60%以上的招聘职位都是针对大数据人才的。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • 本文介绍了Oracle数据库中tnsnames.ora文件的作用和配置方法。tnsnames.ora文件在数据库启动过程中会被读取,用于解析LOCAL_LISTENER,并且与侦听无关。文章还提供了配置LOCAL_LISTENER和1522端口的示例,并展示了listener.ora文件的内容。 ... [详细]
  • 本文介绍了在Mac上搭建php环境后无法使用localhost连接mysql的问题,并通过将localhost替换为127.0.0.1或本机IP解决了该问题。文章解释了localhost和127.0.0.1的区别,指出了使用socket方式连接导致连接失败的原因。此外,还提供了相关链接供读者深入了解。 ... [详细]
  • 成功安装Sabayon Linux在thinkpad X60上的经验分享
    本文分享了作者在国庆期间在thinkpad X60上成功安装Sabayon Linux的经验。通过修改CHOST和执行emerge命令,作者顺利完成了安装过程。Sabayon Linux是一个基于Gentoo Linux的发行版,可以将电脑快速转变为一个功能强大的系统。除了作为一个live DVD使用外,Sabayon Linux还可以被安装在硬盘上,方便用户使用。 ... [详细]
  • 树莓派语音控制的配置方法和步骤
    本文介绍了在树莓派上实现语音控制的配置方法和步骤。首先感谢博主Eoman的帮助,文章参考了他的内容。树莓派的配置需要通过sudo raspi-config进行,然后使用Eoman的控制方法,即安装wiringPi库并编写控制引脚的脚本。具体的安装步骤和脚本编写方法在文章中详细介绍。 ... [详细]
  • 本文介绍了Sencha Touch的学习使用心得,主要包括搭建项目框架的过程。作者强调了使用MVC模式的重要性,并提供了一个干净的引用示例。文章还介绍了Index.html页面的作用,以及如何通过链接样式表来改变全局风格。 ... [详细]
  • 本文讨论了在shiro java配置中加入Shiro listener后启动失败的问题。作者引入了一系列jar包,并在web.xml中配置了相关内容,但启动后却无法正常运行。文章提供了具体引入的jar包和web.xml的配置内容,并指出可能的错误原因。该问题可能与jar包版本不兼容、web.xml配置错误等有关。 ... [详细]
author-avatar
阿门路亚_
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有