动手学深度学习 Vol1 | 线性回归实现
在CS229中主要关注的是一些传统机器学习的模型,包括广义线性模型(GLM)包含的Logistic Regression、Softmax Regression,生成模型的高斯判别式、Decision Tree、Support Vector Machine、浅层神经网络;侧重于对于理论的介绍。李沐课程中对于实际操作的代码实现过程给出了详细的介绍,是非常有意思的。其实整个学习过程的框架无论是简单的逻辑回归还是复杂的YOLO之类的代码框架其实都已经给好了,如何高效的利用框架所提供的抽象好的API来实现复杂的功能是值得思考的。
0x00 Environment build(with conda)
环境安装,性能测试与横向对比中给出Pytorch安装的三种方式:1. 直接安装、2. conda环境、3. Docker安装。后面有时间可以借鉴一下思路来使用Docker管理环境而不是Conda。本次还是利用conda来管理环境
ps:关于conda与docker管理环境之间的差异 – 个人看法 如果有更好的回答希望可以发送到 chenxia31@outlook.com 交流! 作为一个计算机小白,在最初接触Python的时候知道一个电脑中会存在不同版本的python,这个需要我们来进行不同环境的隔离,常见的有python的envs、或者conda管理工具。这样不同的python环境可以使用不同的package。 但是docker可以说是一个更高level的工具,实际上他是一个弱化的虚拟机,并不是从硬件层面来虚拟一整套冯诺依曼体系,而是利用部分硬件和软件调度的方式来降低虚拟机所需要的硬件资源而实现虚拟机的操作系统和主机操作系统之间隔离的目的。在这个过程中可以实现某种意义上的硬件方式的环境隔离。 两者可以说是风马牛,但是在管理python环境中却又有着异曲同工之妙,都能起到环境隔离的作用,但是实现的过程是不一样的:
- conda是python的package的管理者,它为不同的python提供不同的package的路径。这也就是conda install的package值需要装一份就可以为所有环境使用(如果版本一致的话)
- docker是操作系统层面的硬件管理者,它为不同的虚拟机提供硬件和软件资源
1 |
|
别人总结的 Pytorch handbook,看上去还不错
0x01 Review of linear regression
线性回归是非常经典的模型,其求解方法并不是只有梯度下降一种,CS229-01–线性模型之前的blog中给出了相关的介绍,这里再重新复述一下和关于自己在其中新的思考
1.1 记号和引言
假设每个sample包含feature(n*1)和label(1*1),也就是$[(x^{(i)},y^{(i)}),i=0:…:m]$,在这种情况下我们希望构建一个model(或者说一种function)来作为feature和label之间的映射关系,这样在一个新的feature到来的时候,可以做出了预测。这个model其实就是实例化的hypothesis,实例化的过程便是optimization确定模型parameters的过程,其中包括loss function与optim method
1.2 模型实现的过程
对于线性回归,所做出的hypothesis自然是线性的,这也是它属于广义线性模型的原因
对于优化过程,第一步是确定损失函数,第二步是利用损失函数来找到对应的$w,b$参数值使得最小
损失函数是用来描述预测值和实际值之间的差别,通常模型越好损失函数需要最小,这里采用的是欧氏距离作为损失函数,具体原因在1.3中解释
之后便是求解这个优化问题的方式,对于线性回归有两种,一种是利用矩阵的normal equation方法得到解析解;二是利用深度学习中常用的梯度下降(gradient descent)的启发式方法来得到近似解(ps:和做时刻表一样)
- normal equation,利用导数为0的极值点得到取值,推导过程略
image-20220911092806762
- gradient descent,利用导数下降的方式来探索的接近极值点
线性模型的梯度比较好求解
1.3 模型解释
机器学习最方便的就是可解释性。首先我们的假设中认为features和labels之间是关于线性分布,但是通常情况下总会有各种各样的因素也就是高斯分布的假设,所以如果有Ground- truth的话,那必然是,主义嗷对于不同
我们可以使用最大似然法(maximum likelihood) 的方式来推导我们想要什么?抛弃传统距离的概率,我们用概率的方式来表示.(我们的目的都是预测值和真实值相接近,可以用距离、也可以用分布概率)
由上我们可以看出预测值的概率值(不是概率分布!!)
我们希望所有的数据集中的概率都尽可能的大,所以
这个时候就可以求导得到等价于1.2中损失函数的式子!
1.4 回顾过程
1.1 给出为什么要这么做、1.2 给出理论推导过程、1.3给出模型的解释。这里一个困惑的点在于loss function是先有还是先可以被解释的。我的个人理解是它先有欧氏距离的方式,后面随着发展才逐渐利用概率方式解释,同时这种解释的范式我们也可以推广给其他模型。
比如在逻辑回归中,并不是给出假设就给出损失函数,而是利用概率方式来推导(!!)得到损失函数,这里常用的方式是MLP和MAE或者其他的方式,在选择合适的优化算法来寻找参数
不同于机器学习目的是得到一个有效的模型,传统的统计分析会给出参数估计的优劣以及检验是否合理,并就得到的参数给出自变量和因变量之间的关系。
0x02 Manual implementation process(eight step)
接下来就是利用代码实现上述功能,这里参考李沐老师的d2l,在最开始软件模块的设计中就已经给出来代码的框架。
2.1 生成数据集/读取数据集
1 |
|
2.2 数据观察与预处理(暂无)
1 |
|
2.3 数据迭代器(Dataloader)
这里采用的小批量(batch)的梯度下降;在梯度下降的过程中最直接的是计算所有数据集的梯度进行更新,这样对于memory的压力比较大,因此可以一个epoch进行划分,划分不同的batch_size,再利用batch进行参数更新。
但是这样的疑问在于batch能代表整个训练集进行更新吗?所以这样子就需要训练很多次,在某种特殊情况下会震荡多次,所有也会有更多的优化算法,来添加噪音或者动量,提升优化算法的健壮性。
1 |
|
2.4 初始化参数
1 |
|
2.5 定义模型(net)
其实这里net的输入参数应该是X和param,因为在后续的模型中肯定会有参数和训练样本的输入,但是计算方式和linreg并不是相似,如果输入参数规定好为w和b,在后续更改会比较麻烦。
1 |
|
2.6 定义损失函数(loss)
损失函数表征的是预测值和真实值之间的差距,因此函数的输入应该为预测值与真值,这样就可以被复用
1 |
|
2.7 定义优化算法(optim)
这里还是使用给好的API实现,同时在优化过程中我们需要设置的除了批量梯度下降的batch-size之外,还需要确定学习率。这个在任何情况下都是需要设置的
1 |
|
2.8 完整的训练过程
1 |
|
0x03 Automatic implementation process (Pytorch)
回顾上述的过程,为了2.8最后的训练过程,我们首先需要生成数据集和读取数据集;之后我们写来一个dataloader来将数据集转换为可迭代(iterable)的对象来方便后续的梯度下降,dataloader中我们需要设置数据集、batch-size、是否可以被打乱;后面定义模型、损失函数和优化算法,模型是需要根据param和x来得到预测值、损失函数需要根据预测值和真实值得到结果、优化算法需要根据学习率、batch size来进行参数更新
1 |
|
0x04 Discussion
在了解整个代码实现过程之后,才能更好的了解到后续的逻辑回归、图像深度学习等代码实现的方式,以及如何学习pytorch的结构