我的博客中参考了大量的文章或者别的作者的博客,有时候疏忽了并未一一标注,本着分享交流知识的目的,如果侵犯您的权利,这并非我的本意,如果您提出来,我会及时改正。
本篇博客主要是为了解决机器学习中的过拟合和规则化问题,内容以线性回归为基础进行阐述,其优化使用的均为向量范数。
主要内容概述如下:
0.从监督学习中的优化问题谈起
1.范数的引入
2.范数的定义及公式
3.L0、L1范数的理解
4.L2范数的理解
5.几个问题的总结(L1、L2正则化目的引入)
6.Lasso回归(L1正则化)
7.Ridge回归(L2正则化)
8.Lasso回归与Ridge回归间的比较

0.从监督学习中的优化问题谈起

监督机器学习问题无非就是“minimizeyour error while regularizing your parameters”,也就是在规则化参数的同时最小化误差最小化误差是为了让我们的模型拟合我们的训练数据,而规则化参数是防止我们的模型过分拟合我们的训练数据。多么简约的哲学啊!因为参数太多,会导致我们的模型复杂度上升,容易过拟合,也就是我们的训练误差会很小。但训练误差小并不是我们的最终目标,我们的目标是希望模型的测试误差小,也就是能准确的预测新的样本。所以,我们需要保证模型“简单”的基础上最小化训练误差,这样得到的参数才具有好的泛化性能(也就是测试误差也小),而模型“简单”就是通过规则函数来实现的。另外,规则项的使用还可以约束我们的模型的特性。这样就可以将人对这个模型的先验知识融入到模型的学习当中,强行地让学习到的模型具有人想要的特性,例如稀疏、低秩、平滑等等。要知道,有时候人的先验是非常重要的。前人的经验会让你少走很多弯路,这就是为什么我们平时学习最好找个大牛带带的原因。一句点拨可以为我们拨开眼前乌云,还我们一片晴空万里,醍醐灌顶。对机器学习也是一样,如果被我们人稍微点拨一下,它肯定能更快的学习相应的任务。只是由于人和机器的交流目前还没有那么直接的方法,目前这个媒介只能由规则项来担当了。

还有几种角度来看待规则化的。规则化符合奥卡姆剃刀(Occam’s razor)原理。这名字好霸气,razor!不过它的思想很平易近人:在所有可能选择的模型中,我们应该选择能够很好地解释已知数据并且十分简单的模型。从贝叶斯估计的角度来看,规则化项对应于模型的先验概率。民间还有个说法就是,规则化是结构风险最小化策略的实现,是在经验风险上加一个正则化项(regularizer)或惩罚项(penalty term)。

其中,第一项L(yi,f(xi;w)) 衡量我们的模型(分类或者回归)对第i个样本的预测值f(xi;w)和真实的标签yi之前的误差。因为我们的模型是要拟合我们的训练样本的嘛,所以我们要求这一项最小,也就是要求我们的模型尽量的拟合我们的训练数据。但正如上面说言,我们不仅要保证训练误差最小,我们更希望我们的模型测试误差小,所以我们需要加上第二项,也就是对参数w的规则化函数Ω(w)去约束我们的模型尽量的简单。

  • 规则化的微积分角度处理
    拉格朗日乘子法及KKT条件
    添加约束条件,然后将有约束类问题转化为无约束类问题。
    通常我们求解的最优化问题可以分为以下三类:
    1.无约束性优化问题:

    其几何含义:

    2.有等式约束的优化问题


    其几何含义:

    3.等式和不等式约束的优化问题


    KTT的几何含义:

    OK,到这里,如果你在机器学习浴血奋战多年,你会发现,哎哟哟,机器学习的大部分带参模型都和这个不但形似,而且神似。是的,其实大部分无非就是变换这两项而已。对于第一项Loss函数,如果是Square loss,那就是最小二乘了;如果是Hinge Loss,那就是著名的SVM了;如果是exp-Loss,那就是牛逼的 Boosting了;如果是log-Loss,那就是Logistic Regression了;还有等等。不同的loss函数,具有不同的拟合特性,这个也得就具体问题具体分析的。但这里,我们先不究loss函数的问题,我们把目光转向“规则项Ω(w)”。

  • 规则项的选择
    规则化函数Ω(w)也有很多种选择,一般是模型复杂度的单调递增函数,模型越复杂,规则化值就越大。比如,规则化项可以是模型参数向量的范数。然而,不同的选择对参数w的约束不同,取得的效果也不同,但我们在论文中常见的都聚集在:零范数、一范数、二范数、迹范数、Frobenius范数和核范数等等。这么多范数,到底它们表达啥意思?具有啥能力?什么时候才能用?什么时候需要用呢?不急不急,我们挑几个常见的娓娓道来。

  • 关于机器学习优化问题的讨论
    不过在此之前,我们先故作高雅的来聊聊优化问题。优化有两大难题,一是:局部最小值,二是:ill-condition病态问题。前者俺就不说了,大家都懂吧,我们要找的是全局最小值,如果局部最小值太多,那我们的优化算法就很容易陷入局部最小而不能自拔,这很明显不是观众愿意看到的剧情。那下面我们来聊聊ill-condition。ill-condition对应的是well-condition。那他们分别代表什么?假设我们有个方程组AX=b,我们需要求解X。如果A或者b稍微的改变,会使得X的解发生很大的改变,那么这个方程组系统就是ill-condition的,反之就是well-condition的。我们具体举个例子吧:

    咱们先看左边的那个。第一行假设是我们的AX=b,第二行我们稍微改变下b,得到的x和没改变前的差别很大,看到吧。第三行我们稍微改变下系数矩阵A,可以看到结果的变化也很大。换句话来说,这个系统的解对系数矩阵A或者b太敏感了。又因为一般我们的系数矩阵A和b是从实验数据里面估计得到的,所以它是存在误差的,如果我们的系统对这个误差是可以容忍的就还好,但系统对这个误差太敏感了,以至于我们的解的误差更大,那这个解就太不靠谱了。所以这个方程组系统就是ill-conditioned病态的,不正常的,不稳定的,有问题的,哈哈。这清楚了吧。右边那个就叫well-condition的系统了。

    还是再啰嗦一下吧,对于一个ill-condition的系统,我的输入稍微改变下,输出就发生很大的改变,这不好啊,这表明我们的系统不能实用啊。你想想看,例如对于一个回归问题y=f(x),我们是用训练样本x去训练模型f,使得y尽量输出我们期待的值,例如0。那假如我们遇到一个样本x’,这个样本和训练样本x差别很小,面对他,系统本应该输出和上面的y差不多的值的,例如0.00001,最后却给我输出了一个0.9999,这很明显不对呀。就好像,你很熟悉的一个人脸上长了个青春痘,你就不认识他了,那你大脑就太差劲了,哈哈。所以如果一个系统是ill-conditioned病态的,我们就会对它的结果产生怀疑。那到底要相信它多少呢?我们得找个标准来衡量吧,因为有些系统的病没那么重,它的结果还是可以相信的,不能一刀切吧。终于回来了,上面的condition number就是拿来衡量ill-condition系统的可信度的。condition number衡量的是输入发生微小变化的时候,输出会发生多大的变化。也就是系统对微小变化的敏感度。condition number值小的就是well-conditioned的,大的就是ill-conditioned的。

    如果方阵A是非奇异的,那么A的conditionnumber定义为:

    也就是矩阵A的norm乘以它的逆的norm。所以具体的值是多少,就要看你选择的norm是什么了。如果方阵A是奇异的,那么A的condition number就是正无穷大了。实际上,每一个可逆方阵都存在一个condition number。但如果要计算它,我们需要先知道这个方阵的norm(范数)和Machine Epsilon(机器的精度)。为什么要范数?范数就相当于衡量一个矩阵的大小,我们知道矩阵是没有大小的,当上面不是要衡量一个矩阵A或者向量b变化的时候,我们的解x变化的大小吗?所以肯定得要有一个东西来度量矩阵和向量的大小吧?对了,他就是范数,表示矩阵大小或者向量长度。OK,经过比较简单的证明,对于AX=b,我们可以得到以下的结论:

    也就是我们的解x的相对变化和A或者b的相对变化是有像上面那样的关系的,其中k(A)的值就相当于倍率,看到了吗?相当于x变化的界。

对condition number来个一句话总结:conditionnumber是一个矩阵(或者它所描述的线性系统)的稳定性或者敏感度的度量,如果一个矩阵的condition number在1附近,那么它就是well-conditioned的,如果远大于1,那么它就是ill-conditioned的,如果一个系统是ill-conditioned的,它的输出结果就不要太相信了。

1. 范数的引入

向量的范数,就是表示这个原有集合的大小
矩阵的范数,就是表示这个变化过程的大小的一个度量

  • 从函数、几何和矩阵的角度理解范数
  • 从距离的角度理解

2.范数的定义及公式


向量与矩阵范数公式

3.L0、L1范数的理解


L0范数是指向量中非0的元素的个数。如果我们用L0范数来规则化一个参数矩阵W的话,就是希望W的大部分元素都是0。 这太直观了,太露骨了吧,换句话说,让参数W是稀疏的。OK,看到了“稀疏”二字,大家都应该从当下风风火火的“压缩感知”和“稀疏编码”中醒悟过来,原来用的漫山遍野的“稀疏”就是通过这玩意来实现的。但你又开始怀疑了,是这样吗?看到的papers世界中,稀疏不是都通过L1范数来实现吗?脑海里是不是到处都是||W||1影子呀!几乎是抬头不见低头见。没错,这就是这节的题目把L0和L1放在一起的原因,因为他们有着某种不寻常的关系。那我们再来看看L1范数是什么?它为什么可以实现稀疏?为什么大家都用L1范数去实现稀疏,而不是L0范数呢?
L1范数是指向量中各个元素绝对值之和,也有个美称叫“稀疏规则算子”(Lasso regularization)。现在我们来分析下这个价值一个亿的问题:为什么L1范数会使权值稀疏?有人可能会这样给你回答“它是L0范数的最优凸近似”。实际上,还存在一个更美的回答:任何的规则化算子,如果他在Wi=0的地方不可微,并且可以分解为一个“求和”的形式,那么这个规则化算子就可以实现稀疏。 这说是这么说,W的L1范数是绝对值,|w|在w=0处是不可微,但这还是不够直观。这里因为我们需要和L2范数进行对比分析。所以关于L1范数的直观理解,请待会看看第二节。
对了,上面还有一个问题:既然L0可以实现稀疏,为什么不用L0,而要用L1呢?个人理解一是因为L0范数很难优化求解(NP难问题),二是L1范数是L0范数的最优凸近似,而且它比L0范数要容易优化求解。所以大家才把目光和万千宠爱转于L1范数。

好,到这里,我们大概知道了L1可以实现稀疏,但我们会想呀,为什么要稀疏?让我们的参数稀疏有什么好处呢?这里扯两点:

1)特征选择(Feature Selection):

大家对稀疏规则化趋之若鹜的一个关键原因在于它能实现特征的自动选择。一般来说,xi的大部分元素(也就是特征)都是和最终的输出yi没有关系或者不提供任何信息的,在最小化目标函数的时候考虑xi这些额外的特征,虽然可以获得更小的训练误差,但在预测新的样本时,这些没用的信息反而会被考虑,从而干扰了对正确yi的预测。稀疏规则化算子的引入就是为了完成特征自动选择的光荣使命,它会学习地去掉这些没有信息的特征,也就是把这些特征对应的权重置为0

2)可解释性(Interpretability):

另一个青睐于稀疏的理由是,模型更容易解释。例如患某种病的概率是y,然后我们收集到的数据x是1000维的,也就是我们需要寻找这1000种因素到底是怎么影响患上这种病的概率的。假设我们这个是个回归模型:y=w1x1+w2x2+…+w1000x1000+b(当然了,为了让y限定在[0,1]的范围,一般还得加个Logistic函数)。通过学习,如果最后学习到的w就只有很少的非零元素,例如只有5个非零的wi,那么我们就有理由相信,这些对应的特征在患病分析上面提供的信息是巨大的,决策性的。也就是说,患不患这种病只和这5个因素有关,那医生就好分析多了。但如果1000个wi都非0,医生面对这1000种因素,累觉不爱。

4.L2范数的理解


其几何意义便是向量在欧式空间的长度。
L2范数越小,可以使得w的每个元素都很小,接近于0,但L1范数不同的是他不会让它等于0而是接近于0.

5.几个问题的总结(L1、L2正则化目的引入)

先讨论几个问题:
1)实现参数的稀疏有什么好处吗?
一个好处是可以简化模型,避免过拟合。因为一个模型中真正重要的参数可能并不多,如果考虑所有的参数起作用,那么可以对训练数据可以预测的很好,但是对测试数据就只能呵呵了。另一个好处是参数变少可以使整个模型获得更好的可解释性。
2)参数值越小代表模型越简单吗?
是的。为什么参数越小,说明模型越简单呢,这是因为越复杂的模型,越是会尝试对所有的样本进行拟合,甚至包括一些异常样本点,这就容易造成在较小的区间里预测值产生较大的波动,这种较大的波动也反映了在这个区间里的导数很大,而只有较大的参数值才能产生较大的导数。因此复杂的模型,其参数值会比较大。

6.Lasso回归(L1正则化)

从统计学的语言描述:Tibshirani(1996)提出了Lasso(The Least Absolute Shrinkage and Selectionator operator)算法。这种算法通过构造一个惩罚函数获得一个精炼的模型;通过最终确定一些指标的系数为零,Lasso算法实现了指标集合精简的目的。
以线性回归为例:

其实就是对所有回归系数w的绝对值进行了大小限定,也就是缩减技术。(λ需要自己设定)
L1正则化之所以可以防止过拟合,是因为L1范数就是各个参数的绝对值相加得到的,参数值大小和模型复杂度是成正比的。因此复杂的模型,其L1范数就大,最终导致损失函数就大,说明这个模型就不够好。
Lasso回归和岭回归最重要的区别是,岭回归中随着惩罚项增加时,所有项都会减小,但是仍然保持非0的状态,然而Lasso回归中,随着惩罚项的增加时,越来越多的参数会直接变为0,正是这个优势使得lasso回归容易用作特征的选择(对应参数非0项),因此lasso回归可以说能很好的保留那些具有重要意义的特征而去掉那些那些意义不大甚至毫无意义的特征(如果是超多维的稀疏矩阵,这难道不是在垃圾中寻找黄金的“掘金术”吗?),而岭回归永远不会认为一个特征是毫无意义的。

其优化过程的理论推导:


  • 几何角度理解
    以二维情况的线性回归为例:
    lasso回归的优化问题等价形式如下:

7.Ridge回归(L2正则化)

“是一种专用于共线性数据分析的有偏估计回归方法,实质上是一种改良的最小二乘估计法,通过放弃最小二乘法的无偏性,以损失部分信息、降低精度为代价获得回归系数更为符合实际、更稳定、更可靠的回归方法,对病态数据的拟合要强于最小二乘法。”

共线性数据说白了就是“自变量之间呈现出了某种线性关系”。线性回归模型中的自变量之间由于存在精确相关关系或高度相关关系从而使模型估计失真或难以估计准确。这时候,如果我们计算两个自变量之间的相关性系数,可以发现他们之间线性相关系数很高 。这在构建多元线性回归模型时,随着自变数目变得非常庞大,其中某些个自变量之间产生共线性是很容易发生的情况。 此时线性方程组的系数矩阵不满秩,普通的最小二乘法会产生过拟合的情况,无法使用正规方程法来进行求解,此时虽可以用L1正则化来剔除部分无关变量实现降维来达到满秩的情况,但是我们本着不抛弃不放弃的原则,希望可以使用某种方法,在不降维的情况下,实现正规方程法的求解,此时 我们便引入了L2正则化来解决的求解。

带有L2正则化的损失函数如下:

L2正则化防止过拟合的数学推导
以上数学推导我没看懂,但是大概知道它的作用是抑制所以特征值的参数,使模型的复杂度降低,泛化能力越强,但对于特征值,如果其凸性越强,说明其越重要,其参数抑制程度越低,反之其参数抑制程度越高,甚至会趋于0(但不达到0,不会降维)

  • 几何角度理解
    以二维线性回归为例,岭回归的等价形式如下:

8.Lasso回归与Ridge回归间的比较

我们主要从几个问题入手来对两种回归进行比较:
Q1:如何从模型空间的角度来说明两种正则化的作用?
首先,为了便于可视化,我们考虑两维的情况,在(w1, w2)平面上可以画出目标函数的等高线,而约束条件则成为平面上半径为C的一个 norm ball 。等高线与 norm ball 首次相交的地方就是最优解:

从上边两幅图中我们可以看出:
如果不加L1和L2正则化的时候,对于线性回归这种目标函数凸函数的话,我们最终的结果就是最里边的紫色的小圈圈等高线上的点。
L1正则化约束为什么可以产生稀疏性:
当我们加入L1正则化的时候,我们先画出 |w1|+|w2|=F的图像,也就是一个菱形,代表这些曲线上的点算出来的1范数 |w1|+|w2|都为F。那我们现在的目标是不仅是原曲线算得值要小(越来越接近中心的紫色圈圈),还要使得这个菱形越小越好(F越小越好,因为L0范数越小,反映出的系数向量的稀疏性越大,而L1范数是L0的最优凸近似,所以L1范数越小越好)。那么还和原来一样的话,过中心紫色圈圈的那个菱形明显很大,因此我们要取到一个恰好的值。

(1) 以同一条原曲线目标等高线来说,现在以最外圈的红色等高线为例,我们看到,对于红色曲线上的每个点都可以做一个菱形,根据上图可知,当这个菱形与某条等高线相切(仅有一个交点)的时候,这个菱形最小,上图相割对比较大的两个菱形对应的1范数更大。
用公λ式说这个时候能使得在相同的

下,由于相切的时候 小,所以能够使添加L1正则项的代价函数:
更小。
(2)有了(1)说明,我们可以看出,最终加入L1范数得到的解,一定是某个菱形和某条原函数等高线的切点。现在有个比较重要的结论来了,我们经过观察可以看到,几乎对于很多原函数等高曲线,和某个菱形相交的时候及其容易相交在坐标轴(比如上图),即棱角上,也就是说最终的结果,解的某些维度极其容易是0。这也就是我们所说的L1更容易得到稀疏解(解向量中0比较多)的原因。

l1 相比于 l2 为什么容易获得稀疏解?

L2正则化约束为什么可以产生平滑性(提高泛化精度)
当加入L2正则化的时候,分析和L1正则化是类似的,也就是说我们仅仅是从菱形变成了圆形而已,同样还是求原曲线和圆形的切点作为最终解。当然与L1范数比,我们这样求的L2范数的从图上来看,不容易交在坐标轴上,但是仍然比较靠近坐标轴。因此这也就是我们老说的,L2范数能让某些解比较小(靠近0)(一定程度上也反映了L2正则化对某些特征参数的抑制程度),但是比较平滑(不等于0)。
综上所述,我们可以看见,加入正则化项,在最小化经验误差的情况下,可以让我们选择解更简单(趋向于0)的解。

Q2:λ变大,菱形和圆形怎么变化?
λ 越大,菱形和圆形越小,求得的模型参数越小。

Q3:为什么 L2 正则化比 L1 正则化应用更加广泛?
因为 L2 正则化的约束边界光滑且可导,便于采用梯度下降法,而L1正则化不可导,只能采用坐标轴下降法或最小角回归法,计算量大。而且,L1 正则化的效果并不会比 L2 正则化好(自己的见解)。

Q4:从凸优化的角度分析
主要是参考了知乎上的回答,上面的讨论非常专业,给理解这个问题帮助很大。
假设原先损失函数是C0,那么在L2和L1正则条件下对参数求导分别是:
L1:

L2:

总结一下:

L1正则化用来降维,来筛选特征变量,是局部归零,使模型结构复杂度降低,使模型更简单;L2正则化用来处理过拟合问题,是全局缩放,使回归模型更平滑,泛化程度更高

推广成Lp正则化形式

Reference:

[机器学习]范数 常用参考汇集
机器学习中正则化项L1和L2的直观理解
机器学习中的范数规则化之(一)L0、L1与L2范数
直观理解正则化
Spark2.0机器学习系列之12: 线性回归及L1、L2正则化区别与稀疏解
Sparsity and Some Basics of L1 Regularization
为什么L1稀疏,L2平滑?
【机器学习】好想彻底搞明白L1/L2正则

机器学习中的范数规则化之L0、L1、L2范数相关推荐

  1. 机器学习基础-23:矩阵理论(L0/L1/L2范数等)

    机器学习基础-23:矩阵理论(L0/L1/L2范数等) 机器学习原理与实践(开源图书)-总目录,建议收藏,告别碎片阅读! 线性代数是数学的一个分支,广泛应用于科学和工程领域.线性代数和矩阵理论是机器学 ...

  2. 浅谈L0,L1,L2范数及其应用

    原文传送门:浅谈L0,L1,L2范数及其应用 浅谈L0,L1,L2范数及其应用 在线性代数,函数分析等数学分支中,范数(Norm)是一个函数,其赋予某个向量空间(或矩阵)中的每个向量以长度或大小.对于 ...

  3. 机器学习算法源码全解析(二)-范数规则化之L0、L1与L2范数

    前言 今天我们聊聊机器学习中出现的非常频繁的问题:过拟合与规则化.我们先简单的来理解下常用的L0.L1.L2和核范数规则化.最后聊下规则化项参数的选择问题.这里因为篇幅比较长,为了不吓到大家,我将这个 ...

  4. 正则化与L0,L1,L2范数简介

    参考:机器学习中的范数规则化之(一)L0.L1与L2范数 1. 常见的范数 1.1 L0 范数 向量中非零元素的个数,即稀疏度,适合稀疏编码,特征选择. 1.2 L1 范数 又叫曼哈顿距离或最小绝对误 ...

  5. L0,L1,L2范数

    http://blog.csdn.net/zouxy09/article/details/24971995

  6. 范数规则化(一):L0、L1与L2范数

    目录 0 范数 1  L0 范数 2  L1 范数 2.1 L1 2.2 L1正则化和特征选择 2.3 拉普拉斯先验与L1正则化 2.3.1 拉普拉斯分布 2.3.2 拉普拉斯先验 3 L2 范数 3 ...

  7. 机器学习算法源码全解析(三)-范数规则化之核范数与规则项参数选择

    前言 参见上一篇博文,我们聊到了L0,L1和L2范数,这篇我们絮叨絮叨下核范数和规则项参数选择.知识有限,以下都是我一些浅显的看法,如果理解存在错误,希望大家不吝指正.谢谢. 机器学习算法源码全解析( ...

  8. 机器学习中的规则化范数(L0, L1, L2, 核范数)

    今天我们聊聊机器学习中出现的非常频繁的问题:过拟合与规则化.我们先简单的来理解下常用的L0.L1.L2和核范数规则化.最后聊下规则化项参数的选择问题.这里因为篇幅比较庞大,为了不吓到大家,我将这个五个 ...

  9. 机器学习中的范数规则化之(一)L0、L1与L2范数

    机器学习中的范数规则化之(一)L0.L1与L2范数 zouxy09@qq.com http://blog.csdn.net/zouxy09 参考资料:<机器学习中常常提到的正则化到底是什么意思? ...

最新文章

  1. 三星android获取root权限,三星G9250(S6 Edge公开版全网通 Android 5.1)获取ROOT权限详解教程...
  2. 台湾游戏企业抢滩大陆 研发成竞争核心
  3. 使用randomaccessfile类将一个文本文件中的内容逆序输出_Java 中比较常用的知识点:I/O 总结...
  4. Thinkphp3.2版本Controller和Action的访问方法
  5. iPad Air 2完全评测:可怕的三核CPU、六核GPU
  6. linux 改变当前目录,Linux下使用Shell脚本改变当前工作路径
  7. python从入门到精通需要多久-Python从入门到精通
  8. ACL2021 Findings | 挖掘label的语义来增强few-shot问题
  9. envi 打开影像报错:‘HISTOGRAM:illegal binsize or max/min‘.The result maybe invalid
  10. MRS,MSR指令详解
  11. android 关掉屏幕旋转,防止在Android中屏幕旋转时解除对话框
  12. PRML 回归的线性模型
  13. 简述linux的系统组成,【简答题】Linux操作系统有哪几个部分组成?请简述每个组成部分的作用。...
  14. 900万!!!!!!!!这也太强了吧!!!我的老天!!!!!!!!!!
  15. 第三周作业-循环与判断语句(网络131黄宇倩)
  16. 蓝桥杯JAVA-32.二维数组(矩阵)实现旋转模板(JAVA实现)
  17. 波动方程的行波解(一)| 一维波动方程的通解和初值问题的达朗贝尔(d' Alembert)公式 | 偏微分方程(九)
  18. android仿微信红包动画,Android仿微信打开红包动画(逐帧动画)
  19. 2356 - 成绩排序
  20. 七种寻址方式(基址加变址寻址方式)

热门文章

  1. SpringMVC中servletFileUpload.parseRequest(request)解析为空获取不到数据问题
  2. python文字竖排的2种实现方法
  3. 单页面响应式模板:黑石
  4. 解决c#,wpf程序带环境安装包体积太大问题
  5. 45度地图遮挡问题解决方案(cocos2d-x)
  6. Selenium 生成HTML的测试报告
  7. POJ 1948 Triangular Pastures (二维01背包)
  8. 数据库之ODPS中sql语句指南
  9. Java高级架构师(一)第05节:TortoiseGit的本地使用
  10. django 模型 使用 DateTimeFields 字段 auto_now_add 属性 实现 插入数据时 自动记录时间...