1、基本概念
之前的简单线性回归针对的是样本只有一个特征值的情况,当我们的样本中包含了多个特征值的时候,我们就引入了多元线性回归的问题。
我们数据有多个特征、有多少个维度,相应的每一个特征前都有一个系数,这里用theta0、1、2来表示,与此同时,整个直线有个截距,我们先用theta0来表示,这里的theta0相当于之前简单线性回归的b,theta1表示之前的系数a(或者w),在多元线性回归中,相应我们要求n+1个参数,这里就用theta0-n来表示(上面第一张图片的w)
这里其实和简单线性回归很类似,区别只是由一个特征拓展到了现在有n个特征,所以求解思路其实和简单线性回归一致
把theta0-n的值,整理成一个向量,我们用列向量的形式表示
为了使表达式一致,我们在第一项theta0后面也乘上了一个值X0i(本身没有这个X0i这一个特征,为了式子在推导中更方便,虚构了一个X0i横等于1)
注意这里的Xi是个行向量,这个X是一个矩阵,每一行代表一个样本,每一列代表一个特征,Xi代表从X这个矩阵当中抽出一行。
最后我们可以把第i行的样本预测值简单的表示出来
进而我们把式子进行推广,推广到所有的样本上
在这个版本中,将X表示为有m行,n列的矩阵。
Xb表示为有m行,n+1列的矩阵(多了一列第一列恒等于1的一列)
这里的y_hat是一个向量(列向量,一共有m个元素,每个元素对应的是原来的X中经过theta后,得到的预测值),这个向量就是使用多元线性回归当中,根据theta这个参数对每一个样本进行预测的结果。
这里的推导过程就不多说了,对损失函数求导使其等于0,得到theta的值,这里直接展示推导的结果
画个小重点,在上面的所有概念说完之后,总结一下一个theta
对于样本来说,我们一共有n个维度,theta0相当于是截距(之前我们理解的b,theta1-n是对应原来样本特征Xi的系数)
2、代码实现
这里的解决多元线性回归的问题也能解决一元线性回归的问题。
(1)X_b
# np.hstack():在水平方向上平铺,就是在横向上多加一列
# np.ones(矩阵大小, 列数)是增加一列恒为1的一列
X_b = np.hstack([np.ones((len(X_train), 1)), X_train])
(2)theta
# X_b.T是X_b的转置,.dot是点乘,np.linalg.inv是求逆
self._theta = np.linalg.inv(X_b.T.dot(X_b)).dot(X_b.T).dot(y_train)
(3)系数和截距
self.interception_ = self._theta[0] # 截距
self.coef_ = self._theta[1:] # 系数
(4)预测结果
# 预测过程
def predict(self, X_predict):
# 给定待预测数据集X_predict,返回表示X_predict的结果向量
X_b = np.hstack([np.ones((len(X_predict), 1)), X_predict])
return X_b.dot(self._theta)
(5)精确度计算
'''
确定精度,评价多元线性回归的结果
'''
def score(self, X_test, y_test):
# 根据测试数据集X_test 和y_test 确定当前模型的准确度
y_predict = self.predict(X_test)
return r2_score(y_test, y_predict) # r2_score求真值y_test和预测值y_predict的r方
(6)总体代码
# 多元线性回归问题;解析解+梯度下降法(也能解决一元线性回归问题)
import numpy as np
from sklearn import datasets
from sklearn.metrics import r2_score
from sklearn.model_selection import train_test_split
class LinearRegression:
def __init__(self):
# 初始化Linear Regression模型
self.coef_ = None # 系数,对应theta1-n,对应的向量
self.interception_ = None # 截距,对应theta0
self._theta = None # 定义私有变量,整体计算的theta
'''
解析解
'''
# 正规化方程
# 训练过程(解析解)
def fit_normal(self, X_train, y_train): # X_train和y_train都是矩阵
# 根据训练数据集X_train, y_ .train训练Linear Regression模型
# X_train的样本数量和y_train的标记数量应该是一致的
# 使用shape[0]读取矩阵第一维度的长度,在这里就是列数
assert X_train.shape[0] == y_train.shape[0], \
"the size of x_ .train must be equal to the size of y_ train"
# np.hstack():在水平方向上平铺,就是在横向上多加一列
# np.ones(矩阵大小, 列数)是增加一列恒为1的一列
# 得到X_b
X_b = np.hstack([np.ones((len(X_train), 1)), X_train])
# X_b.T是X_b的转置,.dot是点乘,np.linalg.inv是求逆
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):
# 给定待预测数据集X_predict,返回表示X_predict的结果向量
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):
# 根据测试数据集X_test 和y_test 确定当前模型的准确度
y_predict = self.predict(X_test)
return r2_score(y_test, y_predict) # r2_score求真值y_test和预测值y_predict的r方
'''
显示属性
'''
def __repr__(self):
return "LinearRegression()"
# 加载波士顿房价数据集,并划分为X_train,y_train
# 波士顿房价
boston = datasets.load_boston()
# X_train = boston.data
# y_train = boston.target
X = boston.data
y = boston.target
X = X[y < 50.0]
y = y[y < 50.0]
# 分出测试集合训练集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25)
'''
实例化(数学解解法)
'''
reg = LinearRegression()
# 进行训练
reg.fit_normal(X_train, y_train) # LinearRegression()
# 预测r方值
print('预测精确度', reg.score(X_test, y_test))
# 截距
print('数学解系数reg.coef_', reg.coef_)
print('数学解截距reg.interception_', reg.interception_)
print('数学解预测值', reg.predict(X_test))
print('y_test测试值', y_test)
这里用到了sklearn的Boston波士顿房价数据集,简介可以参考波士顿房价数据集
对数据集进行训练后,可以得到我们需要的精确度、系数、截距。也可以对比我们的预测值和真实值