标准的线性回归,无法考虑输入参数features之间的关系
毕竟模型很简单
但是有时候我们需要考虑,features之间的相互作用关系。 这时候多项式扩展就是一个很好的选择。
简单的来说:
比如说我们目前有一群二维的输入样本 [a,b] [ a , b ] , 这个群二维的输入样本去训练模型,发现不管在训练集还是在测试集中的R^2 值都不高。 这时候,我们可以考虑将二维样本空间映射到跟高维度例如: [1,a,b,a2,ab,b2] [ 1 , a , b , a 2 , a b , b 2 ] 或者更高维度。来体现features和features之间的关系。
其调用的方式为
poly = PolynomialFeatures(degree =integer,interaction_only=False,include_bias=True)
degree: 多项式的最高次
interaction_only: 布尔值,默认false , 如果为true, 就按照字面的意思,只有featrues之间相互作用的项会被拓展。
简单的说,如果是true就没有 [a2,b2,a3,b3,ab2] [ a 2 , b 2 , a 3 , b 3 , a b 2 ] 这些项
include_bias: 布尔值,默认为True, 如果为True则包含0阶项作为截距
主要注意的是,越高阶的degree, 输入的维度是按照指数增长的。过高的degree会导致过拟合
powers_: array, shape (输出的featrues数, 输入的features数)
每个powers_[i,j] 代表第i项输出相中,j项的阶数
n_input_features_: int 总的输入的features数目
n_output_features_: int 总的输出的features数目
fit(X) 计算拓展后的features的数量
fit_transform(X[,y]) 基于数据给出最好的扩展规则,再根据规则拓展features
get_feature_names(): 获得字符串,代表features的名称,默认“x0”, “x1”, … “xn_features”
get_params(deep=True): 布尔型,获得estimator的设置参数
transfrom(X): 基于已有的规则将features拓展
下面举个例子来说明多项式拓展API的具体实现过程
import sklearn
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import PolynomialFeatures
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
## 设置字符集,防止中文乱码
mpl.rcParams['font.sans-serif']=[u'simHei']
mpl.rcParams['axes.unicode_minus']=False
# 定义目标函数
def l_model(x):
params = np.arange(1,x.shape[-1]+3)
y = np.sum(params[:-2]*x)+np.random.randn(1)*0.1+5*params[-2]*x[0]*x[1]+5*params[-1]*x[1]*x[2]
return y
# 定义数据集
x = pd.DataFrame(np.random.rand(500,6))
y = x.apply(lambda x_rows:pd.Series(l_model(x_rows)),axis=1)
# 划分训练集和测试集
x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.3,random_state=2)
# 数据标准化
ss = StandardScaler()
x_train_s = ss.fit_transform(x_train)
x_test_s = ss.transform(x_test)
# 多项式拓展
poly = PolynomialFeatures(degree=2,interaction_only=True,include_bias=True)
x_train_poly_s = poly.fit_transform(x_train_s)
x_test_poly_s = poly.transform(x_test_s)
# 训练模型
lr1 = LinearRegression()
lr2 = LinearRegression()
lr1.fit(x_train_s,y_train)
lr2.fit(x_train_poly_s,y_train)
print(lr1.coef_)
print(lr1.intercept_)
print(lr2.coef_)
print(lr2.intercept_)
"""
[[ 5.41234606 12.23505518 6.78190388 0.79008398 1.38341645
1.65798645]]
[ 28.83640761]
[[ 0.00000000e+00 5.08851808e+00 1.23698745e+01 6.51171800e+00
1.11938001e+00 1.46909906e+00 1.63462795e+00 3.05655327e+00
4.57365090e-03 -1.15502895e-02 1.36441821e-03 -3.21027734e-03
3.59911422e+00 -1.04410449e-03 -4.69277303e-03 -4.14113664e-04
1.04280565e-03 -7.76639367e-03 2.24746104e-03 -3.29928656e-03
6.11803772e-05 -1.27460237e-02]]
[ 29.00390507]
"""
# 预测
y_predict_1=lr1.predict(x_test_s)
y_predict_2=lr2.predict(x_test_poly_s)
print(lr1.score(x_test_s,y_test))
print(lr2.score(x_test_poly_s,y_test))
"""
0.905937565673
0.999934738653
"""
#将拓展后的和拓展期的数据做作图对比对比
plt.figure(facecolor='w')#建一个画布,facecolor是背景色
t=np.arange(len(x_test_s))
plt.subplot(2,1,1)
plt.plot(t, y_test, 'r-', linewidth=1.5, label='真实值')
plt.plot(t, y_predict_1, 'g-', linewidth=1, label='原先参数的预测值')
plt.legend(loc = 'upper left')#显示图例,设置图例的位置
plt.subplot(2,1,2)
plt.plot(t, y_test, 'r-', linewidth=1.5, label='真实值')
plt.plot(t, y_predict_2, 'g-', linewidth=1, label='多项式拓展后的预测值')
plt.legend(loc = 'upper left')#显示图例,设置图例的位置
plt.suptitle("线性回归多项式拓展预测真实值之间的关系对比", fontsize=20)
plt.grid(b=True)#加网格
plt.show()
可以看出来,提高的效果还是非常明显的