机器学习系列(十三)——多元线性回归及knn做回归
多元线性回归理论
相比于样本只有一个特征值的简单线性回归,多元线性回归往往更能反映研究对象的真实情况。多元线性回归样本有多个特征,需要研究的是这多个特征与最终结果的关系。
多元线性回归
如上图所示,相比于简单线性回归,这里的变量x不再是单个特征,而是一个向量,代表多个特征。
于是y与x的模型表达式可以为:
对于一个样本的预测值则为:
这与简单线性回归是非常一致的,区别只是特征从1个变成了n个。在求解参数时也和简单线性回归一致,求得的参数要使得:
尽可能小。
令
于是对一组样本的预测结果向量为:
同样可以根据高等数学的知识经过简单推导得到最优的,这里不再给出过程,直接给出最优结果(多元线性回归的正规方程解Normal Equation):
通过监督学习的数据可以很轻易得到这个解,机器学习能直接得到数学解的模型是非常少的,而且可以不对数据作归一化处理。但这种方式有一个问题,就是时间复杂度是,尽管可以优化到,但时间消耗仍然是比较多的。
实现自己的多元线性回归
在play_Ml中新建LinearRegression.py,代码如下:
import numpy as np
from .metrics import r2_score
class LinearRegression:
def __init__(self):
self.coef_ = None
self.interception_ =None
self._theta = None
def fit_normal(self,X_train,y_train):
assert X_train.shape[0] == y_train.shape[0],"must be equal!"
X_b = np.hstack([np.ones((len(X_train),1)),X_train])
self._theta = np.linalg.inv(X_b.T.dot(X_b)).dot(X_b.T).dot(y_train)
self.interception_ = self._theta[0]
self.coef_ = self._theta[1:]
return self
def predict(self,X_predict):
assert self.interception_ is not None and self.coef_ is not None,"must fit first!"
assert X_predict.shape[1] == len(self.coef_),"feature must be the same!"
X_b = np.hstack([np.ones((len(X_predict),1)),X_predict])
return X_b.dot(self._theta)
def score(self,X_test,y_test):
y_predict = self.predict(X_test)
return r2_score(y_test,y_predict)
def __repr__(self):
return "LinearRegression()"
在bsoton房产数据上测试模型,使用boston房产数据的13个特征:
'''使用boston房产数据的所有特征'''
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
boston = datasets.load_boston()
X = boston.data
y = boston.target
X = X[y < 50.0]
y = y[y < 50.0]
'''使用自己的模型'''
from play_Ml.model_selection import train_test_split
X_train,X_test,y_train,y_test = train_test_split(X,y,seed=666)
from play_Ml.LinearRegression import LinearRegression
reg = LinearRegression()
reg.fit_normal(X_train,y_train)
'''查看求得的系数与截距'''
reg.coef_
reg.interception_
'''R方指标'''
reg.score(X_test,y_test)
注:上面的fit_normal方式是我们自己写的基于正规化方程的,sklearn中的fit方式并不是正规化方程方式
coef_inter可以看到,多元线性回归在该数据集上R方为0.8,还是不错的。这也间接反映了如果特征能很好反映与预测之间的关系的话,使用更多特征,会有更好的预测效果。
sklearn中的回归
sklearn中的线性回归
仍然使用和上面相同的数据集:
'''使用boston房产数据的所有特征'''
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
boston = datasets.load_boston()
X = boston.data
y = boston.target
X = X[y < 50.0]
y = y[y < 50.0]
from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test = train_test_split(X,y,random_state=666)
'''这里如果用上面自己算法的train_test_split,可以在sklearn
中的fit中得到和上面一样的系数和截距结果'''
from sklearn.linear_model import LinearRegression
lin_reg = LinearRegression()
lin_reg.fit(X_train,y_train)
lin_reg.coef_
lin_reg.intercept_
lin_reg.score(X_test,y_test)
结果如下:
resultknn做回归
knn也是可以用来做回归任务的,下面仍然用boston房产数据,进行knn的回归:
from sklearn.neighbors import KNeighborsRegressor
knn_reg = KNeighborsRegressor()
knn_reg.fit(X_train,y_train)
knn_reg.score(X_test,y_test)
score值是0.6,显然效果是不如线性回归的,不过这只是在knn回归默认超参数情况下,下面用网格搜索找出更优秀的超参数:
'''定义搜索参数网格'''
param_grid=[
{
'weights':['uniform'],
'n_neighbors':[i for i in range(1,11)]
},
{
'weights':['distance'],
'n_neighbors':[i for i in range(1,11)],
'p':[i for i in range(1,6)]
}
]
from sklearn.model_selection import GridSearchCV
knn_reg = KNeighborsRegressor()
grid_search = GridSearchCV(knn_reg,param_grid,n_jobs = -1,verbose = 1)
grid_search.fit(X_train,y_train)
结果如下:
knn_Regressorscore值变为0.7,虽然有所提高,但是和线性回归相比还是有些差据。