李宏毅机器学习作业2

学习打卡内容:

  • 理解偏差和方差

  • 学习误差为什么是偏差和方差而产生的,并且推导数学公式

  • 过拟合,欠拟合,分别对应bias和variance什么情况

  • 学习鞍点,复习上次任务学习的全局最优和局部最优

  • 解决办法有哪些

  • 梯度下降

  • 学习Mini-Batch与SGD

  • 学习Batch与Mini-Batch,SGD梯度下降的区别

  • 如何根据样本大小选择哪个梯度下降(批量梯度下降,Mini-Batch)

  • 写出SGD和Mini-Batch的代码

  • 学习交叉验证

  • 学习归一化

  • 学习回归模型评价指标

1. 偏差与方差

1.1. 学习误差为什么是偏差和方差而产生的,并且推导数学公式

对测试样本 x x x,令 y D y_D yD x x x在数据集中的标记,y为x的真实标记, f ( x ; D ) f(x;D) f(x;D)为训练集D上学得模型f在x上的预测输出。
方差:度量了同样大小的训练集的变动所导致的学习性能的变化,即刻画了数据扰动所造成的影响,以回归任务为例,学习算法的期望预测为 f ( x ) = E D [ f ˉ ( x ; D ) ] f(x) = E_D[\bar{f}(x;D)] f(x)=ED[fˉ(x;D)] 使用样本数相同的不同训练集产生的方差为 v a r ( x ) = E D [ ( f ( x ; D ) − f ˉ ( x ) ) 2 ] var(x) = E_D[(f(x;D) - \bar{f}(x))^2] var(x)=ED[(f(x;D)fˉ(x))2]
噪声:表达了在当前任务上任何学习算法所能达到的期望泛化误差的下界,即刻画了学习问题本身的难度。噪声是指样本在数据集中的标记与真实标记的偏差。
ε 2 = E D [ ( y D − y ) 2 ] \varepsilon^2 = E_D[(y_D-y)^2] ε2=ED[(yDy)2]
偏差: 度量了学习算法的期望预测与真实结果的偏离程度,即刻画了学习算法本身的拟合能力。期望输出与真实标记的差别称为偏差,即
b i a s 2 ( x ) = ( f ˉ ( x ) − y ) 2 bias^2(x) = (\bar{f}(x) - y)^2 bias2(x)=(fˉ(x)y)2
泛化误差
对算法的期望平均预测误差,定义为:
E ( f ; D ) = E D [ ( f ( x ; D ) − y D ) 2 ] E(f;D) = E_D[(f(x;D) - y_D)^2] E(f;D)=ED[(f(x;D)yD)2]

下面对算法的期望泛化误差进行分解:
E ( f ; D ) = E D [ ( f ( x ; D ) − y D ) 2 ] = E D [ ( f ( x ; D ) − f ˉ ( x ) + f ˉ ( x ) − y D ) 2 ] = E D [ ( f ( x ; D ) − f ˉ ( x ) ) 2 ] + E D [ ( f ˉ ( x ) − y D ) 2 ] + E D [ 2 ( f ( x ; D ) − f ˉ ( x ) ) ( f ˉ ( x ) − y D ) ] = E D [ ( f ( x ; D ) − f ˉ ( x ) ) 2 ] + E D [ ( f ˉ ( x ) − y D ) 2 ] = E D [ ( f ( x ; D ) − f ˉ ( x ) ) 2 ] + E D [ ( f ˉ ( x ) − y + y − y D ) 2 ] = E D [ ( f ( x ; D ) − f ˉ ( x ) ) 2 ] + E D [ ( f ˉ ( x ) − y ) 2 ] + E D [ ( y − y D ) 2 ] + 2 E D [ ( f ˉ ( x ) − y ) ( y − y D ) ] = E D [ ( f ( x ; D ) − f ˉ ( x ) ) 2 ] + E D [ ( f ˉ ( x ) − y ) 2 ] + E D [ ( y − y D ) 2 ] \begin{aligned} E(f;D) &= E_D[(f(x;D) - y_D)^2] \\ &=E_D[(f(x;D) - \bar{f}(x) + \bar f(x) -y_D)^2] \\ &=E_D[(f(x;D) - \bar{f}(x))^2] + E_D[( \bar f(x) -y_D)^2] + E_D[2(f(x;D) - \bar{f}(x))( \bar f(x) -y_D)] \\ &= E_D[(f(x;D) - \bar{f}(x))^2] + E_D[( \bar f(x) -y_D)^2] \\ &=E_D[(f(x;D) - \bar{f}(x))^2] + E_D[( \bar f(x) -y+y- y_D)^2] \\ &= E_D[(f(x;D) - \bar{f}(x))^2] + E_D[(\bar f(x) -y)^2] + E_D[(y- y_D)^2] + 2E_D[(\bar f(x) - y)(y - y_D)]\\ & = E_D[(f(x;D) - \bar{f}(x))^2] + E_D[(\bar f(x) -y)^2] + E_D[(y- y_D)^2] \end{aligned} E(f;D)=ED[(f(x;D)yD)2]=ED[(f(x;D)fˉ(x)+fˉ(x)yD)2]=ED[(f(x;D)fˉ(x))2]+ED[(fˉ(x)yD)2]+ED[2(f(x;D)fˉ(x))(fˉ(x)yD)]=ED[(f(x;D)fˉ(x))2]+ED[(fˉ(x)yD)2]=ED[(f(x;D)fˉ(x))2]+ED[(fˉ(x)y+yyD)2]=ED[(f(x;D)fˉ(x))2]+ED[(fˉ(x)y)2]+ED[(yyD)2]+2ED[(fˉ(x)y)(yyD)]=ED[(f(x;D)fˉ(x))2]+ED[(fˉ(x)y)2]+ED[(yyD)2]
于是, E ( f ; D ) = b i a s 2 ( x ) + v a r ( x ) + ε 2 E(f;D) = bias^2(x) + var(x) + \varepsilon^2 E(f;D)=bias2(x)+var(x)+ε2

1.2 过拟合,欠拟合,分别对应bias和variance什么情况

过拟合:指模型在训练集上具有很好的效果,在测试集上效果却不好。说明有较大的variance
欠拟合:指模型不能很好的拟合训练数据,说明有较大的bias。

1.3 解决过拟合和欠拟合的方法

过拟合:
(1)从数据入手,增加更多的训练数据。
(2)降低模型复杂度
(3)正则化方法
(4)集成学习方法

欠拟合:
(1)添加新的特征。
(2)增加模型复杂度
(3)减小正则化系数。

2 梯度下降

2.1 SGD与mini-Batch

SGD:
经典的梯度下降法采用所有训练数据的平均损失来近似目标函数,在每次对模型参数进行更新时,需要遍历所有的训练数据。当M很大时,需要很大的计算量,耗费很长的计算时间,在时间应用中基本不可行。
为了解决该问题,采用随机梯度下降法,即用单个训练数据对模型的参数进行一次更新,大大加快了收敛速率,该方法也非常适用于数据源源不断到来的在线更新场景。
Min-Batch Gradient Descent:小批量梯度下降法
每次同时处理若干训练数据对模型的参数进行一次更新。这种方法能够降低随机梯度的方差,从而使得迭代算法更加稳定。假设需要同时处理m个训练数据 ( x i 1 , y i 1 ) , . . . , ( x i m , y i m ) {(x_{i_1},y_{i_1}),...,(x_{i_m},y_{i_m})} (xi1,yi1),...,(xim,yim),则目标函数及其梯度为
L ( θ ) = 1 m ∑ j = 1 m L ( f ( x i j , θ ) , y i j ) L(\theta) = \frac{1}{m}\sum_{j=1}^m L(f(x_{i_j},\theta),y_{i_j}) L(θ)=m1j=1mL(f(xij,θ),yij) ∇ L ( θ ) = 1 m ∑ j = 1 m ∇ L ( f ( x i j , θ ) , y i j ) \nabla L(\theta) = \frac{1}{m}\sum_{j=1}^m \nabla L(f(x_{i_j},\theta),y_{i_j}) L(θ)=m1j=1mL(f(xij,θ),yij)

2.2 学习Batch与Mini-Batch,SGD梯度下降的区别

假设样本为M,
Batch:每次选择所有样本来对模型参数进行更新
SGD:每次选择一个训练样本来对模型参数进行更新,
min-Batch: 每次选择m 批量:单次迭代过程中用于求梯度下降法的样本总数
对于样本非常大的情况,批量越大,花的时间就越多,而且出现数据冗杂的情况越高
Batch:噪音少一些,幅度大一些。缺点:每次对整个训练集进行处理,那么数量集很大的时候耗费时间就会比较长。
SGD:从数据集中随机选择1个样本,迭代次数足够多,可以通过小得多的数据集估算(尽管过程非常杂乱)出较大的平均值。因为每次只对一个样本进行梯度下降,所以大部分时候是向着最小值靠近的,但也有一些是离最小值越来越远,因为那些样本恰好指向相反的方向,所以看起来会有很多噪音,但整体趋势是向最小值逼近。但SGD永远不会收敛,它只会在最小值附近不断的波动,不会到达也不会在此停留。SGD的噪音可以通过调节学习率来改善,但它有个很大的缺点,就是不能通过进行向量化来进行加速,因为每次都只是第一个样本进行处理。

Mini-Batch: 通常随机选取10~1000个样本,介于全批量梯度下降和随机梯度下降法之间。 可以减少 SGD 中的杂乱样本数量,但仍然比全批量更高效。速度比BSD快,比SGD慢;精度比BSD低,比SGD高。
该方法有两个优点:一个是可以进行向量化,另一个是不同用等待整个训练集训练完就可以进行后续工作。

2.3 如何根据样本大小选择哪个梯度下降(批量梯度下降,Mini-Batch)

如果训练集较小,一般小于2000的,就直接使用Batch gradient descent
当样本非常大或数据源源不断到来时,建议使用mini-Batch.一般Mini Batch gradient descent的m取2的幂次时能够充分利用矩阵运算操作,所以可以在2的幂次中挑选最优的取值,例如32、64、128、256等。

2.4 写出SGD和Mini-Batch的代码

## SGD(随机梯度下降算法)


def gen_line_data(sample_num = 100):
    """
    y = 3*x1 + 4*x2
    return:
    """
    x1 = np.linspace(0,9,sample_num)
    x2 = np.linspace(4,13,sample_num)
    x = np.concatenate(([x1],[x2]),axis=0).T
    y = np.dot(x, np.array([3,4]).T)
    return x, y

def sgd(samples,y, step_size=0.01, max_iter_count=10000):
    """
    随机梯度下降法
    param samples:样本
    y: 结果值
    step_size:每一次迭代的步长
    max_iter_count: 最大迭代次数
    batch_size: 随机选取的相对于总样本的大小
    return
    """
    sample_num, dim = samples.shape
    y = y.flatten()
    w = np.ones((dim,),dtype = np.float32)
    loss = 10
    iter_count = 0
    while loss > 0.001 and iter_count < max_iter_count:
        loss = 0
        error = np.zeros((dim,), dtype=np.float32)
        for i in range(sample_num):
            predict_y = np.dot(w.T, samples[i])
            for j in range(dim):
                error[j] = (y[i] - predict_y)*samples[i][j]
                w[j] +=step_size * error[j]/sample_num
                
        for i in range(sample_num):
            predict_y = np.dot(w.T,samples[i])
            error = (1/(sample_num * dim)) * np.power((predict_y-y[i]),2)
            loss += error
            
        print('iter_count:' ,iter_count, "the loss:",loss)
        iter_count += 1
        
    return w

if __name__ == '__main__':
    samples, y = gen_line_data()
    w = sgd(samples, y)
    print(w)
# MBGD  小批量梯度下降法
import numpy as np
import random

def gen_line_data(sample_num = 100):
    """
    y = 3*x1 + 4*x2
    """
    x1 = np.linspace(0,9,sample_num)
    x2 = np.linspace(4,13,sample_num)
    x = np.concatenate(([x1],[x2]),axis = 0).T
    y = np.dot(x,np.array([3,4]).T)
    return x,y

def mbgd(samples, y,step_size = 0.01,max_iter_count=10000, batch_size=0.2):
    sample_num,dim = samples.shape
    y = y.flatten()
    w = np.ones((dim,),dtype=np.float32)
    loss = 10
    iter_count=0
    while loss > 0.001 and iter_count < max_iter_count:
        loss = 0
        error = np.zeros((dim,), dtype=np.float32)
        
        index = random.sample(range(sample_num), int(np.ceil(sample_num * batch_size)))
        batch_samples = samples[index]
        batch_y = y[index]
        
        for i in range(len(batch_samples)):
            predict_y = np.dot(w.T, batch_samples[i])
            for j in range(dim):
                error[j] += (batch_y[i] - predict_y)*batch_samples[i][j]
        for j in range(dim):
            w[j] += step_size * error[j]/sample_num
            
        for i in range(sample_num):
            predict_y = np.dot(w.T, samples[i])
            error = (1/(sample_num * dim))*np.power((predict_y - y[i]), 2)
            loss += error
            
        iter_count += 1
    return w
    
if __name__ == '__main__':
    samples, y = gen_line_data()
    w = mbgd(samples, y)
    print(w)

2.5 交叉验证

k-fold交叉验证
首先将全部样本划分成k个大小等的样本子集,依次遍历这k个子集,每次把当前子集作为验证集,其余所有子集作为训练集,进行模型的训练和评估;最后把k次评估指标的平均值作为最终的评估指标。在实际实验中,k经常取10.

留一验证
每次留下1个样本作为验证集,其余所有样本作为测试集。样本总数为n,依次对n个样本进行遍历,进行n次验证,再将评估指标求平均值得到最终的评估指标。在样本总数较多的情况下,留一验证法的时间开销极大。事实上,留一验证是留p验证的特例。留p验证hi每次留下p个样本作为验证集,而从n个元素中选择p个元素有 C n p C_n^p Cnp种可能,因此它的时间开销更是远远高于留一验证,故而很少在实际工程中被应用。

2.6 归一化

为了消除数据特征之间的量纲影响,我们需要对特征进行归一化处理使得不同指标之间具有可比性。
对数值类型的特征做归一化可以将所有的特征都统一到一个大致相同的数值区间内,最常用的方法主要有以下两种:
(1)线性函数归一化(Min-Max Scaling)它对原始数据进行线性变换,使结果映射到[0,1]范围,实现对原始数据的等比缩放。归一化公式如下: X n o r m = X − X m i n X m a x − X m i n X_{norm}= \frac{X-X_{min}}{X_{max} - X_{min}} Xnorm=XmaxXminXXmin 其中 X X X为原始数据, X m a x X_{max} Xmax X m i n X_{min} Xmin分别为数据最大值和最小值。
(2)零均值归一化(Z-Score Normalization)。它会将原始数据映射到均值为0、标准差为1的分布上。具体来说,假设原始特征的均值为 μ \mu μ,标准差为 σ \sigma σ,那么归一化公式定义为 z = x − μ σ z = \frac{x-\mu}{\sigma} z=σxμ
数据归一化并不是万能的。在实际应用中,通过梯度下降法求解的模型通常是需要归一化的,包括线性回归,逻辑回归,支持向量机、神经网络等模型。但对于决策树模型则并不适用。

2.7 学习回归模型评价指标

RMSE(平方根误差)经常被用来衡量回归模型的好坏。RMSE的计算公式为 R M S E = ∑ i = 1 n ( y i − y i ^ ) 2 n RMSE = \sqrt{\frac{\sum_{i=1}^n(y_i - \hat{y_i})^2}{n}} RMSE=ni=1n(yiyi^)2 其中, y i y_i yi是第 i i i个样本点的真实值, y i ^ \hat{y_i} yi^是第i个样本点的预测值,n是样本点的个数。
一般情况下,RMSE能够很好的反映回归模型预测值与真实值的偏离程度,但在实际问题中,如果存在个别偏离程度非常大的离群点时,即使离群点数量非常少,也会让RMSE指标变得很差。
针对这个问题,可以从三个角度来思考。第一,如果这些离群点是噪声点,就需要在数据预处理的阶段把这些噪声点过滤掉,第二、如果不认为这些离群点时噪声点,就需要进一步提高模型的预测能力,将离群点产生的机制建模进去。第三,可以最后一个更适合的指标来评估该模型。关于评估指标,其实是存在比RMSE的鲁棒性更好的指标,比如平均绝对百分比误差(MAPE),它定义为: M A P E = ∑ i = 1 n ∣ y i − y i ^ y i ∣ × 100 n MAPE = \sum_{i=1}^n|\frac{y_i - \hat{y_i}}{y_i}| \times \frac{100}{n} MAPE=i=1nyiyiyi^×n100 相比RMSE、MAPE相当于把每个点的误差进行了归一化,降低了个别离群点带来的绝对误差的影响。

你可能感兴趣的:(李宏毅机器学习)