1 min to read
线性回归
数学原理
在1.个人对机器学习的理解中中提到过,机器学习就是利用数学函数对数据集进行拟合;而数学函数的类型一般都是预先定义好的,求解过程实际上是在求解函数的参数;
线性回归算法是假设输入变量与输出变量之间存在着线性关系,其数学函数形式为y=k*x+b
,特别说明一下,这里的k和x可能是数字,也可能是向量;y一般是一个数字;
任何算法的求解都是从损失函数开始入手的,因为损失函数的最优值是算法求解的目标;线性回归的损失函数一般定义为:
cost = (1/2m) ∑(y^-y)^2
其中 y^ 表示算法的预测值,y表示算法的真实值;求这两个数之差的平方,作为一个样本点的损失,然后各个样本点再求和,再求平均值;至于又乘了1/2是为了后面求导的方便;这个损失函数称为 均方差(MSE mean square error)损失函数
下面说明怎么由损失函数入手,求解k和b的最优值!
关于正则化
正则化是用来防止过拟合的一种手段,具体到线性回归来说,有两种正则化方式,分别是L1正则化和L2正则化; 正则化的具体实现是对损失函数做一定的修改:
L1正则化的损失函数:cost = (1/2m) ∑(y^-y)^2 + ∑|w|
L2正则化的损失函数:cost = (1/2m) ∑(y^-y)^2 + ∑w^2
正则化的数学原理如下:
正则化为什么可以防止过拟合,一般有两点解释:
- 由于正则化可以限制权重W的大小,从某种意义上可以降低模型复杂度,可以具有更好泛化能力。另外,奥卡剃姆刀原理也说明模型复杂度越小越好
- 正则化可以认为是一个惩罚项,只有当每次更新获得更大的收益时,才会选择更新;这样有利于减少噪声的影响。
手写梯度下降求解权重和偏置
# -*- coding:utf-8 -*-
import numpy as np
class my_gradient_decline:
def __init__(self, x, y, init_weight, bias):
self.x = x
self.y = y
self.weight = init_weight
self.bias = bias
# noinspection PyTypeChecker
def update_weight(self, alpha):
pre = (np.dot(self.x, self.weight) + self.bias).reshape(-1, 1)
J = np.sum((pre - self.y) ** 2) / (self.x.shape[0] * 2)
print('J=', J)
# axis=0 是对每一列(每一个维度特征)求和
self.weight -= (alpha * np.sum(((pre - self.y) * self.x), axis=0) / self.x.shape[0]).reshape(-1, 1)
if __name__ == '__main__':
data_x = np.array([[1, 0.99, 1.01], [2, 2, 2.02], [3, 3.01, 2.95], [4, 4.01, 3.98], [5, 5, 4.99]]).reshape(-1, 3)
data_x = np.concatenate((np.ones([5, 1]), data_x), axis=1)
data_y = np.array([2.01, 4.02, 5.99, 7.93, 10.02]).reshape(-1, 1)
init_weight = np.zeros(data_x.shape[1]).reshape(-1, 1)
print('x shape:', data_x.shape, 'y_shape:', data_y.shape, 'weight_shape:', init_weight.shape)
gd = my_gradient_decline(data_x, data_y, init_weight, 0)
for i in range(0, 50000):
gd.update_weight(0.02)
print(gd.weight)
关于正则化的第二种理解:
L1正则化可通过假设权重w的先验分布为拉普拉斯分布,由最大后验概率估计导出。
L2正则化可通过假设权重w的先验分布为高斯分布,由最大后验概率估计导出。
具体推导:https://blog.csdn.net/m0_38045485/article/details/82147817
Comments