Py学习  »  机器学习算法

【Sklearn机器学习】线性回归,你只会调包吗?

蚂蚁学Python • 4 年前 • 663 次点击  

自己动手实现线性回归

我们往往会用类似sklearn的linear_model模块直接调包去使用线性回归处理一些回归问题,但我们绝不能只会调包!

接下来我们就用面向对象的方式,自己实现一个线性回归类,并且在这个过程中体会从数学公式到python代码的美妙。

在这里我将不会讲解线性回归的原理和公式(毕竟这是python为主题的公众号),而是聚焦于”从公式到代码“的过程。所以如果对公式原理以及一些线性回归的相关术语不熟悉,可以去看相关的资料充充电,这并不难,毕竟线性回归是机器学习里最简单直观的算法了

简述线性回归模型

线性回归就是输入一堆数据(假设有m条,每条数据有n个属性,也就是m行n列),结果训练后得到模型参数(也就是线性回归方程中与每个属性相乘的那些值,有n个属性,就有对应的n个参数)的过程。

训练的方法有许多,我大致分两类,一类就是正则方程,也就是直接通过解矩阵方程得到参数。另一类就是梯度下降,它又可以细分为批量梯度下降算法、随机梯度下降算法以及小批量梯度下降算法。梯度下降更加有通用性,因为其它机器学习模型的损失函数都极其复杂,无法获得最值的解析解,所以可以说正则方程法算是线性回归模型的”特色“。

设计自定义的线性回归类

初始化函数:

初始化函数接收参与训练的数据集,并且随机设定模型参数

getNormalEquation函数

正则方程函数

BGD

BGD函数是梯度下降算法的函数

SGD函数

SGD函数是随机梯度下降算法函数,接收学习率这个参数

MBGD函数

MBGD函数是小批量梯度下降算法的函数,接收学习率这个参数

train_BGD函数

用BGD算法训练,接收迭代率和学习率两个参数

train_SGD函数

用SGD算法训练,接收迭代率和学习率两个参数

train_MBGD函数

用MBGD算法训练,接收迭代率和学习率两个参数

Shuffle函数

这个函数主要用于生成与训练数据集大小相同的随机自然数序列。主要用于SGD函数和MBGD函数中,通过随机数序列打乱训练集和标签集,消除训练集顺序对SGD算法和MBGD算法的影响

Cost函数

这个函数就是平均训练的损失函数,计算训练数据集在模型参数下的预测结果与实际值之间的均方误差。它主要用于三个迭代训练函数中,记录每次迭代后的误差

predict函数

这个函数是预测函数,接受一组测试数据,然后结合模型参数对测试数据进行预测

test函数

这个函数和预测函数很相似,都是结合模型参数预测结果,不同的是这个函数接受的是测试数据集,它遍历整个测试数据集,每次都调用predict函数进行预测

自定义线性回归类的结构

import numpy as np

"""
这是一个关于线性回归的模块
核心部分就是LinearRegression这个类
这个类有以下几个方法
构造方法、根据参数计算预测值的方法、计算损失值的方法、生成随机数序列的方法、使用批量梯度下降、随机梯度下降、小批量随机梯度下降更新参数的方法
"
""
class LinearRegress:

   def __init__(self, input_data, real_result, theta):
   def Cost(self):
   def Shuffle(self):
   def BGD(self,alpha):
   def SGD(self,alpha):
   def MBGD(self,alpha,batch_size):
   def train_BGD(self,iter,alpha):
   def train_SGD(self,iter,alpha):
   def train_MBGD(self,iter,batch_size,alpha):
   def predict(self,data):
   def test(self,test_data):

初始化函数的代码实现

初始化函数__init__的参数是训练数据集input_data、训练结果集real_result以及参数theta。在初始化函数内,主要完成训练数据集、结果集以及模型参数的初始化,与此同时还要遍历每组数据,并且要对数据进行拓展,也就是增加一维常数属性1(因为线性回归方程都是z=ax+by+c这种类似形式,c前面的系数是1) 当theta的默认值是None,如果是None,那么就用正态分布随机给模型参数赋值,如若不是,就用theta作为模型参数

import numpy as np


class LinearRegress:

 def __init__(self, input_data, real_result, theta):
  """
  inputData :输入数据  (m条记录,n个属性,m*n)
  realResult :真实数据  (m条记录,1个值,m*1)
  theta :线性回归的参数,也就是这个算法不断更新迭代优化得到的核心数据 (对应n个属性,n*1)
  默认为None  如果是None就用正态分布的数据来初始化参数,如果不是None,就用传进来的theta初始化参数
  "
""

  # 输入数据集的形状
  row, col = np.shape(input_data)
  # 通过输入数据集,建立这个类里面的成员变量Data,先初始化为m个0组成的列表
  self.Data = [0] * row
  # 给m条数据中的每一条数据都添加上一个常数项1,这一步是为了与线性回归模型中的偏置b对应起来
  for (index, data) in enumerate(input_data):
   # 将每一条数据构成的列表后面都追加一个1.0,并且根据序号index将它们存放到成员变量Data相应位置中
   self.Data[index] = list(data).append(1.0)
  # 转化为numpy的格式更加高效
  self.Data = np.array(self.Data)

  # 通过输入的结果数据集,建立这个类中的成员变量Result
  self.Result = real_result

  # 如果参数不为None的时候,利用传入的theta初始化相应参数
  if theta is not None:
   self.Theta = theta
  # 不然就用正态分布的数据来初始化
  else:
   # 此处选取了(n+1*1)的数据,也是为了和偏置匹配
   self.Theta = np.random.normal((col + 1, 1))


推荐我的机器学习实战课程

一个机器学习系列,从模型训练到在线预估,到Linux线上部署,包含大量的工程细节,推荐给大家我自己的机器学习实战课程:


扫码购买

《机器学习 Sklearn二手车价格预估》


课程介绍



购买后加老师微信答疑:

ant_learn_python

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/122608