线性回归python实现详解(附公式推导)

article/2025/8/24 19:11:05

目录

    • 1线性回归
      • 1.1简单线性回归
      • 1.2 多元线性回归的正规方程解
      • 1.3 使用梯度下降求解多元线性回归
      • 1.4 sklearn中的线性回归模型

1线性回归

1.1简单线性回归

在简单线性回归中,输入x只有一个特征,通过调整a和b的参数值,来拟合从x到y的线性关系。下图为进行拟合所需要优化的目标,也即是MES(Mean Squared Error),只不过省略了平均的部分(除以m)。

对于简单线性回归,只有两个参数a和b,通过对MSE优化目标求导后取极值点极值(最小二乘法),即可求得最优a和b如下,所以在训练简单线性回归模型时,也只需要根据数据求解这两个参数值即可。

下面使用波士顿房价数据集中,索引为5(第6个特征)的特征RM (average number of rooms per dwelling:每个住宅的平均房间数)来进行简单线性回归。其中使用的评价指标为:

以及R方指标。这里R方指标一般情况下可以将对模型的评价压缩到[0,1]之间(也可能是负数),值越接近1效果越好。在式子分子分母中的两项都可以认作在算均方误差,只不过分子使用我们训练的线性回归模型的输出,分母则使用真实标签数据的平均值来做均方误差,表示对每个样本,都是一个固定值瞎猜结果,其值等价于实际标签值的方差。通过模型的均方误差和瞎猜产生的误差做对比,就可以将评价指标限定在[0,1](如果模型比瞎猜还差就会成为负数)。

# 以sklearn的形式对simple linear regression 算法进行封装
import numpy as np
import sklearn.datasets as datasets
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
from sklearn.metrics import mean_squared_error,mean_absolute_error
np.random.seed(123)class SimpleLinearRegression():def __init__(self):"""initialize model parameters"""self.a_=Noneself.b_=Nonedef fit(self,x_train,y_train):"""training model parametersParameters----------x_train:train x ,shape:data [N,]y_train:train y ,shape:data [N,]"""assert (x_train.ndim==1 and y_train.ndim==1),\"""Simple Linear Regression model can only solve single feature training data"""assert len(x_train)==len(y_train),\"""the size of x_train must be equal to y_train"""x_mean=np.mean(x_train)y_mean=np.mean(y_train)self.a_=np.vdot((x_train-x_mean),(y_train-y_mean))/np.vdot((x_train-x_mean),(x_train-x_mean))self.b_=y_mean-self.a_*x_meandef predict(self,input_x):"""make predictions based on a batch of dataParameters----------input_x:shape->[N,]"""assert input_x.ndim==1 ,\"""Simple Linear Regression model can only solve single feature data"""return np.array([self.pred_(x) for x in input_x])def pred_(self,x):"""give a prediction based on single input x"""return self.a_*x+self.b_def __repr__(self):return "SimpleLinearRegressionModel"if __name__ == '__main__':boston_data = datasets.load_boston()print(boston_data['DESCR'])x = boston_data['data'][:, 5]  # total x data (506,)y = boston_data['target']  # total y data (506,)# keep data with target value less than 50.x = x[y < 50]  # total x data (490,)y = y[y < 50]  # total x data (490,)plt.scatter(x, y)plt.show()# train size:(343,) test size:(147,)x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3)regs = SimpleLinearRegression()regs.fit(x_train, y_train)y_hat = regs.predict(x_test)rmse = np.sqrt(np.sum((y_hat - y_test) ** 2) / len(x_test))mse = mean_squared_error(y_test, y_hat)mae = mean_absolute_error(y_test, y_hat)# noticeR_squared_Error = 1 - mse / np.var(y_test)print('mean squared error:%.2f' % (mse))print('root mean squared error:%.2f' % (rmse))print('mean absolute error:%.2f' % (mae))print('R squared Error:%.2f' % (R_squared_Error))a = regs.a_b = regs.b_x_plot = np.linspace(4, 8, 50)y_plot = x_plot * a + bplt.scatter(x, y)plt.plot(x_plot, y_plot, color='red')plt.show()

输出结果:

mean squared error:26.74
root mean squared error:5.17
mean absolute error:3.85
R squared Error:0.50

数据的可视化:

1.2 多元线性回归的正规方程解

多元线性回归中,单个x的样本拥有了多个特征,也就是上图中带下标的x。
其结构可以用向量乘法表示出来:
为了便于计算,一般会将x增加一个为1的特征,方便与截距bias计算。

而多元线性回归的优化目标与简单线性回归一致。

通过矩阵求导计算,可以得到方程解,但求解的时间复杂度很高。

下面使用正规方程解的形式,来对波士顿房价的所有特征做多元线性回归。

from math import sqrt
import numpy as np
#from PlayML.metrics import r2_score
from sklearn.model_selection import train_test_split
import sklearn.datasets as datasets
#from PlayML.metrics import  root_mean_squared_error
np.random.seed(123)def mean_squared_error(y_true, y_predict):"""计算y_true和y_predict之间的MSE"""assert len(y_true) == len(y_predict), \"the size of y_true must be equal to the size of y_predict"return np.sum((y_true - y_predict)**2) / len(y_true)
def r2_score(y_true, y_predict):"""计算y_true和y_predict之间的R Square"""return 1 - mean_squared_error(y_true, y_predict)/np.var(y_true)def root_mean_squared_error(y_true, y_predict):"""计算y_true和y_predict之间的RMSE"""return sqrt(mean_squared_error(y_true, y_predict))class LinearRegression():def __init__(self):self.coef_=None # coeffientself.intercept_=None # interceptionself.theta_=Nonedef fit_normal(self, x_train, y_train):"""use normal equation solution for multiple linear regresion as model parametersParameters----------theta=(X^T * X)^-1 * X^T * y"""assert x_train.shape[0] == y_train.shape[0],\"""size of the x_train must be equal to y_train """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) # (featere,1)self.coef_=self.theta_[1:]self.intercept_=self.theta_[0]def predict(self,x_pred):"""给定待预测数据集X_predict,返回表示X_predict的结果向量"""assert self.intercept_ is not None and self.coef_ is not None, \"must fit before predict!"assert x_pred.shape[1] == len(self.coef_), \"the feature number of X_predict must be equal to X_train"X_b=np.hstack([np.ones((len(x_pred),1)),x_pred])return X_b.dot(self.theta_)def score(self,x_test,y_test):"""Calculate evaluating indicator socreParameters---------x_test:x test datay_test:true label y for x test data"""y_pred=self.predict(x_test)return r2_score(y_test,y_pred)def __repr__(self):return "LinearRegression"if __name__ == '__main__':# use boston house price dataset for testboston_data = datasets.load_boston()x = boston_data['data']  # total x data (506,)y = boston_data['target']  # total y data (506,)# keep data with target value less than 50.x = x[y < 50]  # total x data (490,)y = y[y < 50]  # total x data (490,)# train size:(343,) test size:(147,)x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3,random_state=123)regs = LinearRegression()regs.fit_normal(x_train, y_train)# calc errorscore=regs.score(x_test,y_test)rmse=root_mean_squared_error(y_test,regs.predict(x_test))print('R squared error:%.2f' % (score))print('Root mean squared error:%.2f' % (rmse))

输出结果:

R squared error:0.79
Root mean squared error:3.36

1.3 使用梯度下降求解多元线性回归

使用梯度下降的方法,在数据比较多的情况下会比方程解快很多。代码也不难,只是关于参数梯度的向量化推导有一点复杂,还有就是训练前要先进行数据标准化。
损失函数与之前相同,还是使用MSE损失。

为了让梯度为列向量,再做依次转置,得到最终的结果。

import numpy as np
from math import sqrt
import sklearn.datasets as datasets
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScalerdef accuracy_score(y_true, y_predict):"""计算y_true和y_predict之间的准确率"""assert len(y_true) == len(y_predict), \"the size of y_true must be equal to the size of y_predict"return np.sum(y_true == y_predict) / len(y_true)def mean_squared_error(y_true, y_predict):"""计算y_true和y_predict之间的MSE"""assert len(y_true) == len(y_predict), \"the size of y_true must be equal to the size of y_predict"return np.sum((y_true - y_predict)**2) / len(y_true)def root_mean_squared_error(y_true, y_predict):"""计算y_true和y_predict之间的RMSE"""return sqrt(mean_squared_error(y_true, y_predict))def mean_absolute_error(y_true, y_predict):"""计算y_true和y_predict之间的MAE"""assert len(y_true) == len(y_predict), \"the size of y_true must be equal to the size of y_predict"return np.sum(np.absolute(y_true - y_predict)) / len(y_true)def r2_score(y_true, y_predict):"""计算y_true和y_predict之间的R Square"""return 1 - mean_squared_error(y_true, y_predict)/np.var(y_true)class LinearRegression:def __init__(self):"""初始化Linear Regression模型"""self.coef_ = Noneself.intercept_ = Noneself._theta = Nonedef fit_normal(self, X_train, y_train):"""根据训练数据集X_train, y_train训练Linear Regression模型"""assert X_train.shape[0] == y_train.shape[0], \"the size of X_train must be equal to the size of y_train"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.intercept_ = self._theta[0]self.coef_ = self._theta[1:]return selfdef fit_gd(self, X_train, y_train, eta=0.01, n_iters=1e4):"""根据训练数据集X_train, y_train, 使用梯度下降法训练Linear Regression模型"""assert X_train.shape[0] == y_train.shape[0], \"the size of X_train must be equal to the size of y_train"def J(theta, X_b, y):try:return np.sum((y - X_b.dot(theta)) ** 2) / len(y)except:return float('inf')def dJ(theta, X_b, y):return X_b.T.dot(X_b.dot(theta) - y) * 2. / len(y)def gradient_descent(X_b, y, initial_theta, eta, n_iters=1e4, epsilon=1e-8):theta = initial_thetacur_iter = 0while cur_iter < n_iters:gradient = dJ(theta, X_b, y)last_theta = thetatheta = theta - eta * gradientif (abs(J(theta, X_b, y) - J(last_theta, X_b, y)) < epsilon):breakcur_iter += 1return thetaX_b = np.hstack([np.ones((len(X_train), 1)), X_train])initial_theta = np.zeros(X_b.shape[1])self._theta = gradient_descent(X_b, y_train, initial_theta, eta, n_iters)self.intercept_ = self._theta[0]self.coef_ = self._theta[1:]return selfdef predict(self, X_predict):"""给定待预测数据集X_predict,返回表示X_predict的结果向量"""assert self.intercept_ is not None and self.coef_ is not None, \"must fit before predict!"assert X_predict.shape[1] == len(self.coef_), \"the feature number of X_predict must be equal to X_train"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)def __repr__(self):return "LinearRegression()"if __name__ == '__main__':# use boston house price datasetboston_data = datasets.load_boston()x = boston_data['data']  # total x size (506,)y = boston_data['target']  # total y size (506,)# keep data with target value less than 50.x = x[y < 50]  # total x size (490,)y = y[y < 50]  # total x size (490,)# notice! need data normalizescaler=StandardScaler().fit(x)x=scaler.transform(x)# train size:(343,) test size:(147,)x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=123)regs = LinearRegression()regs.fit_gd(x_train, y_train)# calc errorscore = regs.score(x_test, y_test)rmse = root_mean_squared_error(y_test, regs.predict(x_test))print('R squared error:%.2f' % (score))print('Root mean squared error:%.2f' % (rmse))print('coeffient:', regs.coef_.shape)print('interception:', regs.intercept_.shape)

1.4 sklearn中的线性回归模型

import sklearn.datasets as datasets
from sklearn.linear_model import LinearRegression
import numpy as np
from sklearn.model_selection import train_test_split
from math import sqrt
np.random.seed(123)def mean_squared_error(y_true, y_predict):"""计算y_true和y_predict之间的MSE"""assert len(y_true) == len(y_predict), \"the size of y_true must be equal to the size of y_predict"return np.sum((y_true - y_predict)**2) / len(y_true)def root_mean_squared_error(y_true, y_predict):"""计算y_true和y_predict之间的RMSE"""return sqrt(mean_squared_error(y_true, y_predict))if __name__ == '__main__':# use boston house price datasetboston_data = datasets.load_boston()x = boston_data['data']  # total x size (506,)y = boston_data['target']  # total y size (506,)# keep data with target value less than 50.x = x[y < 50]  # total x size (490,)y = y[y < 50]  # total x size (490,)# train size:(343,) test size:(147,)x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=123)regs = LinearRegression()regs.fit(x_train, y_train)# calc errorscore = regs.score(x_test, y_test)rmse = root_mean_squared_error(y_test, regs.predict(x_test))print('R squared error:%.2f' % (score))print('Root mean squared error:%.2f' % (rmse))print('coeffient:',regs.coef_.shape)print('interception:',regs.intercept_.shape)
R squared error:0.79
Root mean squared error:3.36
coeffient: (13,)
interception: ()

http://chatgpt.dhexx.cn/article/QML882gO.shtml

相关文章

机器学习之线性回归原理详解、公式推导(手推)、简单实例

目录 1. 原理详解1.1. 线性回归1.2. 回归系数 2. 公式推导2.1. 单元线性回归2.2. 多元线性回归 3. 简单实例3.1. 实例1&#xff1a;一元线性回归实例2&#xff1a; 多元线性回归3.3. 实例3&#xff1a;房价预测 1. 原理详解 1.1. 线性回归 假设一个空间中有一堆散点&#xff0…

统计学——线性回归公式推导

假设我们有n个点&#xff0c;(x1,y1), (x2,y2), ... ,(xn,yn)&#xff0c;如下图所示&#xff1a; 我们要求这几个点的线性回归方程&#xff0c;假设方程为ymxb&#xff0c;如下图所示&#xff1a; 我们的目的是使误差的平方和最小 即求&#xff1a; 的最小值。

计算线性回归、指数回归公式

最近要计算线性回归、指数回归的公式。就整理下吧&#xff0c;以便帮助他人&#xff0c;少走弯路。 发现网上线性回归的资料还算详细&#xff0c;但是指数回归资料很少&#xff0c;还会误导人。 线性回归是利用数理统计中回归分析&#xff0c;来确定两种或两种以上变量间相互…

Python实现线性回归(公式推导+源代码)

写这篇文章之前&#xff0c;首先要对自己做一个小小的反思&#xff0c;很多时候在学习新技术的时候&#xff0c;看到出了什么什么框架&#xff0c;在这个框架上什么什么方法可以直接拿过来用&#xff0c;这样的好处就是我们可以减少写代码量&#xff0c;几个函数就可以帮我们解…

线性回归方程推导

理论推导 机器学习所针对的问题有两种&#xff1a;一种是回归&#xff0c;一种是分类。回归是解决连续数据的预测问题&#xff0c;而分类是解决离散数据的预测问题。线性回归是一个典型的回归问题。其实我们在中学时期就接触过&#xff0c;叫最小二乘法。 线性回归试图学得一个…

线性回归相关知识及公式推导

转自https://www.cnblogs.com/GuoJiaSheng/p/3928160.html 在现实生活中普遍存在着变量之间的关系&#xff0c;有确定的和非确定的。确定关系指的是变量之间可以使用函数关系式表示&#xff0c;还有一种是属于非确定的&#xff08;相关&#xff09;&#xff0c;比如人的身高和…

线性模型(二)-- 线性回归公式推导

我们在初中学习线性方程的时候就已经接触过回归的相关概念&#xff0c;在这里简单介绍一下机器学习中的“回归”&#xff0c;机器学习的目的有两个&#xff1a;回归和分类&#xff0c;回归是解决连续数据的预测问题&#xff0c;而分类是为了解决离散数据的预测问题。线性回归是…

一元线性回归公式推导

一元线性回归公式推导 平均损失函数&#xff1a; 对w,b求偏导&#xff1a; 可求解&#xff08;先求b,再求w): 或&#xff1a; 这两个式子中的w是等价de,可由第一个w分子分母同除n&#xff0c;再由下式得到第二个w&#xff1a; 参考文献&#xff1a; https://zhidao.baidu.com/q…

线性回归模型公式推导

线性回归公式推导 线性模型一、线性回归&#xff08;一&#xff09;一元线性回归1. 由最小二乘法得出损失函数2. 证明损失函数 E ( w , b ) E(w,b) E(w,b)是关于 w w w和 b b b的凸函数3. 对损失函数求关于b和w的一阶偏导数4. 令一阶偏导数为0解出 w w w和 b b b &#xff08;二…

线性回归--公式推导

线性回归 -- LIner regression 线性回归&#xff08;Linear regression&#xff09;是利用称为线性回归方程的最小二乘函数对一个或多个自变量和因变量之间关系进行建模的一种回归分析 —维基百科 线性回归--理论推导 <1> 数据: 本次推导使用的数据为--银行贷款数据。 &…

线性回归原理及算法

今天给大家的介绍一下线性模型&#xff0c;线性回归模型虽说模型简单&#xff0c;但距今为止依旧在机器学习算法中占据一定的地位&#xff0c;不仅如此&#xff0c;而且在实际的业务应用中也是屡试不爽的机器学习算法。 线性回归模型公式&#xff1a;YXwb &#xff08;一个X变量…

机器学习之线性回归

线性回归是最简单的一个函数拟合过程&#xff0c;一元线性回归公式为yaxb。 我们做拟合&#xff0c;首先需要定义一个损失函数。一般常用的损失函数有&#xff1a;0-1损失函数和绝对值损失函数 0-1损失是指&#xff0c;预测值和目标值不相等为1&#xff0c;否则为0&#xff1a;…

在线Cron表达式生成器,定时任务表达式生成器

近期项目需要在后台管理系统的页面上生成定时任务表达式存入定时任务系统的数据库中&#xff0c;就是那种根据后台管理员指定的时分秒年月日生成一个定时任务表达式。 一时间有点不好下手。我可以根据后台管理员指定的时分秒年月日手动写一个定时任务表达式&#xff0c;也可以…

在线QuartzCron定时任务表达式在线生成

在线QuartzCron定时任务表达式在线生成 在线QuartzCron定时任务表达式在线生成 Quartz是一个完全由java编写的开源作业调度框架,Quartz最主要的功能就是调度器(完成定时任务)。本工具可以在线生成QuartzCron表达式 Quartz是一个完全由java编写的开源作业调度框架,Quartz最主要…

Android Studio修改应用名称及应用图标

一、修改应用名称 找到src/main/AndroidManifest.xml文件&#xff1a; android:label后面配置的就是应用名称配置路径或应用名称。 方式1&#xff1a;android:label"xxx应用"&#xff08;应用名称显示xxx应用&#xff09; 方式2&#xff1a;android:label"st…

Android修改应用程序图标和名字

Android修改应用程序图标和名字 对于一个APP应用程序来说&#xff0c;最鲜明的就是APP的图标和名字了。 修改应用图标 在res/drawable中保存一个jpg或者png的图片文件。(png支持透明度) 例&#xff1a;在drawable中保存icon.jpg文件修改AndroidManifest.xml中application的a…

flutter 修改app名字和图标(安卓)

安卓 修改名字: 找到flutter项目下面的android>app>src>main>AndroidManifest.xml 修改里面的android:label"改成你要的名字" 修改图标: 找到android>app>src>main>res里面的mipmap-xx文件夹修改里面的图标 一件生成多种格式的图标: http…

android studio修改app图标

一、修改图标文件 1.找到项目下的多个mipmap-目录&#xff08;如下图&#xff09;&#xff0c;将要修改的图片在每个目录中都放入一份 2.再找到mipmap-anydpi-v26目录&#xff08;如下图&#xff09;&#xff0c;修改目录中两个文件的内容&#xff0c;使其指向我们上一步放入的…

如何修改安卓应用图标和程序名称

安卓修改大师可以在没有源代码的情况下&#xff0c;直接反编译已经打包的APK安装包&#xff0c;通过修改SMALI代码实现添加和去除部分功能&#xff0c;也可以通过修改应用图标和应用程序名称实现个性化应用&#xff0c;甚至可以通过修改应用程序配置参数&#xff08;内置统计参…

修改app图标

修改app图标 1.准备三个尺寸的.png图片 &#xff08;注&#xff1a;一定要是.png后缀的图片&#xff09;,分别命名为xx.png, xx2x.png, xx3x.png; 2.在项目中找到项目->Resource->AppLogo,把三个尺寸的图片拉入项目中&#xff0c;选择Copy items if needed、Create gr…