机器学习笔记——2 简单线性模型及局部加权线性模型的基本原理和python实现(参数估计的两个基本角度:几何直观和概率直观。函数最值问题的两大基本算法:梯度方法与迭代方法)

简单线性模型及局部加权线性模型的基本原理和python实现(参数估计的两个基本角度:几何直观和概率直观。函数最值问题的两大基本算法:梯度方法与迭代方法)


线性模型是什么?

线性模型是监督学习的各类学习算法最基本的一类学习算法,所谓线性值得是模型的输出与数据的各个属性值之间的关系是线性的。线性是我们最擅长处理的(无论是工程实现还是数学分析),同时利用线性进行拓展,我们还可以处理很多非线性的情况。
简单线性模型假设我们的样本空间 χ \chi χ与参数 θ \theta θ之间的关系是线性的,如下所示:
y ^ = θ 0 x 0 + θ 1 x 1 + . . . + θ n x n \hat{y} = \theta_0x_0+\theta_1x_1+...+\theta_nx_n y^=θ0x0+θ1x1+...+θnxn记之为 y ^ = h θ ( x ) = θ T x \hat{y} = h_{\theta}(x) = \theta^Tx y^=hθ(x)=θTx,简单线性模型是后面我们将学习的广义线性模型的基础。

求解参数 θ \theta θ的两种角度:几何直观和概率直观

估计上述参数 θ \theta θ的方式,主要有两种,一种是从几何直观,一种是从概率直观。它们分别是:

  • 最小二乘方法 (Ordinary Squart Least, OSL)
  • 极大似然估计 (Maximum Liklihood Estimate, MLE)
  1. 最小二乘方法从几何的角度出发,认为拟合值与原值之间的平方误差和应该最小化,因此我们定义了一个损失函数(cost function) 如下:
    J ( θ ) = 1 2 ∑ i = 1 m [ h θ ( x ( i ) ) − y ( i ) ] 2 J(\theta) = \frac{1}{2}\sum_{i=1}^{m}[h_{\theta}(x^{(i)})-y^{(i)}]^2 J(θ)=21i=1m[hθ(x(i))y(i)]2 参数 θ \theta θ需要使得损失函数最小化

  2. 极大似然估计是从概率的角度出发,认为样本数据既然发生了,其背后的概率应该最大化。因此我们首先对模型进行概率解释,即
    y = θ 0 x 0 + θ 1 x 1 + . . . + θ n x n + ϵ y = \theta_0x_0+\theta_1x_1+...+\theta_nx_n + \epsilon y=θ0x0+θ1x1+...+θnxn+ϵ然后我们做一个比较合理的假设,即误差的零均值同方差正态假设,因此有
    ϵ ∼ N ( 0 , σ 2 ) \epsilon \sim{N(0,\sigma^2)} ϵN(0,σ2)所以标签值 y y y的分布为 y ∼ N ( θ T x , σ 2 ) y\sim{N(\theta^Tx,\sigma^2)} yN(θTx,σ2)因此整个样本数据的概率似然函数为
    L ( θ ) = ∑ i = 1 m 1 2 π σ e x p ( − ( y ( i ) − h θ ( x ( i ) ) ) 2 σ 2 ) L(\theta) = \sum_{i=1}^{m}\frac{1}{\sqrt{2\pi}\sigma}exp(-\frac{(y^{(i)}-h_{\theta}(x^{(i)}))^2}{\sigma^2}) L(θ)=i=1m2π σ1exp(σ2(y(i)hθ(x(i)))2)那么参数 θ \theta θ需要使得似然函数最大化。

以上两种参数估计的方法最终都归结为某个函数形式的最值问题,下面我们讨论如何求解非线性函数的最值。

函数最值问题的两大数值算法

  • 梯度方法
    • 批量梯度下降(Batch Gradient Descent, BGD)
    • 随机梯度下降(Stochastic Gradient Descent, SGD)
  • 迭代方法
    • 一般迭代法
    • 牛顿迭代法

梯度方法

梯度是微积分中概念。在映射 f : R n → R f:R^n \rightarrow R f:RnR中,它是一个 n n n维向量,其方向是该点处切平面增长最快的方向,在微分中,因为我们用切平面的增量近似函数的增量,所以梯度的方向也是该点函数增长最快的方向。从而利用自变量空间中关于 f f f的梯度场,就可以保证达到某个极值,在凸性的保证,还可以保证其达到最值。

迭代方法

我们详细介绍迭代方法。首先我们知道最值点的必要条件是稳定点,即导数为0。因此我们实际上需要一个寻找函数零点的方法。一般来讲,迭代方法可以分为两类:

  • 直接法(连续函数的中值定理)
  • 间接法

直接法有我们熟悉的二分法等,我们略去不谈。这里要重点介绍间接法。我们首先谈迭代法的一般理论,然后再谈广泛使用的牛顿迭代法及其多元形式。
在一维情况下,由 f ( x ) = 0 f(x)=0 f(x)=0可以尝试得到:
x = φ ( x ) x=\varphi(x) x=φ(x) ∣ φ ′ ( x ) ∣ < 1 \mid \varphi^{'}(x)\mid < 1 φ(x)<1在区间 [ a , b ] [a,b] [a,b]成立时,则可以证明在由迭代式 x n = φ ( x n − 1 ) x_{n}=\varphi(x_{n-1}) xn=φ(xn1)产生的迭代序列 { x n } \{x_{n}\} {xn}收敛于 x ∗ x^* x,其中 x 0 ∈ [ a , b ] x_0\in[a,b] x0[a,b]。从而有
lim ⁡ n → ∞ x n = lim ⁡ n → ∞ φ ( x n − 1 ) = x ∗ \lim_{n\to\infty}x_{n}=\lim_{n\to\infty}\varphi(x_{n-1})=x^* nlimxn=nlimφ(xn1)=x
现在我们讨论牛顿迭代法。其基本思想在于做切线不断逼近零点。假设我们面对的函数为 f ( x ) f(x) f(x),则在初始值 x 0 x_0 x0处的切线为 y − y 0 = f ′ ( x 0 ) ( x − x 0 ) y-y_0 = f^{'}(x_0)(x-x_0) yy0=f(x0)(xx0) y = 0 y=0 y=0得到 x 1 x_1 x1,从而不断迭代逼近真实值,其迭代式为
x n = φ ( x n − 1 ) = x n − 1 − f ( x n − 1 ) f ′ ( x n − 1 ) x_n = \varphi(x_{n-1}) = x_{n-1}-\frac{f(x_{n-1})}{f^{'}(x_{n-1})} xn=φ(xn1)=xn1f(xn1)f(xn1)当求最值问题时,则迭代式为
x n = x n − 1 − f ′ ( x n − 1 ) f ′ ′ ( x n − 1 ) x_n = x_{n-1}-\frac{f_{'}(x_{n-1})}{f^{''}(x_{n-1})} xn=xn1f(xn1)f(xn1)牛顿迭代法在一定的条件下可以证明收敛 (参见《计算方法》,凹凸性),其收敛条件一般采用事后判断法,即
∣ x n − x n − 1 ∣ < ϵ \mid x_{n}-x_{n-1}\mid < \epsilon xnxn1<ϵ当自变量为多元情况的时候,其迭代式的形式仍是一致的。根据多元微积分,此时的一阶偏导数为一个向量,即梯度,记为 ▽ x f ( x ) \bigtriangledown_{x}f(x) xf(x),二阶偏导数为一个矩阵,即海森矩阵(Hessian) H H H,每一个元素为 H i , j = ∂ 2 f ( x ) ∂ x i ∂ x j H_{i,j} = \frac{\partial^2{f(x)}}{\partial{x_{i}}\partial{x_{j}}} Hi,j=xixj2f(x)因此多元情况下的牛顿迭代法的迭代式为
x n = φ ( x n − 1 ) = x n − 1 − H − 1 ▽ x f ( x ) x_n = \varphi(x_{n-1}) = x_{n-1}-H^{-1}\bigtriangledown_{x}f(x) xn=φ(xn1)=xn1H1xf(x)注:一般情况下牛顿迭代法会比梯度下降迭代次数更少,收敛速度更快。然而每一次迭代牛顿迭代法需要需要计算的量更多,因为其中有一个海森矩阵。但只要维度n不是很大,总体上牛顿迭代的速度更快。

Newton’s method typically enjoys faster convergence than (batch) gra-dient descent, and requires many fewer iterations to get very close to the minimum. One iteration of Newton’s can, however, be more expensive than one iteration of gradient descent, since it requires finding and inverting an n-by-n Hessian; but so long as n is not too large, it is usually much faster overall. When Newton’s method is applied to maximize the logistic regres-sion log likelihood function ℓ(θ), the resulting method is also called Fisher scoring.——Andrew Ng

殊途同归:简单线性模型下几何直观和概率直观的统一汇合

前面我们讨论了 θ \theta θ的两个求解角度,得到了两个函数,即损失函数和似然函数。接下来我们将看到,最小化损失函数和最大化似然函数实际上是等价的。然后我们会讨论在简单线性模型下,两种角度下的函数最值求解,其实不同数值算法也可以,因为我们可以直接进行代数分析给出最值点的数学解析式。

注意,从OSL和MLE两个角度出发,得到损失函数和似然函数,其最值问题等价,这个事情并不平凡。在后面介绍广义线性模型的时候,我们会看到基于各种指数簇分布的回归特例(简单线性模型只是基于正态分布下的回归特例),这个事情并不成立,即它们在理论上可能得到不同的参数 θ \theta θ。BTW,后面我们采用的都是MLE的角度,因为从MLE出发,利用梯度方法,各个回归特例的梯度更新公式都有统一的优美形式,此为后话。

几何直观角度下(OSL)的BGD、SGD梯度方法

OSL定义的损失函数(cost function) 如下:
J ( θ ) = 1 2 ∑ i = 1 m [ h θ ( x ( i ) ) − y ( i ) ] 2 J(\theta) = \frac{1}{2}\sum_{i=1}^{m}[h_{\theta}(x^{(i)})-y^{(i)}]^2 J(θ)=21i=1m[hθ(x(i))y(i)]2其关于参数的导数为 ∂ J ( θ ) ∂ θ = ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) x ( i ) \frac{\partial{J(\theta)}}{\partial\theta}=\sum_{i=1}^{m}(h_{\theta}(x^{(i)})-y^{(i)})x^{(i)} θJ(θ)=i=1m(hθ(x(i))y(i))x(i)在BSD中,每一次对 θ \theta θ的更新需要遍历全部训练集的数据,其更新规则如下: θ : = θ + α ∑ i = 1 m ( y ( i ) − h θ ( x ( i ) ) ) x ( i ) \theta:=\theta+\alpha\sum_{i=1}^{m}(y^{(i)}-h_{\theta}(x^{(i)}))x^{(i)} θ:=θ+αi=1m(y(i)hθ(x(i)))x(i)而在SGD中,每一次仅从训练集中挑出一个训练样本对 θ \theta θ进行更新,因此其更新规则为:
θ : = θ + α ( y ( i ) − h θ ( x ( i ) ) ) x ( i ) \theta:=\theta+\alpha(y^{(i)}-h_{\theta}(x^{(i)}))x^{(i)} θ:=θ+α(y(i)hθ(x(i)))x(i)其中 α \alpha α表示的是学习率,或者形象地认为其为更新的步长。
注:从更高的角度来看,我们要降低不仅仅是训练数据集中的整体误差,而是整个样本空间的泛化误差,因此真正的损失函数为 J ( θ ) = 1 2 ∫ x ∈ χ [ h θ ( x ( i ) ) − y ( i ) ] 2 p ( x ) d x J(\theta) = \frac{1}{2}\int_{x\in\chi}[h_{\theta}(x^{(i)})-y^{(i)}]^2p(x)dx J(θ)=21xχ[hθ(x(i))y(i)]2p(x)dx而由于事实上我们无法知道总体的分布,因此按照蒙特卡洛模拟算法,应该抽取一定的样本进行近似,若取样本量 M = m M = m M=m,则为BGD,若取样本量 M = 1 M = 1 M=1时,则为SGD,显然还可以取 1 < M < m 1 < M < m 1<M<m,此时则为小批量梯度下降算法 (Mini-Batch Gradient Descent)。
至此其实可以看到BGD与SGD本质上是一致的,即从总体中抽出样本来降低模拟误差。实际中SGD的应用会更多一些,特别是在训练数据量m较大时,其收敛速度更快,同时一定程度上能避免陷入局部最小值。

概率直观下(MLE)的 BGD、SGD方法

概率直观下定义的似然函数为
L ( θ ) = ∑ i = 1 m 1 2 π σ e x p ( − ( y i − h θ ( x ) ) 2 σ 2 ) L(\theta) = \sum_{i=1}^{m}\frac{1}{\sqrt{2\pi}\sigma}exp(-\frac{(y_{i}-h_{\theta}(x))^2}{\sigma^2}) L(θ)=i=1m2π σ1exp(σ2(yihθ(x))2)对数之并约简,即可得到
ℓ ( θ ) = l n L ( θ ) = − m l n ( 2 π σ ) − 1 σ 2 ∑ i = 1 m ( y i − h θ ( x ) ) 2 \ell(\theta) = lnL(\theta)=-mln(\sqrt{2\pi}\sigma)-\frac{1}{\sigma^2}\sum_{i=1}^{m}(y^{i}-h_{\theta}(x))^2 (θ)=lnL(θ)=mln(2π σ)σ21i=1m(yihθ(x))2可以看到,求 ℓ ( θ ) \ell(\theta) (θ)的最大值,等价于求 ∑ i = 1 m [ h θ ( x ( i ) ) − y ( i ) ] 2 \sum_{i=1}^{m}[h_{\theta}(x^{(i)})-y^{(i)}]^2 i=1m[hθ(x(i))y(i)]2的最小值,这正是OLS的损失函数的形式。因此MLE对参数 θ \theta θ的求解,理论上同OLS就是等价的。由此也可以领悟到OLS是一个非常自然的方法,它实际上是在一组假设下做极大似然估计(我们其实更偏爱概率直观,所以用MLE来解释OSL)。

This is thus one set of assumptions under which least-squares re-gression can be justified as a very natural method that’s just doing maximum likelihood estimation.----Andrew Ng

两种角度下最优参数的数学解析式

通过代数分析,我们可以直接在理论上给出 θ = arg ⁡ min ⁡ θ ∈ Θ J / L ( θ ) \theta = {\arg\min}_{\theta\in\Theta}J/L(\theta) θ=argminθΘJ/L(θ)时的数学表达式。为了方便进行代数分析,我们引入下列记号:

  • 样本矩阵 X X X
    [ 1 x 1 ( 1 ) x 2 ( 1 ) ⋯ x n ( 1 ) 1 x 1 ( 2 ) x 2 ( 2 ) ⋯ x n ( 2 ) 1 x 1 ( 3 ) x 2 ( 3 ) ⋯ x n ( 3 ) ⋮ ⋱ ⋮ 1 x 1 ( m ) x 2 ( m ) ⋯ x n ( m ) ] \left[ \begin{matrix} 1 & x_1^{(1)} & x_2^{(1)} & \cdots & x_n^{(1)}\\ 1 & x_1^{(2)} & x_2^{(2)} & \cdots & x_n^{(2)}\\ 1 & x_1^{(3)} & x_2^{(3)} & \cdots & x_n^{(3)}\\ \vdots & & & \ddots & \vdots\\ 1 & x_1^{(m)} & x_2^{(m)} & \cdots & x_n^{(m)} \end{matrix} \right] 1111x1(1)x1(2)x1(3)x1(m)x2(1)x2(2)x2(3)x2(m)xn(1)xn(2)xn(3)xn(m)

  • 对参数向量 θ \theta θ的求导运算:

  1. 向量求导: ∂ A T θ ∂ θ = A \frac{\partial{A^T\theta}}{\partial{\theta}}=A θATθ=A,其中 A A A是一个常数列向量。
  2. 向量求导: ∂ θ T B θ ∂ θ = 2 B θ \frac{\partial{\theta^TB\theta}}{\partial{\theta}}=2B\theta θθTBθ=2Bθ,其中 B B B是一个对称矩阵。

至此,则损失函数可以表示为矩阵代数的形式:
J ( θ ) = 1 2 u ^ T u ^ = 1 2 ( y − X θ ) T ( y − X θ ) = 1 2 ( y T y − 2 y T X θ + θ T X T X θ ) \begin{aligned} J(\theta)=& \frac{1}{2}\hat{u}^T\hat{u} \\ =&\frac{1}{2}(y-X\theta)^T(y-X\theta)\\ =&\frac{1}{2}( y^Ty-2y^TX\theta+\theta^TX^TX\theta) \end{aligned} J(θ)===21u^Tu^21(yXθ)T(yXθ)21(yTy2yTXθ+θTXTXθ) J ′ ( θ ) = X T X θ − X T y = 0 J^{'}(\theta) = X^TX\theta-X^Ty = 0 J(θ)=XTXθXTy=0,即可解出
θ = ( X T X ) − 1 X T y \theta = (X^TX)^{-1}X^Ty θ=(XTX)1XTy

简单线性模型的进一步拓展:局部加权线性回归(Local Weighted Liner Regression,LWLR)

局部加权线性回归采用一种非参数的方法来预测未知的样本。在之前的方法中,一旦参数向量 θ \theta θ学习出来后,则可以将历史的样本抛弃。而在LWLR中,历史收集到的样本需要始终保留下来,每一次对新样本进行估计时,都会动态得到结合样本数据和新样本的位置,给出一个参数 θ \theta θ的一个新的估计结果。换言之, θ \theta θ是为新样本量身定做的。下面我们主要从几何直观的角度讨论LWLR。
注:我们其实仍然可以从概率直观的角度来解释LWLR,有兴趣的读者可以自己思考(从异方差的角度)。

下面讨论LWLR的具体做法。对于一个新进的样本 x ( j ) x^{(j)} x(j)

  • 利用已有的数据(经验),最小化 ∑ i = 1 m w ( i ) ( h θ ( x ( i ) ) − y ( i ) ) 2 \sum_{i=1}^{m}w^{(i)}(h_{\theta}(x^{(i)})-y^{(i)})^2 i=1mw(i)(hθ(x(i))y(i))2,得到 θ j ^ \hat{\theta_j} θj^
  • 给出预测值 y ^ ( j ) = θ j ^ T x ( j ) \hat{y}^{(j)} = \hat{\theta_j}^{T}x^{(j)} y^(j)=θj^Tx(j)

其中, w ( i ) w^{(i)} w(i)可以由核光滑函数来确定,即:
w ( i ) = e x p ( − ( x ( i ) − x ( j ) ) 2 2 τ 2 ) w^{(i)} = exp(-\frac{(x^{(i)}-x^{(j)})^2}{2\tau^2}) w(i)=exp(2τ2(x(i)x(j))2)其中 τ \tau τ称为宽度(bandwidth),控制了权重随距离下降的快慢。从几何直观的角度看,越靠近 x ( j ) x^{(j)} x(j) x ( i ) x^{(i)} x(i),其误差平方将会被给予更大的权重。
总体上可以认为对 y ( j ) y^{(j)} y(j)的估计时,不同的训练样本不在被一视同仁,越靠近 x ( j ) x^{(j)} x(j)的样本点越被重视,从而得到的直线将会更好地符合 x ( j ) x^{(j)} x(j)周围的样本点的情况。

在局部加权最小二乘法中,利用梯度方法进行 θ \theta θ的迭代求解,此时的更新公式是:

  • BGD: θ : = θ + α ∑ i = 1 m ( y ( i ) − h θ ( x ( i ) ) ) x ( i ) w ( i ) \theta:=\theta+\alpha\sum_{i=1}^{m}(y^{(i)}-h_{\theta}(x^{(i)}))x^{(i)}w^{(i)} θ:=θ+αi=1m(y(i)hθ(x(i)))x(i)w(i)
  • SGD: θ : = θ + α ( y ( i ) − h θ ( x ( i ) ) ) x ( i ) w ( i ) \theta:=\theta+\alpha(y^{(i)}-h_{\theta}(x^{(i)}))x^{(i)}w^{(i)} θ:=θ+α(y(i)hθ(x(i)))x(i)w(i)

利用矩阵代数分析,同样可以得到 θ j ^ \hat{\theta_{j}} θj^的数学解析式。首先令
权重矩阵 W W W
[ w ( 1 ) 0 ⋯ 0 0 w ( 2 ) ⋯ 0 ⋮ ⋱ ⋮ 0 0 ⋯ w ( m ) ] \left[ \begin{matrix} w^{(1)} & 0 & \cdots & 0\\ 0 & w^{(2)} & \cdots & 0\\ \vdots & & \ddots & \vdots \\ 0 & 0 & \cdots & w^{(m)} \end{matrix} \right] w(1)000w(2)000w(m)则此时的损失函数可以表示为:
J ( θ ) = 1 2 ∑ i = 1 m w ( i ) ( h θ ( x ( i ) ) − y ( i ) ) 2 = 1 2 ∑ i = 1 m ( w ( i ) h θ ( x ( i ) ) − w ( i ) y ( i ) ) 2 = 1 2 ∑ i = 1 m ( h θ ( w ( i ) x ( i ) ) − w ( i ) y ( i ) ) 2 \begin{aligned} J(\theta) = & \frac{1}{2}\sum_{i=1}^{m}w^{(i)}(h_{\theta}(x^{(i)})-y^{(i)})^2\\ = & \frac{1}{2}\sum_{i=1}^{m}(\sqrt{w^{(i)}}h_{\theta}(x^{(i)})-\sqrt{w^{(i)}}y^{(i)})^2\\ = & \frac{1}{2}\sum_{i=1}^{m}(h_{\theta}(\sqrt{w^{(i)}}x^{(i)})-\sqrt{w^{(i)}}y^{(i)})^2 \end{aligned} J(θ)===21i=1mw(i)(hθ(x(i))y(i))221i=1m(w(i) hθ(x(i))w(i) y(i))221i=1m(hθ(w(i) x(i))w(i) y(i))2因此原来的样本数据等价变换后的样本数据,其属性值为 w ( i ) x ( i ) \sqrt{w^{(i)}}x^{(i)} w(i) x(i),标记值为 w ( i ) y ( i ) \sqrt{w^{(i)}}y^{(i)} w(i) y(i)。利用矩阵的记法,则样本矩阵记为 W 1 2 X W^{\frac{1}{2}}X W21X,标记矩阵记为 W 1 2 y ⃗ W^{\frac{1}{2}}\vec{y} W21y ,故代入原来的解析式
θ = ( X T X ) − 1 X T y ⃗ \theta = (X^TX)^{-1}X^T\vec{y} θ=(XTX)1XTy 可得
θ j ^ = ( X T W X ) − 1 X T W y ⃗ \hat{\theta_{j}} = (X^TWX)^{-1}X^TW\vec{y} θj^=(XTWX)1XTWy 一般的,当样本属性空间是多维度的时候,即 x x x是多维向量时,根据高维欧式空间距离的推广式: ∥ x − y ∥ = ( x − y ) T ( x − y ) \parallel x-y \parallel = (x-y)^T(x-y) xy=(xy)T(xy)核光滑函数可以表示为:
w ( i ) = e x p ( − ( x ( i ) − x ( j ) ) T ( x ( i ) − x ( j ) ) 2 τ 2 ) w^{(i)} = exp(-\frac{(x^{(i)}-x^{(j)})^T(x^{(i)}-x^{(j)})}{2\tau^2}) w(i)=exp(2τ2(x(i)x(j))T(x(i)x(j)))

实战项目:简单线性模型下BGD、SGD、Mini-Batch GD、数学解析式的实现和LWLR的实现 (python)

特别说明:在梯度下降算法中,需要特别留意学习率 α \alpha α(步长)的大小设置。以BGD为例,如果 α \alpha α设置过大,则会出现总误差不减反增的现象,最终导致溢出。通过查看中间输出可看到,其过程中误差函数的偏导数出现正负号轮流出现的规律,可以推断这是由于 α \alpha α过大导致的震荡现象,从而使得偏导数越来越大,总误差趋向无穷。
SGD中步长更合适的方法应该是采取自适应方式,即不应当将其设为一个常值,原因在于在最后收敛处,较大的步长会影响其得到稳定的优解,而在一开始迭代时,较小的步长会影响到其迭代的速度,因此总体上步长的设置应该逐步减小。

myLm.py

import numpy as np
from numpy import dot
from numpy.linalg import inv
import random

def Lm(X,Y,method,alpha = 0.001,epsilon = 0.0000001,o = None,tau = None):
    '''
    X:样本矩阵 [1,x1,x2,x3,...,xn]
    Y:样本标签值向量 [y]
    method:训练参数时使用的方法,有OLS、BGD、SGD、MBGD、LWLM
    alpha: 学习速率(步长)
    epsilon:迭代终止阈值
    return:本函数通过使用相应的算法,给出简单线性回归模型的参数估计值
    '''
    if(method == 'OLS'):
        theta_0 = dot(dot(inv(dot(X.T,X)),X.T),Y)
        return theta_0
    elif(method == 'BGD'):
        #初始值设置
        theta_0 = np.ones(shape = X.shape[1])
        #计算当前损失函数的总误差
        error_0 = 0.5*dot((dot(X,theta_0)-Y).T,dot(X,theta_0)-Y)
        #启动循环
        error = epsilon+1
        #迭代次数n
        n = 0
        while(error > epsilon):       
            #计算全部样本误差函数的梯度
            G = dot(dot(X.T,X),theta_0)-dot(X.T,Y)
            #更新theta
            theta_0 = theta_0 - alpha*G
            #计算步长更新后的损失函数的总误差
            error_1 = 0.5*dot((dot(X,theta_0)-Y).T,dot(X,theta_0)-Y)
            #计算前后二者的差
            error = abs(error_1-error_0)
            #将新一轮的误差保存用于下一轮
            error_0 = error_1
            # 输出迭代过程
            # print('---------------第',n,'轮迭代--------------')
            # print('theta:',theta_0)
            # print('error:',error)
            # print('G:',G,'\n')
            n = n + 1
        print('BGD Iteration Times: ',n)
        return theta_0
        
    elif(method == 'SGD'):
        #初始值设置
        theta_0 = np.ones(shape = X.shape[1])
        #计算当前初始值下损失函数的总误差
        error_0 = 0.5*dot((dot(X,theta_0)-Y).T,dot(X,theta_0)-Y)
        #启动循环
        error = epsilon+1
        #样本量
        m = X.shape[0]
        #遍历列表
        k = list(range(m))
        #迭代次数
        n = 0
        while(error > epsilon):
            #选择一个随机数[] r = random.randint(0,m-1)
            #遍历乱序列表
            random.shuffle(k)
            #计算当前样本下的梯度
            for r in k:
                G = (dot(X[r,:],theta_0)-Y[r])*X[r,:]
                #更新theta的值
                theta_0 = theta_0 - alpha*G
            #计算步长更新后theta_1下损失函数的总误差
            error_1 = 0.5*dot((dot(X,theta_0)-Y).T,dot(X,theta_0)-Y)
            #计算误差修正值大小
            error = abs(error_1-error_0)
            #将新一轮的误差保存用于下一轮
            error_0 = error_1
            # 输出迭代过程
            # if(n%100 == 0):
                # print('---------------第',n,'轮迭代--------------')
                # print('theta:',theta_0)
                # print('error:',error)
                # if(n > 8000):
                    # alpha = 0.00001
                # print('r:',r)
                # print('G:',G,'\n')
            n = n + 1
        print('SGD Iteration Times: ',n)
        return theta_0
    elif(method == 'MBGD'):
        #初始值设置
        theta_0 = np.ones(shape = X.shape[1])
        #计算当前损失函数的总误差
        error_0 = 0.5*dot((dot(X,theta_0)-Y).T,dot(X,theta_0)-Y)
        #启动循环
        error = epsilon+1
        #样本量
        m = X.shape[0]
        #遍历列表
        k = list(range(m))        
        #迭代次数n
        n = 0
        while(error > epsilon):       
            #随机选取一定批量的样本
            random.shuffle(k)
            minBatch = k[:m//10]
            minX = X[minBatch]
            minY = Y[minBatch]  
            #计算小批量样本误差函数的梯度
            G = dot(dot(minX.T,minX),theta_0)-dot(minX.T,minY)
            #更新theta
            theta_0 = theta_0 - alpha*G
            #计算步长更新后的损失函数的总误差
            error_1 = 0.5*dot((dot(X,theta_0)-Y).T,dot(X,theta_0)-Y)
            #计算前后二者的差
            error = abs(error_1-error_0)
            #将新一轮的误差保存用于下一轮
            error_0 = error_1
            # 输出迭代过程
            # print('---------------第',n,'轮迭代--------------')
            # print('theta:',theta_0)
            # print('error:',error)
            # print('G:',G,'\n')
            n = n + 1
        print('MBGD Iteration Times: ',n)
        return theta_0
    elif(method == 'LWLM'):
    	#局部加权线性回归
        XCopy = X[:,1:]-o
        d = []
        for i in range(XCopy.shape[0]):
            d.append(dot(XCopy[i],XCopy[i]))
        d = np.array(d)
        w = np.exp(-d**2/(2*tau**2))
        W = np.diag(w)
        theta_0 = dot(dot(dot(inv(dot(dot(X.T,W),X)),X.T),W),Y)
        return theta_0
    else:
        print('No Such Method In this Func.')

myLmtest.py

import myLm
import numpy as np
import pandas as pd

if __name__ == '__main__':
    samData = pd.read_table('mlData/regreData/simpleRegre.txt',header = None)
    #转换为二维数组
    sample = np.array(samData)
    #将属性值与标签值分开
    sampleX = sample[:,:np.shape(sample)[1]-1]
    sampleY = sample[:,sample.shape[1]-1]
    x = np.array([0])
    #Testing
    theta = myLm.Lm(sampleX,sampleY,method = 'LWLM',o = x,tau = 1)
    print('LWLM:',theta)
    theta = myLm.Lm(sampleX,sampleY,method = 'SGD')
    print('SGD:',theta)
    theta = myLm.Lm(sampleX,sampleY,method = 'BGD')
    print('BGD:',theta)
    theta = myLm.Lm(sampleX,sampleY,method = 'MBGD')
    print('MBGD:',theta)
    theta = myLm.Lm(sampleX,sampleY,method = 'OLS')
    print('OLS:',theta)

你可能感兴趣的:(机器学习,统计学,人工智能,计算机科学,数学,机器学习笔记)