大数据分析与应用实战:统计机器学习之数据导向编程
上QQ阅读APP看书,第一时间看更新

1.6.2 Python语言面向对象

本节举例实践Python语言的面向对象编程,假设我们想用普通最小二乘法(Ordinary Least Squares, OLS)估计简单线性回归方程,i=1,2,…,n的系数,此模型是在最小化式(1.1)的损失函数(loss function)Lw)的目标下,根据训练样本(training samples,参见图3.1保留法下简单的训练与测试机制)xiyi来估计线性回归系数w=[b0,b1]。

其中,n为样本数,yi为实际值,为预测值。上式其实是残差平方和,是为了Lw)对w微分后,能取得较简单的形式而乘的常数,以方便后续建立梯度陡降法中回归系数的更新法则。

回归系数的具体求解方法可用梯度陡降法(gradient descent),即通过迭代的方式,依照梯度最大的方向-▽wLw)与学习率(learning rate)(或称步距)α(alpha),逐步修正欲求的向量w=[b0,b1],渐次地将随机初始化的回归参数推向最佳解w*

式(1.2)的梯度陡降数学模型是在学习率α趋近于零的条件下,寻找最小化损失函数式(1.1)的参数w改进方向u。利用微积分可证明出u=-▽wLw),因此梯度陡降算法的伪码如下:

· 输入:学习率α(alpha)与迭代次数n

· 初始化回归系数值w

· 依公式w=w-αwLw),更新回归系数值w

· 输出w,直到迭代次数达到n

Python通过面向对象编程实现上述算法时,须先用关键词class定义类别LinearRegressionGD,此处传入小括号的参数object,说明了这个类没有父类(到始祖源头了!)。Python的类别定义中通常会有_ _init_ _()这个特殊方法(前后两下画线包夹),创建对象时Python会自动调用这个方法,这个过程也称为初始化(initialization)(Raschka,2015)。

梯度陡降算法需要学习率alpha与迭代次数n_iter才能运行,因此在对象初始化时就设定这两个属性。接着使用fit()方法根据传入的预测变量X与反应变量y,计算回归系数向量w_,以及每次迭代的损失函数值cost_(即残差平方和)。LinearRegressionGD类别另有两个计算向量点积和预测y值的方法lin_comb()和predict()。

前述的类别初始化特殊方法_ _init_ _()中有一个参数self,它是为了方便我们引用后续创建出来的对象本身。类别定义中所有方法的第一个参数必须是self,无论它是否会用到。我们可以通过处理self,来修改某个对象的性质。

LinearRegressionGD类别定义中,还使用了Python的自定义函数语法,以及for循环控制语句。前者使用关键词def开始定义函数名称,欲传入的位置参数(positional argument)或关键词参数(keyword argument)置于小括号内,位置参数必须在关键词参数之前,首行最后以冒号:结尾。其下各行语句内缩四个空格,或是两次Tab键,最末一行通常是return语句,让结果返回到调用函数的地方,并把程序的控制权一起返回。没有return语句的情况就是程序自己内部运行,没有传回值。for循环控制语句的首行同样以关键词和冒号:开头与结尾,两者的中间定义指标变量i,它在0到self.n_iter-1的范围range(self.n_iter)中循环,首行下方缩排部分是循环内部反复执行的语句。

执行上面类别定义后,即将LinearRegressionGD加载到内存中,接着仿真五十笔预测变量xi与反应变量yi,作为回归模型训练数据。

有了类别定义后,我们实现n_iter=350的模型对象lr(此时lr为空模),传入X与y完成梯度陡降拟合计算后,lr变成实模。从实模lr新增的w_与costs_属性,可得知估计的回归系数与历代损失函数值,最后运用实模进行预测,并可视化模型拟合状况(图1.11)。总结来说,Python语言的模型拟合过程通常如下:

· 载入类别;

· 定义空模规格;

· 传入训练数据拟合实模(估计或学习模型参数);

· 以实模进行预测或转换。

图1.11 梯度陡降算法拟合线性回归结果图

R语言也是这种模型拟合的流程,其中第二步空模定义与第三步的实模拟合可能合并在一起,建议读者弄清楚空模与实模之间的异同及其转换点,剩余的差异就是两种语言或各个模型的不同关键词了。