美文网首页
Python机器学习基础教程学习笔记(5)——线性模型(回归)

Python机器学习基础教程学习笔记(5)——线性模型(回归)

作者: neumeng | 来源:发表于2019-10-09 08:16 被阅读0次

    Python机器学习基础教程学习笔记(5)——线性模型(回归)

    import numpy as np
    import matplotlib.pyplot as plt
    import pandas as pd
    import mglearn
    

    1 线性回归处理wave数据集

    1.1 wave数据集

    mglearn.plots.plot_linear_regression_wave()
    
    w[0]: 0.393906  b: -0.031804
    
    output_3_1

    1.2 线性回归

    • 线性回归,或者普通最小二乘法(ordinary least squairs ,OLS),回归总是最简单也是最经典的线性方法
    • 寻找参数w和b,使得对训练集的预测值与真实的回归目标值y之间的均方误差(预测值与真实值之差的平方各除以样本数)最小。
    • 没有参数,但无法控制模型的复杂度
    from sklearn.linear_model import LinearRegression
    X,y = mglearn.datasets.make_wave(n_samples=60)
    from sklearn.model_selection import train_test_split
    X_train,X_test,y_train,y_test = train_test_split(X,y,random_state=42)
    
    lr = LinearRegression().fit(X_train,y_train)
    
    # "斜率"参数(w,也叫做权重或系统),被保存到coef_属性中
    print("lr.coef_:{}".format(lr.coef_))
    # 偏移或者截距(b),被保存到intercept_属性中
    print("lr.intercept_:{}".format(lr.intercept_))
    
    lr.coef_:[0.39390555]
    lr.intercept_:-0.031804343026759746
    
    print("Train set score:{:.2f}".format(lr.score(X_train,y_train)))
    print("Test set score:{:.2f}".format(lr.score(X_test,y_test)))
    
    Train set score:0.67
    Test set score:0.66
    
    • R^2分数约为0.66,结果不是很好
    • 训练集和测试集的分数非常接近,可能存在欠拟合
    • 一维数据来说,过拟合的风险很小,因为模型非常简单(或受限)
    • 高维数据来说,线性模型变得更加强大,过拟合的可能性也会变大

    2 线性回归处理波士顿房价数据集

    2.1 波士顿房价数据集

    from sklearn.datasets import load_boston
    boston = load_boston()
    
    # boston是Bunch类型数据
    print("boston.keys :{}".format(boston.keys()))
    
    boston.keys :dict_keys(['data', 'target', 'feature_names', 'DESCR', 'filename'])
    
    # 数据集包括506个数据点,13个特征
    print("data shape :{}".format(boston.data.shape))
    
    data shape :(506, 13)
    

    扩展数据集:

    • 输入特征不仅包括这13个测量结果
    • 还包括这些特征的乘积(也叫交互项
    • 像这样包含导出特征的方法叫作特征工程(feature engineering)
    # 通过load_extended_boston函数加载导出的数据集
    X,y = mglearn.datasets.load_extended_boston()
    # 最初的13个特征加上这13个特征两两组合(有放回)得到的91个特征,一共有104个特征
    print("X.shape:{}".format(X.shape))
    
    X.shape:(506, 104)
    

    2.2 用线性回归处理

    X_train,X_test,y_train,y_test = train_test_split(X,y,random_state=0)
    lr = LinearRegression().fit(X_train,y_train)
    
    print("Train set score:{:.2f}".format(lr.score(X_train,y_train)))
    print("Test set score:{:.2f}".format(lr.score(X_test,y_test)))
    
    Train set score:0.95
    Test set score:0.61
    
    • 训练集和测试集之间的性能差异是过拟合(训练集0.95,测试集0.61)的明显标志
    • 线性回归没有参数,不可以控制模型复杂度。

    3 岭回归(Ridge regression)

    • 一种用于回归的线性模型
    • 预测公式与普通最小二乘法相同
    • 对系数(w)的选择不仅要在训练集数据上得到好的预测结果
    • 还要拟合附加约束
    • 系统尽可能小——w的所有元素都应接近于0
    • 意味着,每个特征对输出的影响应尽可能小(即斜率很小),同时仍给出很好的预测结果 。这种约束是所谓的正则化的一个例子
    • 正则化是指对模型做的显示约束,以避免过拟合
    • 岭回归用的是L2正则化
    from sklearn.linear_model import Ridge
    ridge = Ridge().fit(X_train,y_train)
    
    print("Train set score:{:.2f}".format(ridge.score(X_train,y_train)))
    print("Test set score:{:.2f}".format(ridge.score(X_test,y_test)))
    
    Train set score:0.89
    Test set score:0.75
    
    • ridge的训练集分数0.89低于linear的训练集分数0.95

    • ridge的测试集分数0.75高于linear的训练集分数0.61

    • linear过拟合

    • rigde约束性更强,更不容易过拟合

    • riged复杂度更小,在训练集性能更差,泛化性能更好

    • 我们对泛化性能感兴趣,应选择ridge,而不选择linear

    • ridge在模型的简单性(系数都接近于0)与训练集之间做出权衡

    • 通过alpha参数来指定

    • 默认alpha=0

    • alpha的最佳设定值取决于用到的具体的数据集

    • alpha越大,模型约束性越强,系数越趋向于0,训练集性能越低,泛化能力越强

    • alpha非常小,系数几乎没有限制,结果与linear类似

    ridge10=Ridge(alpha=10).fit(X_train,y_train)
    
    print("Train set score:{:.2f}".format(ridge10.score(X_train,y_train)))
    print("Test set score:{:.2f}".format(ridge10.score(X_test,y_test)))
    
    Train set score:0.79
    Test set score:0.64
    
    ridge01=Ridge(alpha=0.1).fit(X_train,y_train)
    
    print("Train set score:{:.2f}".format(ridge01.score(X_train,y_train)))
    print("Test set score:{:.2f}".format(ridge01.score(X_test,y_test)))
    
    Train set score:0.93
    Test set score:0.77
    
    ridge0001=Ridge(alpha=0.001).fit(X_train,y_train)
    
    print("Train set score:{:.2f}".format(ridge0001.score(X_train,y_train)))
    print("Test set score:{:.2f}".format(ridge0001.score(X_test,y_test)))
    
    Train set score:0.95
    Test set score:0.63
    
    # 约束越强,y值越趋向于0
    # 约束强
    plt.plot(ridge10.coef_,"^",label="alpha=10")
    # 约束中
    plt.plot(ridge.coef_,"s",label="alpha=1")
    # 约束弱
    plt.plot(ridge01.coef_,"v",label="alpha=0.1")
    # 无约束
    plt.plot(lr.coef_,"o",label="linear")
    
    plt.xlabel("Coefficient index")
    plt.ylabel("Coefficient magnitude")
    plt.hlines(0,0,len(lr.coef_))
    plt.ylim(-25,25)
    plt.legend()
    plt.show()
    
    output_31_0
    • 固定alpha的值,改变训练集数据量
    • 将模型性能作为数据集大小的函数进行绘图,这样的图像叫作学习曲线
    mglearn.plots.plot_ridge_n_samples()
    
    output_33_0.png
    • 训练集分数高于测试集分数
    • ridge训练集分数低于linear训练集分数
    • ridge测试集分数高于linear测试集分数
    • 数据越多,性能越好
    • 如果数据量足够多,正则化不再重要,rideg与linear会得到同样的性能
    • 数据越多,linear将更加难以过拟合或记住所有的数据

    4 lasso

    • 约束系数使其接近于0
    • 使用L1正则化
    • 使某些系数刚好为0,说明某些特征被模型完全忽略,更容易解释,呈现模型最重要的特征
    • 自动化特征选择
    from sklearn.linear_model import Lasso
    
    lasso = Lasso().fit(X_train,y_train)
    print("Train set score:{:.2f}".format(lasso.score(X_train,y_train)))
    print("Test set score:{:.2f}".format(lasso.score(X_test,y_test)))
    print("Number of features used:{}".format(np.sum(lasso.coef_!=0)))
    
    Train set score:0.29
    Test set score:0.21
    Number of features used:4
    
    • 训练集和测试集的性能都很差,欠拟合
    • 只用到了104个特征中的4个
    • 正则化参数alpha,默认是1
    • 为降低欠拟合,尝试减小alpha,同时增加max_iter
    • alpha越小,模型越复杂,越不容易欠拟合
    • alpha极小,结果与linear类似
    lasso001 = Lasso(alpha=0.01,max_iter=100000).fit(X_train,y_train)
    print("Train set score:{:.2f}".format(lasso001.score(X_train,y_train)))
    print("Test set score:{:.2f}".format(lasso001.score(X_test,y_test)))
    # 模型用了33个特征,性能好了些
    print("Number of features used:{}".format(np.sum(lasso001.coef_!=0)))
    
    Train set score:0.90
    Test set score:0.77
    Number of features used:33
    
    lasso00001 = Lasso(alpha=0.0001,max_iter=100000).fit(X_train,y_train)
    print("Train set score:{:.2f}".format(lasso00001.score(X_train,y_train)))
    print("Test set score:{:.2f}".format(lasso00001.score(X_test,y_test)))
    # 模型用了96个特征,类似linear,过拟合
    print("Number of features used:{}".format(np.sum(lasso00001.coef_!=0)))
    
    Train set score:0.95
    Test set score:0.64
    Number of features used:96
    
    plt.plot(lasso.coef_, 's', label="Lasso alpha=1")
    plt.plot(lasso001.coef_, '^', label="Lasso alpha=0.01")
    plt.plot(lasso00001.coef_, 'v', label="Lasso alpha=0.0001")
    
    plt.plot(ridge01.coef_, 'o', label="Ridge alpha=0.1")
    plt.legend(ncol=2, loc=(0, 1.05))
    plt.ylim(-25, 25)
    plt.xlabel("Coefficient index")
    plt.ylabel("Coefficient magnitude")
    plt.show()
    
    output_41_0.png
    • alpha=1,只用到了104个特征中的4个,大部分系数都为0,而且系数比较小
    • alpha=0.01,用了33个特征
    • alpha=0.0001,用了96个特征,大不分系数不为0,而且系数比较大
    • ridge(alpha=0.1)性能与lasso(alpha=0.01)性能类似,但是ridge的所有系数都不为0

    实践中:

    • 首先ridge
    • 特征多,认为只有其中几个是重要的,选择lasso
    • 想更容易解释,选择lasso
    • scikit-learn提供了ElasticNet,结合了ridge和lasso的惩罚项,效果最好,需要调节l1正则化参数和l2正则化参数,共2个参数

    相关文章

      网友评论

          本文标题:Python机器学习基础教程学习笔记(5)——线性模型(回归)

          本文链接:https://www.haomeiwen.com/subject/lrtqyctx.html