• 机器学习【线性回归算法2】


    六 线性回归api再使用

    1 正规方程API

    sklearn.linear_model.LinearRegression(fit_intercept=True)
    	通过正规方程优化
    	fit_intercept:是否计算偏置
    	LinearRegression.coef_:回归系数
    	LinearRegression.intercept_:偏置,在一元方程是截距
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2 梯度下降API

    sklearn.linear_model.SGDRegressor(loss="squared_loss", fit_intercept=True, learning_rate ='invscaling', eta0=0.01)
    	SGDRegressor类实现了随机梯度下降学习,它支持不同的loss函数和正则化惩罚项来拟合线性回归模型。
    	loss:损失类型
    		loss=”squared_loss”: 普通最小二乘法
    	fit_intercept:是否计算偏置
    	learning_rate : string, optional
    		学习率填充
    		'constant': eta = eta0
    		'optimal': eta = 1.0 / (alpha * (t + t0)) [default]
    		'invscaling': eta = eta0 / pow(t, power_t)
    			power_t=0.25:存在父类当中
    		对于一个常数值的学习率来说,可以使用learning_rate=’constant’ ,并使用eta0来指定学习率。
    	SGDRegressor.coef_:回归系数
    	SGDRegressor.intercept_:偏置
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    sklearn提供了两种实现的API, 可以根据选择使用

    七 案例:波士顿房价预测

    数据介绍

    在这里插入图片描述

    属性说明

    在这里插入图片描述

    给定的这些特征,是专家们得出的影响房价的结果属性。此阶段不需要自己去探究特征是否有用,只需要使用这些特征。到后面量化很多特征需要自己去寻找

    1 分析

    回归当中的数据大小不一致,是否会导致结果影响较大。所以需要做标准化处理。

    • 数据分割与标准化处理
    • 回归预测
    • 线性回归的算法效果评估

    2 回归性能评估

    均方误差(Mean Squared Error)MSE)评价机制:

    在这里插入图片描述

    注:yi为预测值,¯y为真实值

    sklearn.metrics.mean_squared_error(y_true, y_pred)
    	均方误差回归损失
    	y_true:真实值
    	y_pred:预测值
    	return:浮点数结果
    
    • 1
    • 2
    • 3
    • 4
    • 5

    3 代码实现

    from sklearn.datasets import load_boston
    from sklearn.model_selection import train_test_split
    from sklearn.preprocessing import StandardScaler
    from sklearn.linear_model import LinearRegression,SGDRegressor	
    from sklearn.metrics import mean_squared_error
    
    def linear_model1():
        """
        线性回归:正规方程
        :return:None
        """
        # 1.获取数据
        data = load_boston()
    
        # 2.数据集划分
        x_train, x_test, y_train, y_test = train_test_split(data.data, data.target, random_state=22, test_size=0.2)
    
        # 3.特征工程-标准化
        transfer = StandardScaler()
        x_train = transfer.fit_transform(x_train)
        x_test = transfer.fit_transform(x_test)
    
        # 4.机器学习-线性回归(特征方程)
        estimator = LinearRegression()
        estimator.fit(x_train, y_train)
    
        # 5.模型评估
        # 5.1 获取系数等值
        y_predict = estimator.predict(x_test)
        print("模型中的预测值为:\n", y_predict)
        print("模型中的系数为:\n", estimator.coef_)
        print("模型中的偏置为:\n", estimator.intercept_)
        print("模型中的准确率为:\n", estimator.score(x_test,y_test))
    
        # 5.2 评价
        # 均方误差
        error = mean_squared_error(y_test, y_predict)
        print("误差为:\n", error)
    
    
    def linear_model2():
        """
        线性回归:梯度下降法
        :return:None
        """
        # 1.获取数据
        data = load_boston()
    
        # 2.数据集划分
        x_train, x_test, y_train, y_test = train_test_split(data.data, data.target, random_state=22)
    
        # 3.特征工程-标准化
        transfer = StandardScaler()
        x_train = transfer.fit_transform(x_train)
        x_test = transfer.fit_transform(x_test)
    
        # 4.机器学习-线性回归(随机梯度下降)
        estimator = SGDRegressor(max_iter=1000)
        estimator.fit(x_train, y_train)
    
        # 5.模型评估
        # 5.1 获取系数等值
        y_predict = estimator.predict(x_test)
        print("预测值为:\n", y_predict)
        print("模型中的系数为:\n", estimator.coef_)
        print("模型中的偏置为:\n", estimator.intercept_)
    
        # 5.2 评价
        # 均方误差
        error = mean_squared_error(y_test, y_predict)
        print("误差为:\n", error)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71

    也可以尝试去修改学习率

    estimator = SGDRegressor(max_iter=1000,learning_rate="constant",eta0=0.1)
    
    • 1

    执行

    if __name__ == '__main__':
        linear_model1()
        linear_model2()
    
    • 1
    • 2
    • 3

    此时可以通过调参数,找到学习率效果更好的值。

    八 欠拟合和过拟合

    1 定义

    过拟合:一个假设在训练数据上能够获得比其他假设更好的拟合, 但是在测试数据集上却不能很好地拟合数据,此时认为这个假设出现了过拟合的现象。(模型过于复杂)

    欠拟合:一个假设在训练数据上不能获得更好的拟合,并且在测试数据集上也不能很好地拟合数据,此时认为这个假设出现了欠拟合的现象。(模型过于简单)

    在这里插入图片描述

    那么是什么原因导致模型复杂?线性回归进行训练学习的时候变成模型会变得复杂,这里就对应前面再说的线性回归的两种关系,非线性关系的数据,也就是存在很多无用的特征或者现实中的事物特征跟目标值的关系并不是简单的线性关系。

    2 原因以及解决办法

    2.1 欠拟合原因以及解决办法

    原因:学习到数据的特征过少

    解决办法:

    • 添加其他特征项,有时候模型出现欠拟合的时候是因为特征项不够导致的,可以添加其他特征项来很好地解决。例如,“组合”、“泛化”、“相关性”三类特征是特征添加的重要手段,无论在什么场景,都可以照葫芦画瓢,总会得到意想不到的效果。除上面的特征之外,“上下文特征”、“平台特征”等等,都可以作为特征添加的首选项。
    • 添加多项式特征,这个在机器学习算法里面用的很普遍,例如将线性模型通过添加二次项或者三次项使模型泛化能力更强。

    2.2 过拟合原因以及解决办法

    原因:原始特征过多,存在一些嘈杂特征, 模型过于复杂是因为模型尝试去兼顾各个测试数据点

    解决办法:

    • 重新清洗数据,导致过拟合的一个原因也有可能是数据不纯导致的,如果出现了过拟合就需要重新清洗数据。
    • 增大数据的训练量,还有一个原因就是用于训练的数据量太小导致的,训练数据占总数据的比例过小。
    • 正则化
    • 减少特征维度,防止维灾难

    3 正则化

    3.1 什么是正则化

    在解决回归过拟合中,选择正则化。但是对于其他机器学习算法如分类算法来说也会出现这样的问题,除了一些算法本身作用之外(决策树、神经网络),更多的也是去自己做特征选择,包括之前说的删除、合并一些特征

    在这里插入图片描述

    过拟合的解决办法
    在这里插入图片描述

    在学习的时候,数据提供的特征有些影响模型复杂度或者这个特征的数据点异常较多,所以算法在学习的时候尽量减少这个特征的影响(甚至删除某个特征的影响),这就是正则化

    注:调整时候,算法并不知道某个特征影响,而是去调整参数得出优化的结果

    3.2 正则化类别

    L2正则化

    • 作用:可以使得其中一些权重值都很小,都接近于0,削弱某个特征的影响
    • 优点:越小的参数说明模型越简单,越简单的模型则越不容易产生过拟合现象
    • Ridge回归

    L1正则化

    • 作用:可以使得其中一些权重值直接为0,删除这个特征的影响
    • LASSO回归

    4 维灾难

    4.1 什么是维灾难

    随着维度的增加,分类器性能逐步上升,到达某点之后,其性能便逐渐下降
    在这里插入图片描述

    现有一系列的图片,每张图片的内容可能是猫也可能是狗;需要构造一个分类器能够对猫、狗自动的分类。首先,要寻找到一些能够描述猫和狗的特征,这样分类算法就可以利用这些特征去识别物体。猫和狗的皮毛颜色可能是一个很好的特征,考虑到红绿蓝构成图像的三基色,因此用图片三基色各自的平均值称得上方便直观。这样就有了一个简单的Fisher分类器:

    If  0.5*red + 0.3*green + 0.2*blue > 0.6 : return cat;
        else return dog;
    
    • 1
    • 2

    使用颜色特征可能无法得到一个足够准确的分类器,如果是这样的话,不妨加入一些诸如图像纹理(图像灰度值在其X、Y方向的导数dx、dy),就有5个特征(Red、Blue、Green、dx、dy)来设计分类器:

    也许分类器准确率依然无法达到要求,加入更多的特征,比如颜色、纹理的统计信息等等,如此下去,可能会得到上百个特征。那是不是分类器性能会随着特征数量的增加而逐步提高呢?答案也许有些让人沮丧,事实上,当特征数量达到一定规模后,分类器的性能是在下降的。

    随着维度(特征数量)的增加,分类器的性能却下降了

    4.2 维数灾难与过拟合

    假设猫和狗图片的数量是有限的(样本数量总是有限的),假设有10张图片,接下来就用这仅有的10张图片来训练分类器。

    在这里插入图片描述

    增加一个特征,比如绿色,这样特征维数扩展到了2维:

    增加一个特征后,依然无法找到一条简单的直线将它们有效分类

    在这里插入图片描述

    再增加一个特征,比如蓝色,扩展到3维特征空间:
    在这里插入图片描述

    在3维特征空间中,很容易找到一个分类平面,能够在训练集上有效的将猫和狗进行分类:

    在高维空间中,似乎能得到更优的分类器性能。

    在这里插入图片描述

    从1维到3维,感觉是:维数越高,分类性能越优。然而,维数过高将导致一定的问题:在一维特征空间下,假设一个维度的宽度为5个单位,这样样本密度为10/5=2;在2维特征空间下,10个样本所分布的空间大小25,这样样本密度为10/25=0.4;在3维特征空间下,10个样本分布的空间大小为125,样本密度就为10/125=0.08.

    如果继续增加特征数量,随着维度的增加,样本将变得越来越稀疏,在这种情况下,也更容易找到一个超平面将目标分开。然而,如果将高维空间向低维空间投影,高维空间隐藏的问题将会显现出来:

    过多的特征导致的过拟合现象:训练集上表现良好,但是对新数据缺乏泛化能力。

    在这里插入图片描述

    高维空间训练形成的线性分类器,相当于在低维空间的一个复杂的非线性分类器,这种分类器过多的强调了训练集的准确率甚至于对一些错误/异常的数据也进行了学习,而正确的数据却无法覆盖整个特征空间。为此,这样得到的分类器在对新数据进行预测时将会出现错误。这种现象称之为过拟合,同时也是维灾难的直接体现。

    在这里插入图片描述

    简单的线性分类器在训练数据上的表现不如非线性分类器,但由于线性分类器的学习过程中对噪声没有非线性分类器敏感,因此对新数据具备更优的泛化能力。换句话说,通过使用更少的特征,避免了维数灾难的发生(也即避免了高维情况下的过拟合)

    由于高维而带来的数据稀疏性问题:假设有一个特征,它的取值范围D在0到1之间均匀分布,并且对狗和猫来说其值都是唯一的,现在利用这个特征来设计分类器。如果训练数据覆盖了取值范围的20%(e.g 0到0.2),那么所使用的训练数据就占总样本量的20%。上升到二维情况下,覆盖二维特征空间20%的面积,则需要在每个维度上取得45%的取值范围。在三维情况下,要覆盖特征空间20%的体积,则需要在每个维度上取得58%的取值范围…在维度接近一定程度时,要取得同样的训练样本数量,则几乎要在每个维度上取得接近100%的取值范围,或者增加总样本数量,但样本数量也总是有限的。

    如果一直增加特征维数,由于样本分布越来越稀疏,如果要避免过拟合的出现,就不得不持续增加样本数量。

    在这里插入图片描述

    数据在高维空间的中心比在边缘区域具备更大的稀疏性,数据更倾向于分布在空间的边缘区域:

    不属于单位圆的训练样本比搜索空间的中心更接近搜索空间的角点。这些样本很难分类,因为它们的特征值差别很大(例如,单位正方形的对角的样本)。
    在这里插入图片描述

    一个有趣的问题是,当增加特征空间的维度时,圆(超球面)的体积如何相对于正方形(超立方体)的体积发生变化。尺寸d的单位超立方体的体积总是1 ^ d = 1.尺寸d和半径0.5的内切超球体的体积可以计算为:

    在这里插入图片描述

    在高维空间中,大多数训练数据驻留在定义特征空间的超立方体的角落中。如前所述,特征空间角落中的实例比围绕超球体质心的实例难以分类。

    在这里插入图片描述

    在高维空间中,大多数训练数据驻留在定义特征空间的超立方体的角落中。如前所述,特征空间角落中的实例比围绕超球体质心的实例难以分类:

    在这里插入图片描述

    事实证明,许多事物在高维空间中表现得非常不同。 例如,如果选择一个单位平方(1×1平方)的随机点,它将只有大约0.4%的机会位于小于0.001的边界(换句话说,随机点将沿任何维度“极端”这是非常不可能的)。 但是在一个10000维单位超立方体(1×1×1立方体,有1万个1)中,这个概率大于99.999999%。 高维超立方体中的大部分点都非常靠近边界。更难区分的是:如果在一个单位正方形中随机抽取两个点,这两个点之间的距离平均约为0.52。如果在单位三维立方体中选取两个随机点,则平均距离将大致为0.66。但是在一个100万维的超立方体中随机抽取两点呢?那么平均距离将是大约408.25(大约1,000,000 / 6)!

    非常违反直觉:当两个点位于相同的单位超立方体内时,两点如何分离?这个事实意味着高维数据集有可能非常稀疏:大多数训练实例可能彼此远离。当然,这也意味着一个新实例可能离任何训练实例都很远,这使得预测的可信度表现得比在低维度数据中要来的差。训练集的维度越多,过度拟合的风险就越大

    理论上讲,维度灾难的一个解决方案可能是增加训练集的大小以达到足够密度的训练实例。 不幸的是,在实践中,达到给定密度所需的训练实例的数量随着维度的数量呈指数增长。 如果只有100个特征(比MNIST问题少得多),那么为了使训练实例的平均值在0.1以内,需要比可观察宇宙中的原子更多的训练实例,假设它们在所有维度上均匀分布。

    对于8维超立方体,大约98%的数据集中在其256个角上。结果,当特征空间的维度达到无穷大时,从采样点到质心的最小和最大欧几里得距离的差与最小距离本身只比趋于零:

    在这里插入图片描述

    距离测量开始失去其在高维空间中测量的有效性,由于分类器取决于这些距离测量,因此在较低维空间中分类通常更容易,其中较少特征用于描述感兴趣对象。

    如果理论无限数量的训练样本可用,则维度的诅咒不适用,可以简单地使用无数个特征来获得完美的分类。训练数据的大小越小,应使用的功能就越少。如果N个训练样本足以覆盖单位区间大小的1D特征空间,则需要N ^ 2个样本来覆盖具有相同密度的2D特征空间,并且在3D特征空间中需要N ^ 3个样本。换句话说,所需的训练实例数量随着使用的维度数量呈指数增长

    九 正则化线性模型

    1 Ridge Regression (岭回归)

    在系数前面添加平方项,限制系数值的大小,α越小,系数值越大,反之,系数值越小,推荐岭回归

    又可以称为 Tikhonov regularization

    岭回归是线性回归的正则化版本,即在原来的线性回归的 cost function 中添加正则项(regularization term):

    在这里插入图片描述

    以达到在拟合数据的同时,使模型权重尽可能小的目的,岭回归代价函数:

    在这里插入图片描述

    α=0:岭回归退化为线性回归

    2 Lasso Regression(Lasso 回归)

    对系数值进行绝对值处理,由于绝对值在顶点处不可导,所以进行计算的过程中产生很多0,最后得到的结果为稀疏矩阵

    Lasso 回归是线性回归的另一种正则化版本,正则项为权值向量的ℓ1范数。

    Lasso回归的代价函数 :

    在这里插入图片描述

    【注意】

    • Lasso Regression 的代价函数在 θi=0处是不可导的
    • 解决方法:在θi=0处用一个次梯度向量(subgradient vector)代替梯度,如下式

    Lasso Regression 的次梯度向量

    在这里插入图片描述

    Lasso Regression 有一个很重要的性质是:倾向于完全消除不重要的权重。

    例如:当α 取值相对较大时,高阶多项式退化为二次甚至是线性:高阶多项式特征的权重被置为0。

    也就是说,Lasso Regression 能够自动进行特征选择,并输出一个稀疏模型(只有少数特征的权重是非零的)。

    3 Elastic Net (弹性网络)

    弹性网络在岭回归和Lasso回归中进行了折中,通过 混合比(mix ratio) r 进行控制:

    • r=0:弹性网络变为岭回归
    • r=1:弹性网络便为Lasso回归

    弹性网络的代价函数 :

    在这里插入图片描述

    一般来说,应避免使用朴素线性回归,而应对模型进行一定的正则化处理,那如何选择正则化方法呢?

    一般常用的是岭回归;假设只有少部分特征是有用的,可以使用弹性网络或Lasso

    一般来说,弹性网络的使用更为广泛。因为在特征维度高于训练样本数,或者特征是强相关的情况下,Lasso回归的表现不太稳定。

    API:

    from sklearn.linear_model import Ridge, ElasticNet, Lasso
    
    • 1

    4 Early Stopping

    Early Stopping 也是正则化迭代学习的方法之一。

    其做法为:在验证错误率达到最小值的时候停止训练。

    十 线性回归的改进-岭回归

    1 API

    sklearn.linear_model.Ridge(alpha=1.0, fit_intercept=True,solver="auto", normalize=False)
    	具有l2正则化的线性回归
    	alpha:正则化力度,也叫 λ
    		λ取值:0~1 1~10
    	solver:会根据数据自动选择优化方法
    		sag:如果数据集、特征都比较大,选择该随机梯度下降优化
    	normalize:数据是否进行标准化
    		normalize=False:可以在fit之前调用preprocessing.StandardScaler标准化数据
    	Ridge.coef_:回归权重
    	Ridge.intercept_:回归偏置
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    Ridge方法相当于SGDRegressor(penalty=‘l2’, loss=“squared_loss”),只不过SGDRegressor实现了一个普通的随机梯度下降学习,推荐使用Ridge(实现了SAG)

    sklearn.linear_model.RidgeCV(_BaseRidgeCV, RegressorMixin)
    	具有l2正则化的线性回归,可以进行交叉验证
    	coef_:回归系数	
    
    • 1
    • 2
    • 3
    class _BaseRidgeCV(LinearModel):
        def __init__(self, alphas=(0.1, 1.0, 10.0),
                     fit_intercept=True, normalize=False,scoring=None,
                     cv=None, gcv_mode=None,
                     store_cv_values=False):
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2 对结果影响

    观察正则化程度的变化,对结果的影响?

    在这里插入图片描述

    • 正则化力度越大,权重系数会越小
    • 正则化力度越小,权重系数会越大

    3 波士顿房价预测

    def linear_model3():
        """
        线性回归:岭回归
        :return:
        """
        # 1.获取数据
        data = load_boston()
    
        # 2.数据集划分
        x_train, x_test, y_train, y_test = train_test_split(data.data, data.target, random_state=22)
    
        # 3.特征工程-标准化
        transfer = StandardScaler()
        x_train = transfer.fit_transform(x_train)
        x_test = transfer.fit_transform(x_test)
    
        # 4.机器学习-线性回归(岭回归)
        estimator = Ridge(alpha=1)
        # estimator = RidgeCV(alphas=(0.001,0.1,1,10,100))
        estimator.fit(x_train, y_train)
    
        # 5.模型评估
        # 5.1 获取系数等值
        y_predict = estimator.predict(x_test)
        print("预测值为:\n", y_predict)
        print("模型中的系数为:\n", estimator.coef_)
        print("模型中的偏置为:\n", estimator.intercept_)
    
        # 5.2 评价
        # 均方误差
        error = mean_squared_error(y_test, y_predict)
        print("误差为:\n", error)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    十一 模型保存和加载

    1 sklearn模型的保存和加载

    API

    from sklearn.externals import joblib
    	保存:joblib.dump(estimator, 'test.pkl')
    	加载:estimator = joblib.load('test.pkl')
    
    • 1
    • 2
    • 3

    2 线性回归的模型保存加载案例

    def load_dump_demo():
    “”"
    模型保存和加载
    :return:
    “”"
    # 1.获取数据
    ​ data = load_boston()

    # 2.数据集划分
    x_train, x_test, y_train, y_test = train_test_split(data.data, data.target, random_state=22)
    
    # 3.特征工程-标准化
    transfer = StandardScaler()
    x_train = transfer.fit_transform(x_train)
    x_test = transfer.fit_transform(x_test)
    
    # 4.机器学习-线性回归(岭回归)
    # # 4.1 模型训练
    # estimator = Ridge(alpha=1)
    # estimator.fit(x_train, y_train)
    #
    # # 4.2 模型保存
    # joblib.dump(estimator, "./data/test.pkl")
    
    # 4.3 模型加载
    estimator = joblib.load("./data/test.pkl")
    
    # 5.模型评估
    # 5.1 获取系数等值
    y_predict = estimator.predict(x_test)
    print("预测值为:\n", y_predict)
    print("模型中的系数为:\n", estimator.coef_)
    print("模型中的偏置为:\n", estimator.intercept_)
    
    # 5.2 评价
    # 均方误差
    error = mean_squared_error(y_test, y_predict)
    print("误差为:\n", error)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
  • 相关阅读:
    【读书笔记】【Effective STL】算法
    Arthas使用总结
    11年前写的程序:Java 中闭包运用,实现方法传递
    frp配置http服务使用子域名不通不生效的问题记录
    HTML5离线储存
    基于JavaSwing开发聊天系统设计(群聊+服务器+客户端+MYSQL数据库) 毕业设计
    leetcode 116. 填充每个节点的下一个右侧节点指针-java实现
    Hadoop3.3.4 + HDFS Router-Based Federation配置
    基于 SM3 的密钥派生函数 (KDF):国密合规的安全密钥生成方案
    第十四届蓝桥杯(web应用开发)模拟赛2期 -大学组
  • 原文地址:https://blog.csdn.net/weixin_43923463/article/details/126166892