还有更加特殊的,没有模型的算法,比如最近邻算法
KNN
,这些都是不建模,但是能够直接预测出标签或做出判断的算法。而这些算法,并没有线性非线性之分,单纯的是不建模的算法们。
当我们获取数据时,我们往往希望使用线性模型来对数据进行最初的拟合(线性回归用于回归,逻辑回归用于分类),如果线性模型表现良好,则说明数据本身很可能是线性的或者线性可分的,如果线性模型表现糟糕,那毫无疑问我们会投入决策树,随机森林这些模型的怀抱,就不必浪费时间在线性模型上了。
利用线性回归解决非线性问题
让线性回归在非线性数据上表现提升的核心方法之一是对数据进行分箱,也就是离散化。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.tree import DecisionTreeRegressor
from sklearn.preprocessing import KBinsDiscretizer #分箱
rnd=np.random.RandomState(40)#设置随机数种子
X = rnd.uniform(-3, 3, size=100) #random.uniform,从输入的任意两个整数中取出size个随机数
#生成y的思路:先使用NumPy中的函数生成一个sin函数图像,然后再人为添加噪音
y = np.sin(X) + rnd.normal(size=len(X)) / 3 #random.normal,生成size个服从正态分布的随机数
X = X.reshape(-1, 1)
line = np.linspace(-3, 3, 1000, endpoint=False).reshape(-1, 1)#测试集数据
#分箱操作
enc=KBinsDiscretizer(n_bins=10,#分几个箱子
encode='onehot',#采用哑变量方式做离散化
)
X_binned=enc.fit_transform(X)#之后返回一个稀疏矩阵(m,n_bins),m是样本数量,每一列是一个分好的类别
line_binned = enc.transform(line)
LinearR = LinearRegression().fit(X, y)
TreeR = DecisionTreeRegressor(random_state=0).fit(X, y)
#将两张图像绘制在一起,布置画布
fig, (ax1, ax2) = plt.subplots(ncols=2
, sharey=True #让两张图共享y轴上的刻度
, figsize=(10, 4))
#在图1中布置在原始数据上建模的结果
ax1.plot(line, LinearR.predict(line), linewidth=2, color='green',
label="linear regression")
ax1.plot(line, TreeR.predict(line), linewidth=2, color='red',
label="decision tree")
ax1.plot(X[:, 0], y, 'o', c='k')
ax1.legend(loc="best")
ax1.set_ylabel("Regression output")
ax1.set_xlabel("Input feature")
ax1.set_title("Result before discretization")
#使用分箱数据进行建模
LinearR_ = LinearRegression().fit(X_binned, y)
TreeR_ = DecisionTreeRegressor(random_state=0).fit(X_binned, y)
#进行预测,在图2中布置在分箱数据上进行预测的结果
ax2.plot(line #横坐标
, LinearR_.predict(line_binned) #分箱后的特征矩阵的结果
, linewidth=2
, color='green'
, linestyle='-'
, label='linear regression')
ax2.plot(line, TreeR_.predict(line_binned), linewidth=2, color='red',
linestyle=':', label='decision tree')
#绘制和箱宽一致的竖线,可有可无
ax2.vlines(enc.bin_edges_[0] #x轴
, *plt.gca().get_ylim() #y轴的上限和下限
, linewidth=1
, alpha=.2) #将原始数据分布放置在图像上
ax2.plot(X[:, 0], y, 'o', c='k')
ax2.legend(loc="best")
ax2.set_xlabel("Input feature")
ax2.set_title("Result after discretization")
plt.tight_layout()
plt.show()
多项式回归
除了分箱之外,另一种更普遍的用于解决
”
线性回归只能处理线性数据
“
问题的手段,就是使用多项式回归对线性回归进行改进。这样的手法是机器学习研究者们从支持向量机中获得的:支持向量机通过升维可以将非线性可分数据转化为线性可分,然后使用核函数在低维空间中进行计算,这是一种“
高维呈现,低维解释
”
的思维。那我们为什么不能让线性回归使用类似于升维的转换,将数据由非线性转换为线性,从而为线性回归赋予处理非线性数据的能力呢?
线性模型中的升维工具:
多项式变化
。这是一种通过增加自变量上的次数,而将数据映射到高维空间的方法,只要我们设定一个自变量上的次数(大于1
),就可以相应地获得数据投影在高方的空间中的结果。这种方法可以非常容易地通过sklearn
中的类
PolynomialFeatures
来实现。
一维的转换公式
![](https://img-blog.csdnimg.cn/7479d46870434a34aeebb30337eaf264.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAa29uZ3FpbmcyMw==,size_17,color_FFFFFF,t_70,g_se,x_16)
二维转换公式
![](https://img-blog.csdnimg.cn/a018137716804674a9e2ff027f485fbd.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAa29uZ3FpbmcyMw==,size_20,color_FFFFFF,t_70,g_se,x_16)
当我们进行多项式转换的时候,多项式会产出到最高次数为止的所有低高次项
。比如如果我们规定多项式的次数为2
,多项式就会产出所有次数为
1
和次数为
2
的项反馈给我们,相应的如果我们规定多项式的次数为
n
,则多项式会产出所有从次数为1
到次数为
n
的项。
对比多项式处理前后的回归效果
from sklearn.preprocessing import PolynomialFeatures
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
d=5#多项式维度
rnd=np.random.RandomState(40)#设置随机数种子
X = rnd.uniform(-3, 3, size=100) #random.uniform,从输入的任意两个整数中取出size个随机数
#生成y的思路:先使用NumPy中的函数生成一个sin函数图像,然后再人为添加噪音
y = np.sin(X) + rnd.normal(size=len(X)) / 3 #random.normal,生成size个服从正态分布的随机数
X = X.reshape(-1, 1)
line = np.linspace(-3, 3, 1000, endpoint=False).reshape(-1, 1)#测试集数据
line_=PolynomialFeatures(degree=d).fit_transform(line)
LinearR = LinearRegression().fit(X, y)
X_=PolynomialFeatures(degree=d).fit_transform(X)#对数据进行多项式处理
LinearR_=LinearRegression().fit(X_, y)
#放置画布
fig, ax1 = plt.subplots(1) #将测试数据带入predict接口,获得模型的拟合效果并进行绘制
#多项式处理前
ax1.plot(line, LinearR.predict(line), linewidth=2, color='green'
,label="linear regression")
#多项式处理后 训练时使用多项式数据,预测时也应采用多项式数据
ax1.plot(line, LinearR_.predict(line_), linewidth=2, color='red'
,label="Polynomial regression") #将原数据上的拟合绘制在图像上
ax1.plot(X[:, 0], y, 'o', c='k') #其他图形选项
ax1.legend(loc="best")
ax1.set_ylabel("Regression output")
ax1.set_xlabel("Input feature")
ax1.set_title("Linear Regression ordinary vs poly")
plt.tight_layout()
plt.show()
#随后可以试试看较低和较高的次方会发生什么变化
线性模型
狭义线性模型:自变量上不能有高此项,自变量与标签之间不能存在非线性关系。
广义线性模型:只要标签与模型拟合出的
参数之间的关系是线性的
,模型就是线性的。这是说,只要生成的一系列之间没有相乘或者相除的关系,我们就认为模型是线性的。
就多项式回归本身的性质来说,如果我们考虑狭义线性模型的定义,那它肯定是一种非线性模型没有错
——
否则如何能够处理非线性数据呢,并且在统计学中我们认为,特征之间若存在精确相关关系或高度相关关系,线性模型的估计就会被“
扭曲
“
,从而失真或难以估计准确。多项式正是利用线性回归的这种
”
扭曲
“
,为线性模型赋予了处理非线性数据的能力。但如果我们考虑广义线性模型的定义,多项式回归就是一种线性模型,毕竟它的系数之间也没有相乘或者相除。
总结一下,
多项式回归通常被认为是非线性模型,但广义上它是一种特殊的线性模型
,它能够帮助我们处理非线性数
据,是线性回归的一种进化。