监督式学习算法的任务是拟合多个特征与标签的关系,在实际应用中,所收集的数据中,所有的特征可能并不是都与标签有关联。模型中如果包含与标签无关联的特征,不仅会增加数据规模和计算量,还会影响模型对标签的预测效果。因此特征选择是监督式学习算法的一个重要组成部分。
逐步回归是一个贪心算法。它的运行效率较高,但也因为其是贪心算法,有时会做出次优的最优选择。
向前逐步回归算法是最简单的一种特征选择方法,大概做法为:在向前逐步回归算法的初始阶段,先选定第一个特征,然后重复执行以下几个步骤----首先计算只使用当前选定的特征的线性回归的均方误差,然后逐一引入尚未选取的特征,选择能最大程度降低均方误差的一个特征,判断该特征是否在统计意义上显著地降低均方误差,如果是,就将该特征加入模型。重复循环上述过程,直至没有能够被继续选中的特征为止。
在向前逐步回归算法中,采用F检验来判断均方误差的减小是否具有统计显著性。
给定两个均方误差mse1 和mse2,设mse1>mse2。用F检验计算mse1>mse2的置信度p。
置信度p是在重新采样训练数据并对其重复向前逐步选择算法时再次出现mse1>mse2的概率。
如果置信度p>95%,则认为mse1>mse2这一结论具有统计显著性。
import numpy as np
from scipy.stats import f
# 向前逐步选择
class StepwiseRegression():
def fit(self,X,y):
return np.linalg.inv(X.T.dot(X)).dot(X.T).dot(y)
# 计算均方误差
def compute_mse(self,X,y):
w = self.fit(X,y)
r = y - X.dot(w)
return r.T.dot(r)
# 判断引入新特征是否有效降低均方误差
def f_tesy(self,mse_A,mse_min,m):
if mse_min > mse_A:
return False
F = mse_A/mse_min
p_value = f.cdf(F,m,m)
return p_value>0.95
# 特征选择
def forward_selection(self,X,y):
m, n = X.shape
# 记录特征列数,A为已经选择的特征,C为备选特征
A, C =[0],[i for i in range(1,n)]
while len(C)>0:
# 取训练数据中的A包含的特征
MSE_A = self.compute_mse(X[:,A],y)
MSE_min = float("inf")
j_min = -1
#遍历未选择的特征,保留均方误差最小值以及代表的特征列
for j in C:
MSE_j = self.compute_mse(X[:,A+[j]],y)
if MSE_j < MSE_min:
MSE_min ,j_min = MSE_j,j
if self.f_tesy(MSE_A,MSE_min,m):
A.append(j_min)
C.remove(j_min)
else:
break
self.w = self.fit(X[:,A],y)
self.A = A
# 计算标签值
def predict(self,X):
return X[:,self.A].dot(self.w)
# 应用向前逐步回归算法进行特征选择
import numpy as np
from sklearn.preprocessing import PolynomialFeatures
from machine_learning_lib_stepwise_regression import StepwiseRegression
import matplotlib.pyplot as plt
from machine_learning_lib_stepwise_regressiontwo import Stepwiseregression as Step
# 构造数据
def generate_sample(m):
X = 2 * (np.random.rand(m,1)-0.5)
y = X + np.random.normal(0,0.3,(m,1))
return X,y
np.random.seed(100)
# 生成10个点
X,y = generate_sample(10)
plt.scatter(X,y)
poly = PolynomialFeatures(degree=10)
X_poly = poly.fit_transform(X)
model = StepwiseRegression()
model.forward_selection(X_poly,y)
y_pred = X_poly[:,[0,1]].dot(model.w)
plt.plot(X,y_pred)
print(model.A,model.w)
plt.show()
为了直观的观察特征选择的效果,训练数据是通过随机函数产生的,并对其多项式化,产生11个特征,标签以y=x,赋予一定程度的浮动人为产生。
该训练数据如果不进行特征的选择,直接对全部特征进行线性回归,将产生过度拟合的线性回归模型。
特征选择能有效的剔除与标签无关联的特征,避免无关特征对模型的影响,导致过度的拟合,但向前逐步回归法是一个贪心算法,在算法的开始,选择了第一个特征为起始,但第一个特征与标签的关系并未进行判断,若第一个特征与标签无关联,则将会产生次优解。
向后逐步回归算法可以有效解决向前逐步回归算法的影响,向后逐步回归在起始的时候选取全部特征,之后逐一 剔除不能有效降低均方误差的特征。但是向后逐步回归算法也是一个贪心算法,依然可能产生次优解,并且当前选定的特征已经过度拟合,从而具有较小的均方误差,向后逐步回归算法将无法继续从模型中剔除与标签无关的特征。
向前逐步回归算法与向后逐步回归算法的合并使用。
向前逐步回归算法起始选择随机,多次运行,选择最优情况。