zoukankan      html  css  js  c++  java
  • 《机器学习》周志华西瓜书学习笔记(十):降维与度量学习

    【机器学习】《机器学习》周志华西瓜书 笔记/习题答案 总目录

    ——————————————————————————————————————————————————————

    降维与度量学习

    这一章的内容大致如下:

    • k近邻学习:什么是 k 近邻学习?k 近邻学习和其他学习方法有什么明显的不同之处?最近邻学习的原理是什么?

    • 低维嵌入:维数灾难是什么?怎么解决维度灾难?MDS 算法的原理是什么?

    • 主成分分析:PCA 算法是解决什么问题的?原理是什么?解是什么?

    • 核化线性降维:KPCA 算法的原理是什么?解决什么问题的?

    • 流形学习:等度量映射是什么?Isomap 算法的原理是什么?局部线性嵌入是什么?LLE 算法的原理是什么?

    • 度量学习:度量学习的原理是什么?解决什么问题的?如何解决的?

    k近邻学习

    在这里插入图片描述
    k 近邻(k-Nearest Neighbor,简称kNN) 学习是一种常用的监督学习方法,其工作机制非常简单:给定测试样本,基于某种距离度量,找出训练集中与其最靠近的 k 个训练样本,然后基于这 k 个 邻居 的信息来进行预测。用中文成语说,就是近朱者赤近墨者黑。

    通常,在 分类 任务中可使用 投票法,即选择这 k 个样本中出现最多的类别标记作为预测结果;在 回归 任务中时使用 平均法,即将这 k 个样本的实值输出标记的平均值作为预测结果;还可基于距离远近进行加权平均或加权投票,距离越近的样本权重越大。

    前面介绍的学习方法 相比,k 近邻学习有一个明显的不同之处: 它似乎没有显式的训练过程!事实上,它是 懒惰学习(lazy learning) 的著名代表,此类学习技术在训练阶段仅仅是把样本保存起来,训练时间开销为零,待收到测试样本后再进行处理;相应的,那些在训练阶段就对样本进行学习处理的方法,称为 急切学习(eager learning)
    在这里插入图片描述
    上图给出了 k 近邻分类器的一个示意图。显然,k 是一个重要参数,当 k 取不同值时,分类结果会有显著不同。另一方面,若采用不同的距离计算方式,则找出的 近邻 可能有显著差别,从而也会导致分类结果有显著不同。

    暂且假设距离计算是恰当的,即能够恰当地找出 k 个近邻,我们来对 最近邻分类器(lNN,即 k = 1) 在二分类问题上的性能做一个简单的讨论。

    给定测试样本 xx,若其最近邻样本为 zz, 则最近邻分类器出错的概率,就是 xxzz 类别标记不同的概率,即
    在这里插入图片描述
    假设样本独立同分布,且对任意 mm 和任意小正数 δdelta,在 xx 附近 δdelta 距离范围内,总能找到一个训练样本;换言之,对任意测试样本,总能在任意近的范围内找到上式中的训练样本 zz


    在这里插入图片描述
    表示贝叶斯最优分类器的结果(《机器学习》周志华西瓜书学习笔记(七):贝叶斯分类器),有
    在这里插入图片描述
    于是我们得到了有点令人惊讶的结论:最近邻分类器虽简单,但它的泛化错误率不超过贝叶斯最优分类器的错误率的两倍!

    低维嵌入

    上一节的结论,是基于一个重要假设:任意测试样本 xx 附近任意小的 δdelta 距离范围内总能找到一个训练样本,即训练样本的来样密度足够大,或称为 密采样(dense sample)。然而,这个假设在现实任务中通常很难满足。为什么这么说呢?

    举个例子,例如 δdelta = 0.001 ,仅考虑单个属性,则仅需 1000 个样本点平均分布在归一化后的属性取值范围内,即可使得任意测试样本在其附近 δdelta 距离范围内总能找到一个训练样本,此时最近邻分类器的错误率不超过贝叶斯最优分类器的错误率的两倍。然而,这仅是属性维数为 1 的情形,若有更多的属性,则情况会发生显著变化。例如假定属性维数为 20,若要求样本满足密来样条件,则至少需 (103)20=1060(10^3)^{20} = 10^{60} 个样本。现实应用中属性维数经常成千上万,要满足 密采样 条件所需的样本数目是无法达到的天文数字。此外,许多学习方法都涉及距离计算,而高维空间会给距离计算带来很大的麻烦,例如当维数很高时甚至连计算内积都不再容易。

    事实上,在高维情形下出现的 数据样本稀疏距离计算困难 等问题,是所有机器学习方法共同面临的严重障碍, 被称为维数灾难(curse of dimensionality)
    在这里插入图片描述
    缓解 维数灾难 的一个重要途径是 降维(dimension reduction), 亦称 维数约简,即通过某种数学变换将原始高维属性空间转变为一个低维 子空间(subspace),在这个子空间中样本密度大幅提高, 距离计算也变得更为容易。为什么能进行降维?

    这是因为在很多时候,人们观测或收集到的数据样本虽是高维的,但与学习任务密切相关的也许仅是某个低维分布,即 高维空间中的一个低维嵌入(embedding)

    下图给出了一个直观的例子。原始高维空间中的样本点,在这个低维嵌入子空间中更容易进行学习
    在这里插入图片描述
    若要求原始空间中样本之间的距离在低维空间中得以保持,即有 多维缩放(Mult iple Dimensional Scaling,简称MDS) 这样一种经典的降维方法,下面做一个简单的介绍:
    在这里插入图片描述

    在这里插入图片描述
    其中 BB 为降维后样本的内积矩阵,如下:
    在这里插入图片描述

    在这里插入图片描述
    令降维后的样本 ZZ 被中心化,即
    在这里插入图片描述
    显然,矩阵 BB 的行与列之和均为零,即
    在这里插入图片描述
    易知
    在这里插入图片描述
    以上面公式的第一个为例,推导:

    解析
    在这里插入图片描述
    南瓜书——https://datawhalechina.github.io/pumpkin-book/

    其中 tr()tr(·) 表示矩阵的 迹(trace)
    在这里插入图片描述

    在这里插入图片描述
    可得
    在这里插入图片描述

    解析
    在这里插入图片描述
    南瓜书——https://datawhalechina.github.io/pumpkin-book/

    由此即可通过降维前后保持不变的距离矩阵 DD 求取内积矩阵 BB

    然后对矩阵 BB特征值分解(eigenvalue decomposition)
    在这里插入图片描述
    其中 A=diag(λ1λ2...λd)A = diag(λ_1,λ_2,...,λ_d) 为特征值构成的对角矩阵,
    在这里插入图片描述
    VV 为特征向量矩阵。假定其中有 dd^* 个非零特征值,它们构成对角矩阵
    在这里插入图片描述在这里插入图片描述
    VV_* 表示相应的特征向量矩阵,则 ZZ 可表达为
    在这里插入图片描述
    在现实应用中为了有效降维,往往仅需降维后的距离与原始空间中的距离尽可能接近,而不必严格相等。此时可取 d<<dd' << d 个最大特征值构成对角矩阵
    在这里插入图片描述
    在这里插入图片描述 表示相应的特征向量短阵,则 ZZ 可表达为
    在这里插入图片描述
    MDS 算法的描述如下:

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    一般来说,欲获得低维子空间,最简单的是对原始高维空间进行线性变换。给定 dd 维空间中的样本
    在这里插入图片描述
    变换之后得到 ddd' ≤ d 维空间中的样本
    在这里插入图片描述
    其中 WRddW∈R^{d * d'} 是变换矩阵,ZRdmZ∈R^{d' * m} 是样本在新空间中的表达。

    变换矩阵 WW 可视为 dd'dd 维基向量,zi=WTxiz_i=W^Tx_i 是第 ii 个样本与这 dd' 个基向量分别做内积而得到的 dd' 维属性向量。换言之,均是原属性向量 xix_i 在新坐标系 {w1w2wd}{w_1,w_2,…,w_{d^{'}}} 中的坐标向量。若 wiw_iwj(ij)w_j(i≠j) 正交,则新坐标系是一个正交坐标系,此时 WW 为正交变换。显然,新空间中的属性是原空间中属性的线性组合

    基于线性变换来进行降维的方法称为 线性降维 方法,它们都符合上式 Z=WTXZ=W^TX 的基本形式,不同之处是对低维子空间的性质有不同的要求,相当于对 WW 施加了不同的约束。

    对降维效果的评估,通常是比较降维前后学习器的性能,若性能有所提高则认为降维起到了作用。若将维数降至二维或三维,则可通过可视化技术来直观地判断降维效果。

    主成分分析

    主成分分析(Principal Component Analysis ,简称PCA) 是最常用的一种降维方法。

    在介绍 PCA 之前,先考虑这样一个问题:对于正交属性空间中的样本点,如何用一个 超平面(直线的高维推广) 对所有样本进行恰当的表达?容易想到,若存在这样的超平面,那么它大概应具有这样的性质:

    • 最近重构性:样本点到这个超平面的距离都足够近
    • 最大可分性:样本点在这个超平面上的投影能尽可能分开

    有趣的是,基于最近重构性和最大可分性,能分别得到主成分分析的两种等价推导。

    先从 最近重构性 来推导。
    在这里插入图片描述
    考虑整个训练集,原样本点 xix_i 与基于投影重构的样本点 xi^hat{x_i} 之间的距离为
    在这里插入图片描述

    解析
    在这里插入图片描述
    南瓜书——https://datawhalechina.github.io/pumpkin-book/

    根据 最近重构性,上式应被最小化,考虑到叫 wjw_j 是标准正交基,协方差矩阵是
    在这里插入图片描述

    在这里插入图片描述
    这就是主成分分析的优化目标。

    最大可分性 出发,能得到主成分分析的另一种解释。样本点均在新空间中超平面上的投影是 WTxiW^Tx_i, 若所有样本点的投影能尽可能分开,则应该使投影后样本点的方差最大化,如下图所示:
    在这里插入图片描述
    投影后样本点的方差是
    在这里插入图片描述
    于是优化目标可写为
    在这里插入图片描述
    使用拉格朗日乘子法可得
    在这里插入图片描述

    解析
    在这里插入图片描述
    在这里插入图片描述
    南瓜书——https://datawhalechina.github.io/pumpkin-book/

    于是,只需对协方差矩阵xxT 进行特征值分解,将求得的特征值排序:
    在这里插入图片描述
    再取前 dd' 个特征值对应的特征向量构成 W=(w1w2...wd)W = (w_1,w_2,...,w_{d'})。这就是 主成分分析的解

    PCA 算法描述如下图所示:
    在这里插入图片描述

    实践中常通过对 X 进行奇异值分解来代替协方差矩阵的特征值分解。

    PCA 也可看作是逐一选取方差最大方向,即先对协方差矩阵在这里插入图片描述做特征值分解,取最大特征值对应的特征向量 w1w_1

    在这里插入图片描述
    再对上式做特征值分解,取最大特征值对应的特征向量 w2w_2;…由 WW 各分量正交及

    在这里插入图片描述
    可知,上述逐一选取方差最大方向的做法与直接选取最大 dd' 个特征值等价。

    降维后低维空间的维数 dd' 通常是由用户事先指定,或通过在 dd' 值不同的低维空间中对 kk 近邻分类器(或其他开销较小的学习器)进行交叉验证来选取较好的 dd' 值。对 PCA,还可从重构的角度设置一个重构阔值,例如 t=95t = 95%, 然后选取使下式成立的最小 dd' 值:
    在这里插入图片描述
    PCA 仅需保留 WW 与样本的均值向量(保存均值向量是为了通过向量减法对新样本同样进行中心化),即可通过简单的向量减法和矩阵 - 向量乘法将新样本投影至低维空间中。显然,低维空间与原始高维空间必有不同,因为对应于最小的 ddd - d' 个特征值的特征向量被舍弃了,这是降维导致的结果。

    但舍弃这部分信息往往是必要的:

    • 一方面,舍弃这部分信息之后能使样本的采样密度增大,这正是降维的重要动机;
    • 另一方面,当数据受到噪声影响时, 最小的特征值所对应的特征向量往往与噪声有关,将它们舍弃能在一定程度上起到去噪的效果。

    核化线性降维

    线性阵维方法假设从高维空间到低维空间的函数映射是 线性 的,然而,在不少现实任务中,可能需要非线性映射才能找到恰当的低维嵌入。来看一个例子,如下图,样本点从三维空间中的矩形区域采样后,以 S 形曲面嵌入到三维空间,若直接使用线性降维方法对三维空间观察到的样本点进行降维,则将丢失原本的低维结构。为了对 原本采样的低维空间降维后的低维空间 加以区别,称前者为 本真(intrinsic)低维空间
    在这里插入图片描述
    非线性降维的一种常用方法,是基于核技巧对线性降维方法进行 核化(kernelized)。下面以 核主成分分析(Kernelized PCA ,简称KPCA) 为例来进行演示:

    假设在高维特征空间中把数据投影到由 WW 确定的超平面上,即 PCA 欲求解
    在这里插入图片描述
    其中 ziz_i 是样本点 xix_i 在高维特征空间中的像。易知
    在这里插入图片描述
    其中
    在这里插入图片描述
    假定 ziz_i 是由原始属性空间中的样本点 xix_i 通过映射 ϕphi 产生,即
    在这里插入图片描述
    ϕphi 能被显式表达出来,则通过它将样本映射至高维特征空间,再在特征空间中实施 PCA 即可。
    在这里插入图片描述
    在这里插入图片描述
    一般情形下,我们不清楚 ϕphi 的具体形式,于是引入核函数
    在这里插入图片描述
    将上面三个公式简化可得
    在这里插入图片描述

    解析
    在这里插入图片描述
    南瓜书——https://datawhalechina.github.io/pumpkin-book/

    其中 KKκκ 对应的核矩阵
    在这里插入图片描述
    显然,从式子可以看出是特征值分解问题,取 KK 最大的 dd' 个特征值对应的特征向量即可。

    对新样本 xx ,其投影后的第 j(j=1,2,...,d)j (j = 1, 2, . . ., d') 维坐标为
    在这里插入图片描述
    其中 αialpha_i 已经过规范化,αijalpha_i^jαialpha_i 的第 jj 个分量。上式显示出,为获得投影后的坐标,KPCA 需对所有样本求和,因此它的计算开销较大。

    流形学习

    流形学习(manifold learning) 是一类借鉴了拓扑流形概念的降维方法。流形 是在局部与欧氏空间同胚的空间,换言之,它在局部具有欧氏空间的性质,能用欧氏距离来进行距离计算。这给降维方法带来了很大的启发:若低维流形嵌入到高维空间中, 则数据样本在高维空间的分布虽然看上去非常复杂,但在局部上仍具有欧氏空间的性质,因此,可以容易地在局部建立阵维映射关系,然后再设法将局部映射关系推广到全局。当维数被降至二维或三维时,能对数据进行可视化展示,因此流形学习也可被用于可视化。

    介绍两种著名的流形学习方法:

    等度量映射

    等度量映射(Isometric Mapping,简称Isomap) 的基本出发点,是认为低维流形嵌入到高维空间之后,直接在高维空间中计算直线距离具有误导性,因为高维空间中的直线距离在低维嵌入流形上是不可达的。
    在这里插入图片描述
    如图 (a) 所示,低维嵌入流形上两点间的距离是 测地线(geodesic)距离:想象一只虫子从一点爬到另一点,如果它不能脱离曲面行走,那么图 (a) 中的红色曲线是距离最短的路径, 即 S 曲面上的测地线,测地线距离是两点之间的本真距离。显然,直接在高维空间中计算直线距离是不恰当的。

    那么,如何计算测地线距离呢?这时可利用 流形在局部上与欧氏空间同胚 这个性质,对每个点基于欧氏距离找出其近邻点,然后就能建立一个近邻连接图,图中近邻点之间存在连接,而非近邻点之间不存在连接, 于是,计算两点之间测地线距离的问题就转变为计算近邻连接图上两点之间的最短路径问题。从图 (b) 可看出,基于近邻距离逼近能获得低维流形上测地线距离很好的近似。

    在近邻连接图上计算两点间的最短路径,可采用著名的 Dijkstra 算法或 Floyd 算法,在得到任意两点的距离之后,就可通过 MDS 方法来获得样本点在低维空间中的坐标。Isomap 算法描述如下:

    在这里插入图片描述
    需注意的是, Isomap 仅是得到了训练样本在低维空间的坐标,对于新样本,如何将其映射到低维空间呢?这个问题的常用解决方案,是将训练样本的高维空间坐标作为输入、低维空间坐标作为输出,训练一个回归学习器来对新样本的低维空间坐标进行预测。这显然仅是一个权宜之计,但目前似乎并没有更好的办法。

    对近邻图的构建通常有两种做法:

    • 一种是指定近邻点个数,例如欧氏距离最近的 k 个点为近邻点,这样得到的近邻图称为 k 近邻图;
    • 另一种是指定距离阈值 E,距离小于 ε 的点被认为是近邻点,这样得到的近邻图称为 ε 近邻图。

    两种方式均有不足:

    • 例如若近邻范围指定得较大,则距离很远的点可能被误认为近邻,这样就出现"短路"问题;
    • 近邻范围指定得较小,则圈中有些区域可能与其他区域不存在连接,这样就出现"断路"问题。

    短路与断路都会给后续的最短路径计算造成误导。

    局部线性嵌入

    与 Isomap 试图保持近邻样本之间的距离不同,局部线性嵌入(Locally Linear Embedding,简称LLE) 试图保持邻域内样本之间的线性关系。
    在这里插入图片描述
    如上图所示,假定样本点 xix_i 的坐标能通过它的邻域样本 xjx_jxix_ixjx_j 的坐标通过线性组合而重构出来,即
    在这里插入图片描述
    LLE 希望上式的关系在低维空间中得以保持。具体操作如下:

    先为每个样本 xix_i 找到其近邻下标集合 QiQ_i, 然后计算出基于 QiQ_i 中的样本点对 xix_i 进行线性重构的系数 wiw_i
    在这里插入图片描述
    其中 xix_ixjx_j 均为己知,令
    在这里插入图片描述
    wijw_{ij} 有闭式解
    在这里插入图片描述

    解析
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    南瓜书——https://datawhalechina.github.io/pumpkin-book/

    LLE 在低维空间中保持 wiw_i 不变,于是 xix_i 对应的低维空间坐标均可通过下式求解:
    在这里插入图片描述

    在这里插入图片描述
    优化目标同形,唯一的区别是第二个式子中需确定的是 wiw_i,而第一个式子中需确定的是 xix_i 对应的低维空间坐标 ziz_i


    在这里插入图片描述
    则有
    在这里插入图片描述
    可把
    在这里插入图片描述
    重写为
    在这里插入图片描述

    解析
    在这里插入图片描述
    南瓜书——https://datawhalechina.github.io/pumpkin-book/

    这个式子可通过特征值分解求解:MM 最小的 dd' 个特征值对应的特征向量组成的矩阵即为 ZTZ^T

    LLE 的算法描述如下图所示:

    在这里插入图片描述
    在这里插入图片描述
    算法第 4 行显示出:对于不在样本 xix_i 邻域区域的样本 xjx_j,无论其如何变化,都对 xix_iziz_i 没有任何影响,这种将变动限制在局部的思想在许多地方都有用。

    度量学习

    在机器学习中,对高维数据进行降维的主要目的是希望找到一个合适的低维空间,在此空间中进行学习能比原始空间性能更好。事实上,每个空间对应了在样本属性上定义的一个距离度量,而寻找合适的空间,实质上就是在寻找一个合适的距离度量。那么,为何不直接尝试"学习"出一个合适的距离度量呢?这就是 度量学习(metric learning) 的基本动机。

    欲对距离度量进行学习,必须有一个便于学习的距离度量表达形式。《机器学习》周志华西瓜书学习笔记(九):聚类 给出了很多种距离度量的表达式,但它们都是"固定的"、没有可调节的参数,因此不能通过对数据样本的学习来加以改善。

    为此,先来做一个推广,推广到一般化。

    对两个 dd 维样本 xix_ixjx_j ,它们之间的平方欧氏距离可写为
    在这里插入图片描述
    其中 distij,kdist_{ij, k} 表示 xix_ixjx_j 在第 kk 维上的距离。若假定不同属性的重要性不同,则可引入属性权重 WW , 得到
    在这里插入图片描述
    其中 wi0,W=diag(w)w_i ≥0, W = diag(w) 是一个对角矩阵,(W)ii=w(W)_{ii} = w

    上式中的 WW 可通过学习确定,但还能再往前走一步:WW 的非对角元素均为零,这意味着坐标轴是正交的,即属性之间无关;但现实问题中往往不是这样,例如考虑西瓜的"重量"和"体积"这两个属性,它们显然是正相关的,其对应的坐标轴不再正交。为此,将式子中的 WW 替换为一个普通的半正定对称矩阵 MM,于是就得到了马氏距离(Mahalanobis distance)
    在这里插入图片描述
    其中 MM 亦称 度量矩阵,而度量学习则是对 MM 进行学习。注意到为了保持距离非负且对称,MM 必须是(半)正定对称矩阵,即必有正交基 PP 使得 MM 能写为 M=PPTM=PP^T。对 MM 进行学习当然要设置一个目标。假定我们是希望提高近邻分类器的性能,则可将 MM 直接嵌入到近邻分类器的评价指标中去,通过优化该性能指标相应地求得M。

    下面以 近邻成分分析(Neighbourhood Component Analysis,简称NCA) 为例进行讨论。

    近邻分类器在进行判别时通常使用多数投票法,邻域中的每个样本投 1 票,邻域外的样本投 0 票。不妨将其替换为概率投票法,对于任意样本的 xjx_j,它对 xix_i 分类结果影响的概率为
    在这里插入图片描述
    当 i = j 时,pijp_{ij} 最大。显然,xjx_jxix_i 的影响随着它们之间距离的增大而减小。若以留一法(LOO)正确率的最大化为目标,则可计算 xix_i 的留一法正确率,即它被自身之外的所有样本正确分类的概率为
    在这里插入图片描述
    其中 ΩiOmega_i 表示与 xix_i 属于相同类别的样本的下标集合。于是,整个样本集上的留一法正确率为
    在这里插入图片描述

    在这里插入图片描述
    带入到
    在这里插入图片描述
    再考虑到 M=PPTM=PP^T ,则 NCA 的优化目标为
    在这里插入图片描述
    求解上式(随机梯度下降法,详见《机器学习实战》学习笔记(五):Logistic 回归)即可得到最大化近邻分类器 LOO 正确率的距离度量矩阵 MM

    实际上,我们不仅能把错误率这样的监督学习目标作为度量学习的优化目标,还能在度量学习中引入领域知识。例如,若己知某些样本相似、某些样本不相似,则可定义 必连(must-link) 约束集合 MM勿连(cannot-link) 约束集合 CC(xi,xj)M(x_i, x_j)∈M 表示 xix_ixjx_j 相似,(xi,xk)C(x_i, x_k)∈C 表示 xix_ixkx_k 不相似。显然,我们希望相似的样本之间距离较小,不相似的样本之间距离较大,于是可通过求解下面这个凸优化问题获得适当的度量矩阵 MM
    在这里插入图片描述
    其中约束
    在这里插入图片描述
    表明 MM 必须是半正定的。上式要求在不相似样本间的距离不小于 1 的前提下,使相似样本间的距离尽可能小。

    不同的度量学习方法针对不同目标获得"好"的半正定对称距离度量矩阵 MM,若 MM 是一个低秩矩阵,则通过对 MM 进行特征值分解,总能找到一组正交基,其正交基数目为矩阵 MM 的秩 rank(M)rank(M),小于原属性数 dd

    于是,度量学习学得的结果可衍生出一个降维矩阵
    在这里插入图片描述
    这个矩阵能用于降维。

  • 相关阅读:
    vlc代码分析(3)——输入模块
    vlc学习计划(4)在EMACS中使用GDB调试
    There Are Free RTSP DirectShow Source Filters with full source code
    HDU 4283 You Are the One 第37届ACM/ICPC 天津赛区网络赛 1006题 (DP)
    HDU 4276 The Ghost Blows Light 第37届ACM/ICPC长春赛区1010题 (树形DP)
    POJ 1459 Power Network 最大流 dinic模板
    HDU 4273 Rescue 第37届ACM/ICPC 长春赛区网络赛1007题(三维凸包+重心+点面距离)
    HDU 4286 Data Handler 第37届ACM/ICPC 天津赛区网络赛1009题 (双向链表模拟)
    POJ 2246 ZOJ 1094 Matrix Chain Multiplication(简单题)
    HDU 4280 Island Transport 第37届ACM/ICPC 天津网络赛1003题 (最大流模板题,高效SAP模板)
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13302686.html
Copyright © 2011-2022 走看看