美文网首页机器学习
"深入浅出Python机器学习" 学习笔记-

"深入浅出Python机器学习" 学习笔记-

作者: 爱折腾的大懒猪 | 来源:发表于2019-07-04 23:27 被阅读1次

    3.2.3 kNN用于回归分析

    首先使用make_regression 创建一个数据集, 然后用KNeighborsRegressor 构建回归模型. 最后看看影响因素. 对比kNN用于分类, 回归的效果要差些.

    • make_regression : 产生随机回归问题的数据点.
      • n_samples=100 : 数据点数.
      • n_features=100 : 特征数.默认100个变量.
      • n_targets=1 :目标值的向量的大小. 默认是一个标量值.
      • n_informative=10 : 有效特征数. 用于构建模型使用的特征数.
      • noise=0.0 : 高斯噪音的标准差.
      • bias=0.0 : 偏差. 体现出来类似截距, 但不是一个概念.
      • effective_rank=None :
      • tail_strength=0.5 :
      • coef=False : 如设置为True, 返回时会返回线性模型的特征的系数.
      • shuffle=True, random_state=None: 同上.
      • 返回(X, y, coef), coef要在参数设置后才有返回.

    这里构建了100样本(默认), 特征数1, 有效特征1, 噪音标准差50的数据集.

    # 使用make_regression 生成特征1,噪音50
    from sklearn.datasets import make_regression
    X, y = make_regression(n_features=1,n_informative=1,noise=50,random_state=8)
    plt.scatter(X,y,c='orange',edgecolor='k')
    plt.show()
    
    make_regression生成数据集
    # 导入kNN回归分析的模型
    from sklearn.neighbors import KNeighborsRegressor
    reg = KNeighborsRegressor()
    # 拟合数据并评分
    reg.fit(X,y)
    print('模型评分:{:.2f}'.format(reg.score(X,y)))
    
    # 预测结果可视化.
    z = np.linspace(-3,3,200).reshape(-1,1)
    plt.scatter(X,y,c='orange',edgecolor='k')
    plt.plot(z, reg.predict(z),c='k',linewidth=3)
    plt.title('KNN Regressor')
    plt.show()
    
    kNN回归分析(k=5)
    # 导入kNN回归分析的模型
    from sklearn.neighbors import KNeighborsRegressor
    reg2 = KNeighborsRegressor(n_neighbors=20)
    # 拟合数据并评分
    reg2.fit(X,y)
    print('模型评分:{:.2f}'.format(reg2.score(X,y)))
    
    # 预测结果可视化.
    z = np.linspace(-3,3,200).reshape(-1,1)
    plt.scatter(X,y,c='orange',edgecolor='k')
    plt.plot(z, reg2.predict(z),c='k',linewidth=3)
    plt.title('KNN Regressor: n_neighbors=20')
    plt.show()
    # k = 2: 模型评分:0.86
    # k = 5: 模型评分:0.77 (上面默认的5)
    # k = 10: 模型评分:0.75
    # k = 20: 模型评分:0.67
    # k = 50: 模型评分:0.54
    
    kNN回归分析(k=2) kNN回归分析(k=5) kNN回归分析(k=10) kNN回归分析(k=20) kNN回归分析(k=50)

    从上述可以看出, 随着k的增大, 评分下降. 但k太小的时候, 显然存在一定过拟合的情况.

    # 尝试使用线性回归求解
    from sklearn.linear_model import LinearRegression
    lr = LinearRegression()
    lr.fit(X,y)
    print('模型评分:{:.2f}'.format(lr.score(X,y)))
    # 预测结果可视化.
    z = np.linspace(-3,3,200).reshape(-1,1)
    plt.scatter(X,y,c='orange',edgecolor='k')
    plt.plot(z, lr.predict(z),c='k',linewidth=3)
    plt.title('Linear Regressor')
    plt.show()
    
    # 模型评分: 0.69
    
    线性回归分析

    对比线性回归, kNN=20时较为接近. 太大时拟合不好, 太小时过拟合.

    那究竟分开训练集和测试集后是不是能明显看出这种差异呢?

    # 重新测试分割训练集合测试集后的效果
    # 点数越多, 拟合越稳定, 效果更稳定
    X, y = make_regression(n_samples=200, n_features=1,n_informative=1,noise=50,random_state=8)
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2,random_state=4)
    # 喜欢的可以把下面的random_state=4去掉,看多个效果
    
    # 测试分割训练集和测试集
    for n in [2,5,10,20,50]:
        reg3 = KNeighborsRegressor(n_neighbors=n)
        reg3.fit(X_train, y_train)
        print('训练集评分:{:.2f}'.format(reg3.score(X_train, y_train)))
        print('测试集评分:{:.2f}'.format(reg3.score(X_test, y_test)))
        # 预测结果可视化.
        z = np.linspace(-3,3,200).reshape(-1,1)
        plt.scatter(X_train, y_train,c='orange',edgecolor='k')
        plt.scatter(X_test, y_test,c='green',edgecolor='k')
        plt.plot(z, reg3.predict(z),c='k',linewidth=2)
        plt.title('KNN Regressor: n_neighbors=2')
        plt.show()
    
    lr2 = LinearRegression()
    lr2.fit(X_train, y_train)
    print('训练集评分:{:.2f}'.format(lr2.score(X_train, y_train)))
    print('测试集评分:{:.2f}'.format(lr2.score(X_test, y_test)))
    # 预测结果可视化.
    z = np.linspace(-3,3,200).reshape(-1,1)
    plt.scatter(X_train, y_train,c='orange',edgecolor='k')
    plt.scatter(X_test, y_test,c='green',edgecolor='k')
    plt.plot(z, lr2.predict(z),c='k',linewidth=2)
    plt.title('Linear Regressor')
    plt.show()
    
    • k = 2 训练集评分:0.87 测试集评分:0.66
    • k = 5 训练集评分:0.82 测试集评分:0.71
    • k = 10 训练集评分:0.80 测试集评分:0.72
    • k = 20 训练集评分:0.78 测试集评分:0.76
    • k = 50 训练集评分:0.68 测试集评分:0.64
    • 线性回归 训练集评分:0.77 测试集评分:0.70

    从上面结果来看, 的确存在过拟合现象, 尤其当k=2时最严重. k=5和10差不多, k=20时尽管训练集评分低些, 但测试集评分最高. 当k=50时, 出现欠拟合现象, 训练集和测试集评分均不高.

    # 重新测试分割训练集合测试集后的效果
    # 点数越多, 拟合越稳定, 效果更稳定
    import pandas as pd
    kv1 = [100, 200, 500, 1000, 2000]
    kv2 = [2, 5, 10, 20, 50]
    
    final_out = []
    for sn in kv1:
        X, y = make_regression(n_samples=sn, n_features=1,
                               n_informative=1, noise=50, random_state=8)
        output = []
        for i in range(100):
            X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2,random_state=i)
            scores = []
    
            # 测试分割训练集和测试集
            for n in kv2:
                reg3 = KNeighborsRegressor(n_neighbors=n)
                reg3.fit(X_train, y_train)
                scores += [reg3.score(X_train, y_train), reg3.score(X_test, y_test)]
    
            lr2 = LinearRegression()
            lr2.fit(X_train, y_train)
            scores += [lr2.score(X_train, y_train), lr2.score(X_test, y_test)]
            output.append(scores)
        final_out.append(pd.DataFrame(output).mean().tolist())
    pd.DataFrame(final_out,
                 columns=pd.MultiIndex.from_product([['k=2', 'k=5', 'k=10','k=20','k=50','LR']
                         ,['train', 'test']]),
                 index = kv1).round(decimals=3)
    
    多次测试

    上述做了个多次测试, 主要对采样训练和测试做了随机100次, 而不同的k, 以及不同的样本数的情况. 从上表中可以看到一个比较奇怪的是500样本时比较反常, 因为此时(随机为8)时, 样本点比较分散, 因此回归和kNN的效果都不甚好, 甚至在kNN中的测试集出现了负数.

    从上表也可以看出, 当k较小时, 容易出现过拟合, 当k=5或10时, 其实已经比较稳定了, 继续增大时(k=50)部分就出现欠拟合情况(点多的情况, k=50也开始稳定.)在多次的随机训练可以看出, 线性回归在这里的测试表现最佳, 训练和测试的成功率相当.

    500次样本时的点分布

    书中说, k=2时覆盖更多点, 评分比k=5时显著提高. 这实在说得不科学. 上面测试做了更丰富的结果供参考.

    相关文章

      网友评论

        本文标题:"深入浅出Python机器学习" 学习笔记-

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