• sklearn机器学习——day13


    要探索 两个变量之间的关系是否是线性的,最简单的方式就是绘制散点图,如果散点图能够相对均匀地分布在一条直线的两 端,则说明这两个变量之间的关系是线性的。

    线性数据

    一组数据由多个特征和标签组成。当这些 特征分别与标签存在线性关系的时候,我们就说这一组数据是线性数据。当特征矩阵中任意一个特征与标签之间的关 系需要使用三角函数,指数函数等函数来定义,则我们就说这种数据叫做“非线性数据”

     

    线性回归在非线性数据上的表现

    建立一个明显是非线性的数据集,并观察线性回归和决策树的而回 归在拟合非线性数据集时的表现:

    1. import numpy as np
    2. import matplotlib.pyplot as plt
    3. from sklearn.linear_model import LinearRegression
    4. from sklearn.tree import DecisionTreeRegressor
    5. #创建需要拟合的数据集
    6. rnd = np.random.RandomState(42) #设置随机数种子
    7. X = rnd.uniform(-3, 3, size=100) #random.uniform,从输入的任意两个整数中取出size个随机数
    8. #生成y的思路:先使用NumPy中的函数生成一个sin函数图像,然后再人为添加噪音
    9. y = np.sin(X) + rnd.normal(size=len(X)) / 3 #random.normal,生成size个服从正态分布的随机数
    10. #使用散点图观察建立的数据集是什么样子
    11. plt.scatter(X, y,marker='o',c='k',s=20)
    12. plt.show()
    13. #为后续建模做准备:sklearn只接受二维以上数组作为特征矩阵的输入
    14. X.shape
    15. X = X.reshape(-1, 1)
    16. #使用原始数据进行建模
    17. #使用原始数据进行建模
    18. LinearR = LinearRegression().fit(X, y)
    19. TreeR = DecisionTreeRegressor(random_state=0).fit(X, y)
    20. #放置画布
    21. fig, ax1 = plt.subplots(1)
    22. #创建测试数据:一系列分布在横坐标上的点
    23. line = np.linspace(-3, 3, 1000, endpoint=False).reshape(-1, 1)
    24. #将测试数据带入predict接口,获得模型的拟合效果并进行绘制
    25. ax1.plot(line, LinearR.predict(line), linewidth=2, color='green',
    26. label="linear regression")
    27. ax1.plot(line, TreeR.predict(line), linewidth=2, color='red',
    28. label="decision tree")
    29. #将原数据上的拟合绘制在图像上
    30. ax1.plot(X[:, 0], y, 'o', c='k')
    31. #其他图形选项
    32. ax1.legend(loc="best")
    33. ax1.set_ylabel("Regression output")
    34. ax1.set_xlabel("Input feature")
    35. ax1.set_title("Result before discretization")
    36. plt.tight_layout()
    37. plt.show()
    38. #从这个图像来看,可以得出什么结果?

     线性回归无法拟合出这条带噪音的正弦曲线的真实面貌,只能够模拟出大概的趋势,而决策树却 通过建立复杂的模型将几乎每个点都拟合出来了。可见,使用线性回归模型来拟合非线性数据的效果并不好,而决策 树这样的模型却拟合得太细致,但是相比之下,还是决策树的拟合效果更好一些。

    线性模型可以用来拟合非线性数据,而非线性模型也可以用来拟合线性数据,更 神奇的是,有的算法没有模型也可以处理各类数据,而有的模型可以既可以是线性,也可以是非线性模型!

    非线性模型拟合线性数据

    如果我们使用随机森林来拟合一条直线,那随机森林毫无疑问会过拟合,因为线性数 据对于非线性模型来说太过简单,很容易就把训练集上的 训练得很高,MSE训练的很低

     

    线性模型拟合非线性数据

    线性模型若用来拟合非线性数据或者对非线性可分的数据进行分类,那通常都会表现糟糕。通常如果我 们已经发现数据属于非线性数据,或者数据非线性可分的数据,则我们不会选择使用线性模型来进行建模

    既是线性,也是非线性的模型 

    于有一些模型来说,他们既可以处理线性模型又可以处理非线性模型,比如说强大的支持向量机。 

     

     总结:

    使用分箱处理非线性问题

    1. import numpy as np
    2. import matplotlib.pyplot as plt
    3. from sklearn.linear_model import LinearRegression
    4. from sklearn.tree import DecisionTreeRegressor
    5. #创建需要拟合的数据集
    6. rnd = np.random.RandomState(42) #设置随机数种子
    7. X = rnd.uniform(-3, 3, size=100) #random.uniform,从输入的任意两个整数中取出size个随机数
    8. #生成y的思路:先使用NumPy中的函数生成一个sin函数图像,然后再人为添加噪音
    9. y = np.sin(X) + rnd.normal(size=len(X)) / 3 #random.normal,生成size个服从正态分布的随机数
    10. #使用散点图观察建立的数据集是什么样子
    11. plt.scatter(X, y,marker='o',c='k',s=20)
    12. plt.show()
    13. #为后续建模做准备:sklearn只接受二维以上数组作为特征矩阵的输入
    14. X.shape
    15. X = X.reshape(-1, 1)
    16. #使用原始数据进行建模
    17. #使用原始数据进行建模
    18. LinearR = LinearRegression().fit(X, y)
    19. TreeR = DecisionTreeRegressor(random_state=0).fit(X, y)
    20. #放置画布
    21. fig, ax1 = plt.subplots(1)
    22. #创建测试数据:一系列分布在横坐标上的点
    23. line = np.linspace(-3, 3, 1000, endpoint=False).reshape(-1, 1
    24. #将测试数据带入predict接口,获得模型的拟合效果并进行绘制
    25. ax1.plot(line, LinearR.predict(line), linewidth=2, color='green',
    26. label="linear regression")
    27. ax1.plot(line, TreeR.predict(line), linewidth=2, color='red',
    28. label="decision tree")
    29. #将原数据上的拟合绘制在图像上
    30. ax1.plot(X[:, 0], y, 'o', c='k')
    31. #其他图形选项
    32. ax1.legend(loc="best")
    33. ax1.set_ylabel("Regression output")
    34. ax1.set_xlabel("Input feature")
    35. ax1.set_title("Result before discretization")
    36. plt.tight_layout()
    37. plt.show()

     分箱及分箱的相关问题

    1. from sklearn.preprocessing import KBinsDiscretizer
    2. #将数据分箱
    3. enc = KBinsDiscretizer(n_bins=10 #分几类?
    4. ,encode="onehot") #ordinal
    5. X_binned = enc.fit_transform(X)
    6. #encode模式"onehot":使用做哑变量方式做离散化
    7. #之后返回一个稀疏矩阵(m,n_bins),每一列是一个分好的类别
    8. #对每一个样本而言,它包含的分类(箱子)中它表示为1,其余分类中它表示为0
    9. X.shape
    10. X_binned
    11. #使用pandas打开稀疏矩阵
    12. import pandas as pd
    13. pd.DataFrame(X_binned.toarray()).head()
    14. #我们将使用分箱后的数据来训练模型,在sklearn中,测试集和训练集的结构必须保持一致,否则报错
    15. LinearR_ = LinearRegression().fit(X_binned, y)
    16. LinearR_.predict(line) #line作为测试集
    17. line.shape #测试
    18. X_binned.shape #训练
    19. #因此我们需要创建分箱后的测试集:按照已经建好的分箱模型将line分箱
    20. line_binned = enc.transform(line)
    21. line_binned.shape #分箱后的数据是无法进行绘图的
    22. line_binned
    23. LinearR_.predict(line_binned).shape

    使用分箱数据进行建模和绘图

    1. #准备数据
    2. enc = KBinsDiscretizer(n_bins=10,encode="onehot")
    3. X_binned = enc.fit_transform(X)
    4. line_binned = enc.transform(line)
    5. #将两张图像绘制在一起,布置画布
    6. fig, (ax1, ax2) = plt.subplots(ncols=2
    7. , sharey=True #让两张图共享y轴上的刻度
    8. , figsize=(10, 4))
    9. #在图1中布置在原始数据上建模的结果
    10. ax1.plot(line, LinearR.predict(line), linewidth=2, color='green',
    11. label="linear regression")
    12. ax1.plot(line, TreeR.predict(line), linewidth=2, color='red',
    13. label="decision tree")
    14. ax1.plot(X[:, 0], y, 'o', c='k')
    15. ax1.legend(loc="best")
    16. ax1.set_ylabel("Regression output")
    17. ax1.set_xlabel("Input feature")
    18. ax1.set_title("Result before discretization")
    19. #使用分箱数据进行建模
    20. LinearR_ = LinearRegression().fit(X_binned, y)
    21. TreeR_ = DecisionTreeRegressor(random_state=0).fit(X_binned, y)
    22. #进行预测,在图2中布置在分箱数据上进行预测的结果
    23. ax2.plot(line #横坐标
    24. , LinearR_.predict(line_binned) #分箱后的特征矩阵的结果
    25. , linewidth=2
    26. , color='green'
    27. , linestyle='-'
    28. , label='linear regression')
    29. ax2.plot(line, TreeR_.predict(line_binned), linewidth=2, color='red',
    30. linestyle=':', label='decision tree')
    31. #绘制和箱宽一致的竖线
    32. ax2.vlines(enc.bin_edges_[0] #x轴
    33. , *plt.gca().get_ylim() #y轴的上限和下限
    34. , linewidth=1
    35. , alpha=.2)
    36. #将原始数据分布放置在图像上
    37. ax2.plot(X[:, 0], y, 'o', c='k')
    38. #其他绘图设定
    39. ax2.legend(loc="best")
    40. ax2.set_xlabel("Input feature")
    41. ax2.set_title("Result after discretization")
    42. plt.tight_layout()
    43. plt.show()

    箱子数如何影响模型的结果

    1. enc = KBinsDiscretizer(n_bins=5,encode="onehot")
    2. X_binned = enc.fit_transform(X)
    3. line_binned = enc.transform(line)
    4. fig, ax2 = plt.subplots(1,figsize=(5,4))
    5. LinearR_ = LinearRegression().fit(X_binned, y)
    6. print(LinearR_.score(line_binned,np.sin(line)))
    7. TreeR_ = DecisionTreeRegressor(random_state=0).fit(X_binned, y)
    8. ax2.plot(line #横坐标
    9. , LinearR_.predict(line_binned) #分箱后的特征矩阵的结果
    10. , linewidth=2
    11. , color='green'
    12. , linestyle='-'
    13. , label='linear regression')
    14. ax2.plot(line, TreeR_.predict(line_binned), linewidth=2, color='red',
    15. linestyle=':', label='decision tree')
    16. ax2.vlines(enc.bin_edges_[0], *plt.gca().get_ylim(), linewidth=1, alpha=.2)
    17. ax2.plot(X[:, 0], y, 'o', c='k')
    18. ax2.legend(loc="best")
    19. ax2.set_xlabel("Input feature")
    20. ax2.set_title("Result after discretization")
    21. plt.tight_layout()
    22. plt.show()

    如何选取最优的箱数

    1. from sklearn.model_selection import cross_val_score as CVS
    2. import numpy as np
    3. pred,score,var = [], [], []
    4. binsrange = [2,5,10,15,20,30]
    5. for i in binsrange:
    6. #实例化分箱类
    7. enc = KBinsDiscretizer(n_bins=i,encode="onehot")
    8. #转换数据
    9. X_binned = enc.fit_transform(X)
    10. line_binned = enc.transform(line)
    11. #建立模型
    12. LinearR_ = LinearRegression()
    13. #全数据集上的交叉验证
    14. cvresult = CVS(LinearR_,X_binned,y,cv=5)
    15. score.append(cvresult.mean())
    16. var.append(cvresult.var())
    17. #测试数据集上的打分结果
    18. pred.append(LinearR_.fit(X_binned,y).score(line_binned,np.sin(line)))
    19. #绘制图像
    20. plt.figure(figsize=(6,5))
    21. plt.plot(binsrange,pred,c="orange",label="test")
    22. plt.plot(binsrange,score,c="k",label="full data")
    23. plt.plot(binsrange,score+np.array(var)*0.5,c="red",linestyle="--",label = "var")
    24. plt.plot(binsrange,score-np.array(var)*0.5,c="red",linestyle="--")
    25. plt.legend()
    26. plt.show()

    多项式回归PolynomialFeatures

    用于解决”线性回归只能处理线性数据“问题的手段,就是使用多项式回归对线性回归 进行改进

    1. from sklearn.preprocessing import PolynomialFeatures
    2. import numpy as np
    3. #如果原始数据是一维的
    4. X = np.arange(1,4).reshape(-1,1)
    5. X
    6. #二次多项式,参数degree控制多项式的次方
    7. poly = PolynomialFeatures(degree=2)
    8. #接口transform直接调用
    9. X_ = poly.fit_transform(X)
    10. X_
    11. X_.shape
    12. #三次多项式
    13. PolynomialFeatures(degree=3).fit_transform(X)

     

    多项式回归处理非线性问题

    1. from sklearn.preprocessing import PolynomialFeatures as PF
    2. from sklearn.linear_model import LinearRegression
    3. import numpy as np
    4. rnd = np.random.RandomState(42) #设置随机数种子
    5. X = rnd.uniform(-3, 3, size=100)
    6. y = np.sin(X) + rnd.normal(size=len(X)) / 3
    7. #将X升维,准备好放入sklearn中
    8. X = X.reshape(-1,1)
    9. #创建测试数据,均匀分布在训练集X的取值范围内的一千个点
    10. line = np.linspace(-3, 3, 1000, endpoint=False).reshape(-1, 1)
    11. #原始特征矩阵的拟合结果
    12. LinearR = LinearRegr
    13. ession().fit(X, y)
    14. #对训练数据的拟合
    15. LinearR.score(X,y)
    16. #对测试数据的拟合
    17. LinearR.score(line,np.sin(line))
    18. #多项式拟合,设定高次项
    19. d=5
    20. #进行高此项转换
    21. poly = PF(degree=d)
    22. X_ = poly.fit_transform(X)
    23. line_ = PF(degree=d).fit_transform(line)
    24. #训练数据的拟合
    25. LinearR_ = LinearRegression().fit(X_, y)
    26. LinearR_.score(X_,y)
    27. #测试数据的拟合
    28. LinearR_.score(line_,np.sin(line))
    29. import matplotlib.pyplot as plt
    30. d=5
    31. #和上面展示一致的建模流程
    32. LinearR = LinearRegression().fit(X, y)
    33. X_ = PF(degree=d).fit_transform(X)
    34. LinearR_ = LinearRegression().fit(X_, y)
    35. line = np.linspace(-3, 3, 1000, endpoint=False).reshape(-1, 1)
    36. line_ = PF(degree=d).fit_transform(line)
    37. #放置画布
    38. fig, ax1 = plt.subplots(1)
    39. #将测试数据带入predict接口,获得模型的拟合效果并进行绘制
    40. ax1.plot(line, LinearR.predict(line), linewidth=2, color='green'
    41. ,label="linear regression")
    42. ax1.plot(line, LinearR_.predict(line_), linewidth=2, color='red'
    43. ,label="Polynomial regression")
    44. #将原数据上的拟合绘制在图像上
    45. ax1.plot(X[:, 0], y, 'o', c='k')
    46. #其他图形选项
    47. ax1.legend(loc="best")
    48. ax1.set_ylabel("Regression output")
    49. ax1.set_xlabel("Input feature")
    50. ax1.set_title("Linear Regression ordinary vs poly")
    51. plt.tight_layout()
    52. plt.show()
    53. #来一起鼓掌,感叹多项式回归的神奇
    54. #随后可以试试看较低和较高的次方会发生什么变化
    55. #d=2
    56. #d=20

    多项式回归的可解释性

    1. import numpy as np
    2. from sklearn.preprocessing import PolynomialFeatures
    3. from sklearn.linear_model import LinearRegression
    4. X = np.arange(9).reshape(3, 3)
    5. X
    6. poly = PolynomialFeatures(degree=5).fit(X)
    7. #重要接口get_feature_names
    8. poly.get_feature_names()
    9. from sklearn.datasets import fetch_california_housing as fch
    10. import pandas as pd
    11. housevalue = fch()
    12. X = pd.DataFrame(housevalue.data)
    13. y = housevalue.target
    14. housevalue.feature_names
    15. X.columns = ["住户收入中位数","房屋使用年代中位数","平均房间数目"
    16. ,"平均卧室数目","街区人口","平均入住率","街区的纬度","街区的经度"]
    17. poly = PolynomialFeatures(degree=2).fit(X,y)
    18. poly.get_feature_names(X.columns)
    19. X_ = poly.transform(X)
    20. #在这之后,我们依然可以直接建立模型,然后使用线性回归的coef_属性来查看什么特征对标签的影响最大
    21. reg = LinearRegression().fit(X_,y)
    22. coef = reg.coef_
    23. [*zip(poly.get_feature_names(X.columns),reg.coef_)]
    24. #放到dataframe中进行排序
    25. coeff = pd.DataFrame([poly.get_feature_names(X.columns),reg.coef_.tolist()]).T
    26. coeff.columns = ["feature","coef"]
    27. coeff.sort_values(by="coef")
    28. #顺便可以查看一下多项式变化之后,模型的拟合效果如何了
    29. poly = PolynomialFeatures(degree=4).fit(X,y)
    30. X_ = poly.transform(X)
    31. reg = LinearRegression().fit(X,y)
    32. reg.score(X,y)
    33. from time import time
    34. time0 = time()
    35. reg_ = LinearRegression().fit(X_,y)
    36. print("R2:{}".format(reg_.score(X_,y)))
    37. print("time:{}".format(time()-time0))
    38. #假设使用其他模型?
    39. from sklearn.ensemble import RandomForestRegressor as RFR
    40. time0 = time()
    41. print("R2:{}".format(RFR(n_estimators=100).fit(X,y).score(X,y)))
    42. print("time:{}".format(time()-time0))

    线性还是非线性模型?

    多项式回归通常被认为是非线性模型,但广义上它是一种特殊的线性模型,它能够帮助我们处理非线性数 据,是线性回归的一种进化。

    线性回归进行多项式变化后被称为多项式回归,但这并不代表多项式变化只能够与线性回 归连用。

  • 相关阅读:
    VD6283TX环境光传感器驱动开发(3)----测试闪烁频率代码
    使用自定义委托来调用Lua中的多返回值和长参数类型函数
    FP为什么更适合做独立站?自己掌握话语权才是王道
    基于ElasticSearch存储海量AIS数据:AIS数据索引机制篇
    前端知识粉碎机
    PHP数组转json和php的json转数组
    微信键盘悄悄上线
    交换机和路由器基础
    java jdk8新特性学习
    ElastaticSearch -- es之Filters aggregation 先过滤再聚合
  • 原文地址:https://blog.csdn.net/weixin_44267765/article/details/126950920