机器学习系列14丨线性回归(二)

一.线性回归api介绍

1.通过正规方程优化

  • sklearn.linear_model.LinearRegression(fit_intercept=True)

    • 通过正规方程优化
    • fit_intercept:是否计算偏置
    • LinearRegression.coef_:回归系数
    • LinearRegression.intercept_:偏置

代码演示:

# 数据集
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
# 模型评估
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, test_size=0.2, random_state=22)

    # 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_)

    # 准确率
    score = estimator.score(x_test, y_test)
    print("准确率是:\n", score)

    # 5.2 评价
    # 均方误差
    error = mean_squared_error(y_test, y_predict)
    print("均方误差是:\n", error)

if __name__ == '__main__':
    linear_model1()

结果如下:

20211015150712

2.通过梯度下降法优化

  • 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_:偏置

代码演示:

# 加载数据集
from sklearn.datasets import load_boston
# 数据集分割
from sklearn.model_selection import train_test_split
# 特征工程标准化,数据预处理
from sklearn.preprocessing import StandardScaler
# 线性回归-梯度下降法
from sklearn.linear_model import SGDRegressor
# 模型评估
from sklearn.metrics import mean_squared_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, test_size=0.2, random_state=22)

    # 3.特征工程-标准化
    transfer = StandardScaler()
    x_train = transfer.fit_transform(x_train)
    x_test = transfer.fit_transform(x_test)

    # 4.机器学习-线性回归(梯度下降)
    # eta0 指定学习率
    estimator = SGDRegressor(max_iter=1000, learning_rate="constant", eta0=0.001)
    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_)

    # 准确率
    score = estimator.score(x_test, y_test)
    print("准确率是:\n", score)

    # 5.2 评价
    # 均方误差
    error = mean_squared_error(y_test, y_predict)
    print("均方误差是:\n", error)


if __name__ == '__main__':
    linear_model2()

learning_rate一般进行动态的更新,也可以指定成为一个常数,但是不推荐,运行发现结果波动会比较大。

20211015154724

二.欠拟合、过拟合

1.什么是欠拟合、过拟合

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

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

2.欠拟合原因以及解决办法

原因:

学习到数据的特征过少

解决办法:

1)添加其他特征项,有时候我们模型出现欠拟合的时候是因为特征项不够导致的,可以添加其他特征项来很好地解决。例如,“组合”、“泛化”、“相关性”三类特征是特征添加的重要手段,无论在什么场景,都可以照葫芦画瓢,总会得到意想不到的效果。除上面的特征之外,“上下文特征”、“平台特征”等等,都可以作为特征添加的首选项。

2)添加多项式特征,这个在机器学习算法里面用的很普遍,例如将线性模型通过添加二次项或者三次项使模型泛化能力更强。

3.过拟合原因以及解决办法

原因:

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

解决办法:

1)重新清洗数据,导致过拟合的一个原因也有可能是数据不纯导致的,如果出现了过拟合就需要我们重新清洗数据。

2)增大数据的训练量,还有一个原因就是我们用于训练的数据量太小导致的,训练数据占总数据的比例过小。

3)正则化

4)减少特征维度,防止维灾难

4.什么是正则化

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

20211015225805

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

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

5.正则化类别

  • L2正则化

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

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

6.维灾难

什么是维灾难

随着维度的增加,分类器性能逐步上升,到达某点之后,其性能便逐渐下降。

20211015230315

表现在哪些方面

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

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

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

三.正则化线性模型

1.Ridge Regression (岭回归,又名 Tikhonov regularization)

在系数前面添加平方项,然后限制系数值的大小,α值越小,系数值越大,α越大,系数值越小。

20211018141748

2.Lasso Regression(Lasso 回归)

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

20211018143012

3.Elastic Net (弹性网络)

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

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

弹性网络的代价函数 :

20211018144707

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

4.小结:

常用: 岭回归

假设只有少部分特征是有用的:

  • 弹性网络
  • Lasso

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

from sklearn.linear_model import Ridge, ElasticNet, Lasso

5.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_:回归偏置

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

sklearn.linear_model.RidgeCV(_BaseRidgeCV, RegressorMixin)

  • 具有l2正则化的线性回归,可以进行交叉验证
  • coef_:回归系数

2.正则化程度的变化,对结果的影响

20211018152737

3.岭回归代码演示

Ridge和RidgeCV方法

# 加载数据集
from sklearn.datasets import load_boston
# 数据集分割
from sklearn.model_selection import train_test_split
# 特征工程标准化,数据预处理
from sklearn.preprocessing import StandardScaler
# 线性回归-岭回归
from sklearn.linear_model import Ridge,RidgeCV
# 模型评估
from sklearn.metrics import mean_squared_error


def linear_model():
    """
    线性回归:岭回归
    :return:None
    """
    # 1.获取数据
    data = load_boston()

    # 2.数据集划分
    x_train, x_test, y_train, y_test = train_test_split(data.data, data.target, test_size=0.2, random_state=22)

    # 3.特征工程-标准化
    transfer = StandardScaler()
    x_train = transfer.fit_transform(x_train)
    x_test = transfer.fit_transform(x_test)

    # 4.机器学习
    # eta0 指定学习率
    # estimator = Ridge()
    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_)

    # 准确率
    score = estimator.score(x_test, y_test)
    print("准确率是:\n", score)

    # 5.2 评价
    # 均方误差
    error = mean_squared_error(y_test, y_predict)
    print("均方误差是:\n", error)


if __name__ == '__main__':
    linear_model()

结果如下图:

20211018153315

五.模型保存和加载

1.API介绍

from sklearn.externals import joblib

# 保存
joblib.dump(estimator, 'test.pkl')

# 加载
estimator = joblib.load('test.pkl')

2.模型的保存

代码演示:

20211018154509

结果如下:

20211018154749

3.模型加载

加载刚刚保存的模型文件,代码演示:

20211018154953

运行结果和上方是一致的,均方差相同。

20211018154850