大叔学ML第四:线性回归正则化
正则:正则是一个汉语词汇,拼音为zhèng zé,基本意思是正其礼仪法则;正规;常规;正宗等。出自《楚辞·离骚》、《插图本中国文学史》、《东京赋》等文献。 —— 百度百科
基本形式
线性回归模型常常会出现过拟合的情况,由于训练集噪音的干扰,训练出来的模型抖动很大,不够平滑,导致泛化能力差,如下所示:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import PolynomialFeatures
def poly4(X, *theta):
return theta[0] + theta[1] * X + theta[2] * X**2 + theta[3] * X**3 + theta[4] * X**4
''' 创建样本数据 '''
X = np.arange(0, 9, 1)
Y = [-10, 1, 10, 19, 10, 10, 46, 49, 50]
''' 用4次多项式拟合 '''
pf = PolynomialFeatures(degree=4)
featrues_matrix = pf.fit_transform(X.reshape(9, 1))
theta = tuple(np.dot(np.dot(np.linalg.pinv(np.dot(featrues_matrix.T, featrues_matrix)), featrues_matrix.T), np.array(Y).T))
Ycalculated = poly4(X, *theta)
plt.scatter(X, Y, marker='x', color='k')
plt.plot(X, Ycalculated, color='r')
plt.show()
运行结果:

上面的代码中,大叔试图用多项式\(\theta_0 + \theta_1x + \theta_2x^2 + \theta_3x^3 + \theta_4x^4\)拟合给出的9个样本(如对以上代码有疑问,可参见大叔学ML第三:多项式回归),用正规方程计算出\(\vec\theta\),并绘图发现:模型产生了过拟合的情况。解决线性回归过拟合的一个方案是给代价函数添加正则化项。代价函数(参见大叔学ML第二:线性回归)形如:
\]
添加正则化后的代价函数形如:
## 梯度下降法中应用正则化项
对(2)式中的$\vec\theta$求偏导:
- $\frac{\partial}{\partial\theta_0}j(\theta_0,\theta_1\dots \theta_n) = \frac{1}{m}\left[\sum_{k=1}^m(\theta_0x_0^{(k)} + \theta_1x_1^{(k)} + \dots+ \theta_nx_n^{(k)} - y^{(k)})x_0^{(k)} + \lambda\theta_0\right]$
- $\frac{\partial}{\partial\theta_1}j(\theta_0,\theta_1\dots \theta_n) = \frac{1}{m}\left[\sum_{k=1}^m(\theta_0x_0^{(k)} + \theta_1x_1^{(k)} + \dots+ \theta_nx_n^{(k)}- y^{(k)})x_1^{(k)} + \lambda\theta_1\right]$
- $\dots$
- $\frac{\partial}{\partial\theta_n}j(\theta_0,\theta_1\dots \theta_n) = \frac{1}{m}\left[\sum_{k=1}^m(\theta_0x_0^{(k)} + \theta_1x_1^{(k)} + \dots+ \theta_nx_n^{(k)}- y^{(k)})x_n^{(k)} + \lambda\theta_n\right]$
有了偏导公式后修改原来的代码(参见[大叔学ML第二:线性回归][4])即可,不再赘述。
## 正规方程中应用正则化项
用向量的形式表示代价函数如下:
$$J(\vec\theta)=\frac{1}{2m}||X\vec\theta - \vec{y}||^2 \tag{3}\]
观察(2)式,添加了正则化项的向量表示形式如下:
\]
变形:
J(\vec\theta)&=\frac{1}{2m}\left[||X\vec\theta - \vec{y}||^2 + ||\vec\theta||^2\right] \\
&=\frac{1}{2m}\left[(X\vec\theta - \vec{y})^T(X\vec\theta - \vec{y}) + \lambda\vec\theta^T\vec\theta \right]\\
&=\frac{1}{2m}\left[(\vec\theta^TX^T - \vec{y}^T)(X\vec\theta - \vec{y}) + \lambda\vec\theta^T\vec\theta\right] \\
&=\frac{1}{2m}\left[(\vec\theta^TX^TX\vec\theta - \vec\theta^TX^T\vec{y}- \vec{y}^TX\vec\theta + \vec{y}^T\vec{y}) + \lambda\vec\theta^T\vec\theta\right]\\
&=\frac{1}{2m}(\vec\theta^TX^TX\vec\theta - 2\vec{y}^TX\vec\theta + \vec{y}^T\vec{y} + \lambda\vec\theta^T\vec\theta)\\
\end{align}\]
对\(\vec\theta\)求导:
\frac{d}{d\vec\theta}J(\vec\theta)&=\frac{1}{m}(X^TX\vec\theta-X^T\vec{y} + \lambda I\vec\theta) \\
\frac{d}{d\vec\theta}J(\vec\theta)&=\frac{1}{m}\left[(X^TX + \lambda I)\vec\theta-X^T\vec{y}\right]
\end{align}\]
令其等于0,得:$$\vec\theta=(X^TX + \lambda I){-1}XT\vec{y}\tag{5}$$
小试牛刀
对本文开头所给出的代码进行修改,加入正则化项看看效果:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import PolynomialFeatures
def poly4(X, *theta):
return theta[0] + theta[1] * X + theta[2] * X**2 + theta[3] * X**3 + theta[4] * X**4
''' 创建样本数据 '''
X = np.arange(0, 9, 1)
Y = [-10, 1, 10, 19, 10, 10, 46, 49, 50]
''' 用4次多项式拟合 '''
pf = PolynomialFeatures(degree=4)
featrues_matrix = pf.fit_transform(X.reshape(9, 1))
ReM = np.eye(5) #正则化矩阵
ReM[0, 0] = 0
theta1 = tuple(np.dot(np.dot(np.linalg.pinv(np.dot(featrues_matrix.T, featrues_matrix) + 0 * ReM), featrues_matrix.T), np.array(Y).T))
Y1 = poly4(X, *theta1)
theta2 = tuple(np.dot(np.dot(np.linalg.pinv(np.dot(featrues_matrix.T, featrues_matrix) + 1 * ReM), featrues_matrix.T), np.array(Y).T))
Y2 = poly4(X, *theta2)
theta3 = tuple(np.dot(np.dot(np.linalg.pinv(np.dot(featrues_matrix.T, featrues_matrix) + 10000 * ReM), featrues_matrix.T), np.array(Y).T))
Y3 = poly4(X, *theta3)
plt.scatter(X, Y, marker='x', color='k')
plt.plot(X, Y1, color='r')
plt.plot(X, Y2, color='y')
plt.plot(X, Y3, color='b')
plt.show()
运行结果:

上图中,红线是没有加正则化项拟合出来的多项式曲线,黄线是加了\(\lambda\)取1的正则化项后拟合出来的曲线,蓝线是加了\(\lambda\)取10000的正则化项拟合出来的曲线。可见,加了正则化项后,模型的抖动变小了,曲线变得更加平滑。
调用类库
sklean中已经为我们写好了加正则化项的线性回归方法,修改上面的代码:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import Ridge
from sklearn.preprocessing import PolynomialFeatures
def poly4(X, *theta):
return theta[0] + theta[1] * X + theta[2] * X**2 + theta[3] * X**3 + theta[4] * X**4
''' 创建样本数据 '''
X = np.arange(0, 9, 1)
Y = [-10, 1, 10, 19, 10, 10, 46, 49, 50]
''' 用4次多项式拟合 '''
pf = PolynomialFeatures(degree=4)
featrues_matrix = pf.fit_transform(X.reshape(9, 1))
ridge_reg = Ridge(alpha=100)
ridge_reg.fit(featrues_matrix, np.array(Y).reshape((9, 1)))
theta = tuple(ridge_reg.intercept_.tolist() + ridge_reg.coef_[0].tolist())
Y1 = poly4(X, *theta)
plt.scatter(X, Y, marker='x', color='k')
plt.plot(X, Y1, color='r')
plt.show()
运行结果:

哇,调库和自己写代码搞出的模型差距居然这么大。看来水很深啊,大叔低估了ML的难度,路漫漫其修远兮......将来如果有机会需要阅读一下这些库的源码。大叔猜测是和样本数量可能有关系,大叔的样本太少,自己瞎上的。园子里高人敬请在评论区指教哦。
扩展
正则化项不仅如本文一种添加方式,本文所用的加\(\lambda||\vec\theta||^2\)的方式被称为“岭回归”,据说是因为给矩阵\(X^TX\)加了一个对角矩阵,此对角矩阵的主元看起来就像一道分水岭,所以叫“岭回归”。代码中用的sklean中的模块名字就是Ridge,也是分水岭的意思。
除了岭回归,还有“Lasso回归”,这个回归算法所用的正则化项是\(\lambda||\vec\theta||\),岭回归的特点是缩小样本属性对应的各项\(\theta\),而Lasso回归的特点是使某些不打紧的属性对应的\(\theta\)为0,即:忽略掉了某些属性。还有一种回归方式叫做“弹性网络”,是一种对岭回归和Lasso回归的综合应用。大叔在以后的日子研究好了还会专门再写一篇博文记录。
通过这几天的研究,大叔发现其实ML中最重要的部分就是线性回归,连高大上的深度学习也是对线性回归的扩展,如果对线性回归有了透彻的了解,定能在ML的路上事半功倍,一往无前。祝大家圣诞快乐!
大叔学ML第四:线性回归正则化的更多相关文章
- 大叔学ML第二:线性回归
目录 基本形式 求解参数\(\vec\theta\) 梯度下降法 正规方程导法 调用函数库 基本形式 线性回归非常直观简洁,是一种常用的回归模型,大叔总结如下: 设有样本\(X\)形如: \[\beg ...
- 大叔学ML第五:逻辑回归
目录 基本形式 代价函数 用梯度下降法求\(\vec\theta\) 扩展 基本形式 逻辑回归是最常用的分类模型,在线性回归基础之上扩展而来,是一种广义线性回归.下面举例说明什么是逻辑回归:假设我们有 ...
- 大叔学ML第三:多项式回归
目录 基本形式 小试牛刀 再试牛刀 调用类库 基本形式 上文中,大叔说道了线性回归,线性回归是个非常直观又简单的模型,但是很多时候,数据的分布并不是线性的,如: 如果我们想用高次多项式拟合上面的数据应 ...
- 大叔学ML第一:梯度下降
目录 原理 实践一:求\(y = x^2 - 4x + 1\)的最小值 实践二:求\(z = x^2 + y^2 + 5\)的最小值 问答时间 原理 梯度下降是一个很常见的通过迭代求解函数极值的方法, ...
- [老老实实学WCF] 第四篇 初探通信--ChannelFactory
老老实实学WCF 第四篇 初探通信--ChannelFactory 通过前几篇的学习,我们简单了解了WCF的服务端-客户端模型,可以建立一个简单的WCF通信程序,并且可以把我们的服务寄宿在IIS中了. ...
- 一步一步学ZedBoard & Zynq(四):基于AXI Lite 总线的从设备IP设计
本帖最后由 xinxincaijq 于 2013-1-9 10:27 编辑 一步一步学ZedBoard & Zynq(四):基于AXI Lite 总线的从设备IP设计 转自博客:http:// ...
- 从零开始学Xamarin.Forms(四) Android 准备步骤(添加第三方Xamarin.Forms.Labs库)
原文:从零开始学Xamarin.Forms(四) Android 准备步骤(添加第三方Xamarin.Forms.Labs库) 1.安装对应dll Update-Package Xama ...
- (素材源代码)猫猫学IOS(四)UI之半小时搞定Tom猫
下载地址:http://download.csdn.net/detail/u013357243/8514915 以下是执行图片展示 制作思路以及代码解析 猫猫学IOS(四)UI之半小时搞定Tom猫这里 ...
- HDU 6467 简单数学题 【递推公式 && O(1)优化乘法】(广东工业大学第十四届程序设计竞赛)
传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6467 简单数学题 Time Limit: 4000/2000 MS (Java/Others) M ...
随机推荐
- CentOS7+CDH5.14.0安装CDH错误排查: HiveServer2 该角色的进程已退出。该角色的预期状态为已启动
错误提示: HiveServer2 该角色的进程已退出.该角色的预期状态为已启动 解决办法:出现此问题应该是内存不足造成的,重启相应的组件即可.比如Hive报错,重启Hive,YARN报错,重启YAR ...
- 开发模型之V模型
1.模型目的: V模型的目的在于改进软件开发的效率和效果. 2.常见理论性描述: V模型从整体上看起来,就是一个V字型的结构,由左右两边组成. 左边的下划线分别代表了需求分析.概要设计.详细设计.编 ...
- JavaSE基础知识(5)—面向对象(5.4面向对象三大特征:封装、继承、多态)
面向对象编程具有三大特征: 封装 继承 多态 一.封装 1.好处 狭义的封装:也就是属性的封装,避免了任意赋值的危险,提高了数据的安全性! ①隐藏一个类中不需要对外提供的实现细节 ②使用者只能通过实现 ...
- IDEA 开发环境中设置Subversion,遇到svn安装路径包含空格无法使用版本控制的解决办法
假如你的svn.exe的安装位置是:C:\Program Files\TortoiseSVN\bin\svn.exe,路径中包含空格. 1.File->Settings->Version ...
- python中的继承和多态
继承 继承的表现方式: class Animal(): pass class Cat(Animal): #animal是cat的父类,也可以说是基类 pass print(Cat.__bases__) ...
- 一键脚本清理DEBIAN系统无用组件 减少系统资源
虽然如今我们选择服务器资源都比较多,以前我们看到很多128MB内存.甚至32MB内存的建站网站,感觉特别羡慕.其实这些也不是难事,相比之下,DEBIAN系统比CENTOS系统占用资源少,然后我们需要进 ...
- 在IDEA下导入Maven项目之后 Dependencies报红线
在IDEA中导入新的Maven项目之后,许多jar包出现波浪线的情况,在网上搜了很多办法都不管,什么直接删掉pom文件中的依赖,保存之后,刷新再ctrl+z 撤回 问题就消失了, 还有的说,你可以直接 ...
- Python unittest使用小结
unittest是Python自带的单元测试框架,其中最核心的四个概念是:test case, test suite, test runner, test fixture. 流程:TestLoader ...
- python 练习4
题目为信用卡消费管理系统: 主程序:main.py #!usr/bin/env python # encoding: utf-8 import conf,sys,time,re,os import j ...
- 磨人的Fragment的转换
磨人的Fragment的转换 本次任务是 程序运行之后将第一个Fragment加载出来 然后点击"SHOW NEXT PAGE"切换到第二个Fragment 当再次点击按钮时下方出 ...