ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

《统计学习方法》读书笔记2021.1.24

2021-01-24 22:31:43  阅读:217  来源: 互联网

标签:2021.1 24 似然 frac 函数 读书笔记 样本 正类 theta


《统计学习方法》读书笔记

文章目录

1. 基于梯度的优化方法

(1)最速梯度下降(局部非全局),计算方向导数:
m i n u , u T u = 1 u T ∇ x f ( x ) = m i n u , u T u = 1 ∣ ∣ u ∣ ∣ 2 ∣ ∣ ∇ x f ( x ) ∣ ∣ 2 c o s θ θ 为 u 与 梯 度 的 夹 角 min_{u,u^Tu=1}u^{T}\nabla_{x}f(x) = min_{u,u^Tu=1}||u||_{2}||\nabla_{x}f(x)||_2cos\theta\\ \theta为u与梯度的夹角 minu,uTu=1​uT∇x​f(x)=minu,uTu=1​∣∣u∣∣2​∣∣∇x​f(x)∣∣2​cosθθ为u与梯度的夹角
线搜索,选择方向导数最小的补偿计算梯度:
x ′ = x − ϵ ∇ x f ( x ) ϵ 为 学 习 率 x'=x - \epsilon\nabla_xf(x) \\ \epsilon为学习率 x′=x−ϵ∇x​f(x)ϵ为学习率
个人总结:学习率的选择有三种:①小常数(程序里作为超参数设置)②计算得到使得方向导数变为零的步长 ③线搜索:该方向上选择几个点计算,然后取代价最小的)

最速下降在每个元素为0或接近0时收敛,通过求解方程来停止迭代
∇ x f ( x ) = 0 \nabla_xf(x)=0 ∇x​f(x)=0
(2)为什么有时不适用欧式范数?因为使用欧式范数的最速下降,下降方向并不一定是梯度最陡、下降最快的方向:
∇ x f ( x ) = ( δ f ( x ) x 0 + δ f ( x ) x 1 + . . . + δ f ( x ) x n ) \nabla_{x}f(x) = (\frac{\delta f(x)}{x_{0}}+\frac{\delta f(x)}{x_{1}}+...+\frac{\delta f(x)}{x_{n}}) ∇x​f(x)=(x0​δf(x)​+x1​δf(x)​+...+xn​δf(x)​)
向量中元素的大小决定了梯度的方向. 并且梯度是变化的,梯度方向为起始点的方向,梯度方向不一定是起始点与终点之间的其他点的方向。(为什么不适用欧式范数,这里并不是很理解,不知是否还有其它的观点?

(3)随机梯度下降: 以损失很小的一部分精确度和增加一定数量的迭代次数为代价,换取了总体的优化效率的提升。增加的迭代次数远远小于样本的数量。最小化每条样本的损失函数,虽然不是每次迭代得到的损失函数都向着全局最优方向, 但是大的整体的方向是向全局最优解的,最终的结果往往是在全局最优解附近,适用于大规模训练样本情况。

批量梯度下降:最小化所有训练样本的损失函数,使得最终求解的是全局的最优解,即求解的参数是使得风险函数最小,但是对于大规模样本问题效率低下。

(4)牛顿法使用Hessian矩阵优化,为二阶最优化算法, 基于二阶泰勒展开来近似x0附近的f(x):
f ( x ) ≈ f ( x 0 ) + ( x − x 0 ) T ∇ x f ( x 0 ) + 1 2 ( x − x 0 ) H ( f ) ( x 0 ) ( x − x 0 ) f(x) \approx f(x^{0})+(x-x^0)^{T}\nabla_{x}f(x^{0})+\frac{1}{2}(x-x^{0})H(f)(x^{0})(x-x^{0}) f(x)≈f(x0)+(x−x0)T∇x​f(x0)+21​(x−x0)H(f)(x0)(x−x0)
通过计算,可以得到这个函数的临界点:(迭代更新似然函数和跳到似然函数附件的最小点可以比梯度下降更快到大临界点
x ∗ = x 0 − H ( f ) ( x 0 ) − 1 ∇ x f ( x 0 ) x^{*}=x^{0}-H(f)(x^{0})^{-1}\nabla_{x}f(x^{0}) x∗=x0−H(f)(x0)−1∇x​f(x0)
当f(x)为正定二次函数时,牛顿法只需通过式(5)解出函数最小点,f(x)不是一个真正二次但能在局部近似为正定二次,牛顿法需多次迭代式(6),

个人总结

​ 1. 收敛性:牛顿法是二阶优化算法,梯度下降是一阶优化算法,所以牛顿法就更快收敛。

  1. 全局性:梯度下降法每次只从你当前所处位置选一个坡度最大的方向走一步,牛顿法在选择方向时,不仅会考虑坡度是否够大,还会考虑你走了一步之后,坡度是否会变得更大。所以,可以说牛顿法比梯度下降法看得更远一点,能更快地走到最底部,牛顿法考虑了全局最优,梯度下降容易陷入局部最优。
  2. 缺点:牛顿法是一种迭代算法,每一步都需要求解目标函数的Hessian矩阵的逆矩阵,计算比较复杂。但引入拟牛顿法可以解决,其本质思想是改善牛顿法每次需要求解复杂的Hessian矩阵的逆矩阵的缺陷,它使用正定矩阵来近似Hessian矩阵的逆,从而简化了运算的复杂度。拟牛顿法不需要二阶导数的信息,所以有时比牛顿法更为有效)

维基百科的解释:几何上说,牛顿法就是用一个二次曲面去拟合你当前所处位置的局部曲面,而梯度下降法是用一个平面去拟合当前的局部曲面,通常情况下,二次曲面的拟合会比平面更好,所以牛顿法选择的下降路径会更符合真实的最优下降路径。)
在这里插入图片描述

2. KKT条件:

使用一组简单的性质来描述约束优化问题的最优点

(1)广义Lagrangian的梯度为零

(2)关于x和KKT乘子(λ、α)的约束都满足

(3) 不等式约束显示的“互补松弛性”:
在这里插入图片描述

广义Lagrangian 可以如下定义:

在这里插入图片描述

当约束满足时,
在这里插入图片描述

其中f(x)是原目标函数,hj(x)是第j个等式约束条件,λj是对应的约束系数,gk是不等式约束,uk是对应的约束系数。

在这里插入图片描述

(注: 若f(x)为凸函数,g(x)为凸函数,h(x)为线性函数,则该问题称为**凸优化。**注意这里不等式约束g(x)<=0则要求g(x)为凸函数,若g(x)>=0则要求g(x)为凹函数。)

对应现实问题中的三种情况:

1.无约束条件 :如果一个函数f是凸函数,那么可以直接通过f(x)的梯度等于0来求得全局极小值点。

  1. 等式约束 : 如: 目标函数f(x) = x1 + x2,
    在这里插入图片描述,求解极小值点。
  2. 不等式约束

在这里插入图片描述

(1)是对拉格朗日函数取极值时候带来的一个必要条件,(2)是拉格朗日系数约束(同等式情况),(3)是不等式约束情况,(4)是互补松弛条件,(5)、(6)是原约束条件

个人总结

  1. 对任意问题,KKT为求解最优化的必要条件,KKT点是驻点,是可能的极值点,不一定是极小值点;而当问题为凸优化问题时,KKT为求解全局极小的充分必要条件。

  2. 对非凸优化问题,还需加入正定条件才能变为充分条件:
    在这里插入图片描述

  3. 我记得支持向量机SVM推导时,求解最大化几何间隔,将其转换为最小化1/2 ||w|| ^2,由于目标函数是二次的,约束条件是线性的,因此是求解凸二次最优化问题,满足KKT条件下,引入拉格朗日函数,转为对偶问题,求解w、b的极小,拉格朗日乘子a的极大。最终求得超平面。

3. 线性最小二乘法(Moore-Penrose 伪逆求解)

求解x:
f ( x ) = 1 2 ∣ ∣ A x − b ∣ ∣ 2 2 f(x) = \frac{1}{2}||Ax-b||_{2}^2 f(x)=21​∣∣Ax−b∣∣22​
计算梯度:
∇ x f ( x ) = A T ( A x − b ) = A T A x − A T b \nabla_{x}f(x) = A^{T}(Ax-b)=A^{T}Ax-A^Tb ∇x​f(x)=AT(Ax−b)=ATAx−ATb
伪代码:
将 步 长 ( ϵ ) 和 容 差 ( δ ) 设 为 小 的 正 数 w h i l e : ∣ ∣ A T A x − A T b ∣ ∣ 2 > δ d o : x = x 0 − ϵ ( A T A x − A T b ) e n d w h i l e 将步长(\epsilon)和容差(\delta)设为小的正数\\ while : ||A^{T}Ax-A^Tb||_{2} > \delta \\ do : x = x_{0} - \epsilon(A^{T}Ax-A^Tb) end while 将步长(ϵ)和容差(δ)设为小的正数while:∣∣ATAx−ATb∣∣2​>δdo:x=x0​−ϵ(ATAx−ATb)endwhile
x^⊤*x 1 的约束,引入 Lagrangian:
L ( x , λ ) = f ( x ) + λ ( x T x − 1 ) L(x,\lambda) = f(x)+\lambda(x^Tx-1) L(x,λ)=f(x)+λ(xTx−1)
变成求解以下问题:
m i n x m a x λ , λ > = 0 L ( x , λ ) min_{x}max_{\lambda,\lambda>=0}L(x,\lambda) minx​maxλ,λ>=0​L(x,λ)
引入Moore-Penrose 伪逆, x = **A^{+}**b找到约束最小二乘问题的最小范数解

关于x的微分:
A T A x − A T b + 2 λ x = 0 A^{T}Ax-A^Tb+2\lambda x=0 ATAx−ATb+2λx=0
得到解:(λ 的选择必须使结果服从约束)
x = ( A T A + 2 λ I ) − 1 A T b x = (A^{T}A + 2\lambda I)^{-1}A^{T}b x=(ATA+2λI)−1ATb
(和极限学习机隐含层权值求逆一毛一样。。)

4. 机器学习任务总结

  1. 分类:在这类任务中,计算机程序需要指定某些输入属于 k 类中的哪一类。
  2. 输入缺失分类: 当输入向量的每个度量不被保证的时候,分类问题将会变得更有挑战性。为了解决分类任务,学习算法只需要定义一个从输入向量映射到输出类别的函数。当一些输入可能丢失时,学习算法必须学习一组函数,而不是单个分类函数。每个函数对应着分类具有不同缺失输入子集的 x
  3. 回归: 计算机程序需要对给定输入预测数值。(连续)
  4. 转录: 观测到一些相对非结构化表示的数据,并转录信息为离散的文本形式。
  5. 机器翻译: 输入是一种语言的符号序列,输出是另一种语言的符号序列。
  6. 结构化输出: 结构化输出任务的输出是向量或者其他包含多个值的数据结构,并且构成输出的这些不同元素间具有重要关系。如语法分析——映射自然语言句子到语法结构树,并标记树的节点为动词、名词、副词等等。
  7. 异常检测: 根据一组样本或对象中筛选,并标记不正常或非典型的个体。(信用卡欺诈检测)
  8. 合成和采样:生成一些与训练集相似的新样本,(类似对抗神经网络?)
  9. 缺失值填补: 给定一个新样本x属于R,x中元素xi缺失,算法填补它。
  10. 去噪:干净样本x通过位置损坏后得到损坏样本xi,算法通过损坏样本预测干净样本或者其概率分布?(自编码类似?)
  11. 密度估计和概率质量函数估计: 在密度估计问题中,机器学习算法学习函数pmodel : Rn R,其中 pmodel(x) 可以解释成样本采样空间的概率密度函数(如果 x 是连续的)或者概率质量函数(如果 x 是离散的)。

5. 精确率、准确率、查准率(召回率)、ROC曲线、AUC值

(1)精确率:正类预测为正类的样本占所有预测为正类的样本的比例
精 确 率 = 正 类 预 测 为 正 类 的 正 类 预 测 为 正 类 的 + 负 类 预 测 为 正 类 的 = T P T P + F P 精确率=\frac{正类预测为正类的}{正类预测为正类的+负类预测为正类的}=\frac{TP}{TP+FP} 精确率=正类预测为正类的+负类预测为正类的正类预测为正类的​=TP+FPTP​

(2)准确率:所有预测对了的占所有预测样本的比例
准 确 率 = 正 类 预 测 为 正 类 的 + 负 类 预 测 为 负 类 的 预 测 的 所 有 样 本 = T P + T N T P + F N + F P + T N 准确率=\frac{正类预测为正类的+负类预测为负类的}{预测的所有样本} = \frac{TP+TN}{TP+FN+FP+TN} 准确率=预测的所有样本正类预测为正类的+负类预测为负类的​=TP+FN+FP+TNTP+TN​

(3)召回率: (针对训练样本而言)正类预测为正类的样本占训练样本中所有正类样本的比例
召 回 率 = 正 类 预 测 为 正 类 的 正 类 预 测 为 正 类 的 + 正 类 预 测 为 负 类 的 = T P T P + F N 召回率=\frac{正类预测为正类的}{正类预测为正类的+正类预测为负类的}=\frac{TP}{TP+FN} 召回率=正类预测为正类的+正类预测为负类的正类预测为正类的​=TP+FNTP​

(4)ROC曲线:反映敏感性和特异性连续变量的综合指标,ROC曲线上每个点反映着对同一信号刺激的感受性。
在这里插入图片描述

横坐标为:伪正率,FPR = FP / (FP+TN), 负类样本预测为正类的占所有负类样本的比例

纵坐标为: 召回率, TPR,正类预测为正类的样本占训练样本中所有正类样本的比例

ROC真正的理想情况,TPR应接近1,FPR接近0,即图中的(0,1)点。ROC曲线越靠拢(0,1)点,越偏离45度对角线越好

(5) AUC: (Area Under Curve) 被定义为ROC曲线下的面积,显然这个面积的数值不会大于1。又由于ROC曲线一般都处于y=x这条直线的上方,所以AUC的取值范围一般在0.5和1之间。使用AUC值作为评价标准是因为很多时候ROC曲线并不能清晰的说明哪个分类器的效果更好,而作为一个数值,对应AUC更大的分类器效果更好。一句话来说,AUC值越大的分类器,正确率越高。

6. 防止过拟合的5种方法

  1. earlystopping

  2. 增加数据集、引入噪声

  3. 正则化L1, L2, 加入正则化则相当于引入约束条件,也相当于引入参数的先验知识,L1引入拉普拉斯分布,导数为x, -x, 存在突变的极值点,权值更易等于0, 因此容易产生稀疏矩阵,相对于L2更具有稀疏性,因此具有特征选择的作用,一定程度上防止过拟合; L2引入高斯分布,可以做到加速训练,防止过拟合。(L1: |w1| + |w2|+…+|wn| , L2 = \sqrt{|w1|^{2} + |w2|^{2}+ … +|wn|^{2}}

  4. Dropout:

1) 具有取平均的作用,随机丢弃一部分神经元,使得每个epoch的网络结构不同,相当于对多个epoch下的网络结构取平均。

2)减少神经元之间复杂的共适关系,随机去掉一部分神经元,使得权值的更新不再依赖于具有固定关系的隐含层节点共同作用,丢掉特定的线索片段,从众多线索中学习一些共同特征

  1. Batch Normalization: 批归一化,在某网络层后加入批归一化层,使得该层输出的数据标准化,一定程度上避免梯度消失和爆炸。

7. 熵、相对熵(KL散度)、交叉熵

(1)熵: 指事件包含信息量的多少
期 望 : S ( x ) = − Σ i P ( x i ) l o g P b ( x i ) = − [ P ( A ) l o g ( P ( A ) ) + P ( B ) l o g ( P ( B ) ) + . . + p ( N ) l o g ( P ( N ) ) ] 期望:S(x) = -\Sigma_{i}P(x_{i})logP_{b}(x_{i}) \\ =-[P(A)log(P(A))+P(B)log(P(B))+..+p(N)log(P(N))] 期望:S(x)=−Σi​P(xi​)logPb​(xi​)=−[P(A)log(P(A))+P(B)log(P(B))+..+p(N)log(P(N))]
信息量:-log(P(A))

(2)KL散度: 从事件A的角度看,事件B有多大的不同
D K L ( P ∣ ∣ Q ) = Σ i n P ( x i ) l o g ( P ( x i ) Q ( x i ) ) D_{KL}(P||Q) = \Sigma_{i}^{n}P(x_{i})log(\frac{P(x_{i})}{Q(x_{i})}) DKL​(P∣∣Q)=Σin​P(xi​)log(Q(xi​)P(xi​)​)
其中,P(xi)往往表示真实分布,如[1, 0, 0], Q(xi)往往表示概率分布,如[0.7, 0.2, 0.4]

Dkl越小,P分布与Q分布越接近。

(3)交叉熵:从事件A的角度来看,如何描述事件B
H ( p , q ) = − Σ i n P ( x i ) l o g ( P ( x i ) Q ( x i ) ) H(p,q)= -\Sigma_{i}^{n}P(x_{i})log(\frac{P(x_{i})}{Q(x_{i})}) H(p,q)=−Σin​P(xi​)log(Q(xi​)P(xi​)​)

在这里插入图片描述

loss猫 = -0*log(0.3) - (1-0)log(1-0.3) = -log0.7

loss青蛙 = -1log(0.6) - (1-1)log(1-0.6) = -1log0.6

loss老鼠 = -0log(0.1) - (1-0)log(1-0.1) = -1log0.1

loss = loss1 + loss2 + loss3

8. 最大似然估计

(1) 概念:已知某个随机样本满足某种概率分布,通过若干次试验进行参数估计,观察其结果,利用结果推出参数的大概值。最大似然估计是建立在这样的思想上:已知某个参数能使这个样本出现的概率最大,我们当然不会再去选择其他小概率的样本,所以干脆就把这个参数作为估计的真实值。

考虑一组含有 m 个样本的数据集 X = {x (1) , . . . , x(m)},独立地由未知的真实数据生成分布 pdata(x) 生成.

pmodel(x; θ) 是一族由 θ 确定在相同空间上的概率分布。换言之,pmodel(x; θ)将任意输入 x 映射到实数来估计真实概率 pdata(x)。

θ 的最大似然估计被定义为:
θ M L = a r g m a x θ P m o d e l ( X ; θ ) = a r g m a x θ ∏ i = 1 m P m o d e l ( X i ; θ ) \theta_{ML}=argmax_{\theta}P_{model}(X;\theta)\\ =argmax_{\theta}\prod_{i=1}^{m}P_{model}(X^{i};\theta) θML​=argmaxθ​Pmodel​(X;θ)=argmaxθ​i=1∏m​Pmodel​(Xi;θ)
多个概率的乘积会因很多原因不便于计算。例如,计算中很可能会出现数值下溢。为了得到一个便于计算的等价优化问题,我们观察到似然对数不会改变其arg max 但是将乘积转化成了便于计算的求和形式:
θ M L = a r g m a x θ Σ i = 1 m P m o d e l ( X i ; θ ) \theta_{ML}=argmax_{\theta}\Sigma_{i=1}^{m}P_{model}(X^{i};\theta) θML​=argmaxθ​Σi=1m​Pmodel​(Xi;θ)
最小化 KL 散度其实就是在最小化分布之间的交叉熵,任何一个由负对数似然组成的损失都是定义在训练集上的经验分布和定义在模型上的概率分布之间的交叉熵。例如,均方误差是经验分布和高斯模型之间的交叉熵。

条件最大似然估计:
θ M L = a r g m a x θ P ( Y ∣ X ; θ ) \theta_{ML}=argmax_{\theta}P(Y|X;\theta) θML​=argmaxθ​P(Y∣X;θ)

(2)步骤:

1)写出似然函数;

2)对似然函数取对数,并整理;

3)求导数,令导数为0,得到似然方程;

4)解似然方程,得到的参数即为所求。

(3) 优势:

  1. 它被证明当样本数目 m → ∞ 时,就收敛率而言是最好的渐近估计。

  2. 一致性,在合适的条件下,训练样本数目趋向于无穷大时,参数的最大似然估计会收敛到参数的真实值。

    ​ 条件:1) 真实分布 pdata 必须在模型族 pmodel(·; θ) 中。否则,没有估计可以还原 pdata。

    ​ 2) 真实分布 pdata 必须刚好对应一个 θ 值。否则,最大似然估计恢复出真实分布pdata 后,也不能决定数据生成过程使用哪个 θ

个人总结

  1. 最大似然等价于最小化交叉熵
  2. 要求θ,只需要使θ的似然函数L(θ)极大化,然后极大值对应的θ就是我们的估计。这里就回到了求最值的问题了。怎么求一个连续可微的函数的最值?当然是求导,然后让导数为0,那么解这个方程得到的θ就是了。
  3. 那如果θ是包含多个参数的向量那怎么处理啊?当然是求L(θ)对所有参数的偏导数,也就是梯度了,那么n个未知的参数,就有n个方程,方程组的解就是似然函数的极值点了,当然就得到这n个参数了
  4. 最大似然估计可以把它看作是一个反推。多数情况下我们是根据已知条件来推算结果,而最大似然估计是已经知道了结果,然后寻求使该结果出现的可能性最大的条件,以此作为估计值。)

9. 贝叶斯统计

贝叶斯估计用概率反应知识状态的确定程度。

最大似然估计采用点估计*\theta的方法预测,贝叶斯则考虑\theta的全分布。贝叶斯与最大似然估计的最大区别是采用了先验概率P(A)分布造成的,先验能够影响概率质量密度朝参数空间中偏好先验的区域偏移,实践中,先验通常表现为偏好更简单或更光滑的模型。
P ( A ∣ B ) = P ( A , B ) P ( B ) = P ( A ) P ( B ∣ A ) P ( B ) 后 验 概 率 ( 条 件 概 率 ) = 联 合 概 率 分 布 先 验 概 率 ( 边 缘 概 率 ) = 先 验 概 率 ∗ 标 准 相 似 度 P(A|B) = \frac{P(A,B)}{P(B)} = \frac{P(A)P(B|A)}{P(B)}\\ 后验概率(条件概率) = \frac{联合概率分布}{先验概率(边缘概率)}=先验概率*标准相似度 P(A∣B)=P(B)P(A,B)​=P(B)P(A)P(B∣A)​后验概率(条件概率)=先验概率(边缘概率)联合概率分布​=先验概率∗标准相似度
现在假设我们有一组数据样本 {*x (1), . . . , x
(m)}。通过贝叶斯规则结合数据似然p(x (1), . . . , x(m) | θ) 和先验,我们可以恢复数据对我们关于 θ 信念的影响:
p ( θ ∣ x 1 , . . . , x m ) = p ( x 1 , . . . , x m ∣ θ ) p ( θ ) p ( x 1 , . . . , x m ) p(\theta|x^1,...,x^m)=\frac{p(x^1,...,x^m|\theta)p(\theta)}{p(x^1,...,x^m)} p(θ∣x1,...,xm)=p(x1,...,xm)p(x1,...,xm∣θ)p(θ)​
在贝叶斯估计常用的情景下,先验开始是相对均匀的分布或高熵的高斯分布,观测数据通常会使后验的熵下降,并集中在参数的几个可能性很高的值。

在观测到 m 个样本后,下一个数据样本 x^(m+1) 的预测分布如下:
p ( x m + 1 ∣ x 1 , . . . , x m ) = ∫ p ( x m + 1 ∣ θ ) p ( θ ∣ ( x 1 , . . . , x m ) d θ p(x^{m+1}|x^1,...,x^m)=\int{p(x^{m+1}|\theta)p(\theta|(x^1,...,x^m)}d\theta p(xm+1∣x1,...,xm)=∫p(xm+1∣θ)p(θ∣(x1,...,xm)dθ
这里,每个具有正概率密度的 θ 的值有助于下一个样本的预测,其中贡献由后验密度本身加权。在观测到数据集 {*x (1), . . . , x*(m)} 之后,如果我们仍然非常不确定 θ 的值,那么这个不确定性会直接包含在我们所做的任何预测中。

(朴素贝叶斯的缺点:属性独立性的条件同时也是朴素贝叶斯分类器的不足之处, 现实中很多数据难以满足独立同分布)

标签:2021.1,24,似然,frac,函数,读书笔记,样本,正类,theta
来源: https://blog.csdn.net/weixin_45776027/article/details/113098480

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有