目录
一、一元线性回归代码实测
二、统计量分析
1、statsmodels库
2、计算各种统计量
3、F检验、t检验
4、置信区间、预测区间
5、残差正态检验
6、自相关检测
①导入相关模块
首先导入必要的模块,这里主要使用了Python的sklearn库里自带的丰富算法模块!具体每个库的功能可自行查阅,这里只讲明思路。
import warnings
warnings.filterwarnings('ignore')
import numpy as np
import pandas as pd
import sklearn
import matplotlib.pyplot as plt
import seaborn
from pylab import rcParams
rcParams['figure.figsize'] = 10,8
from sklearn import datasets,linear_model
from sklearn.linear_model import LinearRegression,Ridge,Lasso #后面两个是套索回归和岭回归,暂时用不到
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression,Lasso,Ridge
from sklearn.metrics import mean_squared_error,r2_score,mean_absolute_error
from sklearn.model_selection import KFold #老函数cross_validation改名为model_selection
from sklearn.datasets import load_boston
from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import make_pipeline
from scipy.interpolate import make_interp_spline #老函数spline改名为make_interp_spline
from sklearn.neighbors import KNeighborsRegressor
from sklearn.kernel_ridge import KernelRidge
②导入并查看数据
#读取数据
regression_data = pd.read_csv('simple_regression_data.csv') #加载数据集csv文件:1000x2(1列名Volume,1列名Price)
#绘制数据散点图,观察数据分布
plt.scatter(regression_data['Volume'],regression_data['Price'])
plt.xlabel('Volume')
plt.ylabel('Price')
plt.title('Price-Volume Data')
plt.show()
③划分训练集和测试集
#数据分割为训练集80%和测试集20%,每次运行划分都是随机的(设置random_state参数为一个任意整数即可解除这种随机)
X_train, X_test, Y_train, Y_test =
train_test_split(regression_data['Volume'],regression_data['Price'],test_size=0.20)
④创建算法对象并训练(fit拟合)
#创建线性回归对象
simple_linear_regression = LinearRegression()
#利用训练集训练数据
X_train = X_train.values
Y_train = Y_train.values
X_test = X_test.values
simple_linear_regression.fit(pd.DataFrame(X_train),pd.DataFrame(Y_train)) #fit方法训练模型找规律
⑤用测试集预测并输出
#使用测试集进行预测
Y_predict = simple_linear_regression.predict(pd.DataFrame(X_test)) #predict方法预测测试数据
#输出拟合后的图像
plt.scatter(X_test,Y_test,color='blue') #测试集散点图
plt.plot(X_test,Y_predict,color='red',linewidth=2) #测试集部分折线图(直线)
plt.show()
statsmodels
库对比statsmodels
库与scikit-learn
库的线性回归
上面代码使用了scikit-learn`库中的LinearRegression()实现线性回归。下面我们要使用statsmodels库的sm.OLS普通最小二乘法(Ordinary Least Squares, OLS)进行线性回归建模。相比之下,主要区别在于两者提供了不同的功能和输出:
(1)功能:
LinearRegression()是scikit-learn线性回归,主要用途是进行机器学习任务,例如预测或分类。scikit-learn的模型设计更加简单,适用于广泛的机器学习任务。
statsmodels的OLS模型更侧重于统计分析,提供了更多关于模型统计性质的详细信息,如p值、置信区间等。它通常用于回归分析和统计推断,更适用于需要详细统计信息的数据分析。
(2)输出:
LinearRegression()对象通常不提供直接的统计信息,而是提供模型的系数、截距等。对于统计信息,你需要使用其他方法或库进行分析。
statsmodels的OLS模型通过model.summary()提供了非常详细的模型统计信息摘要,包括ANOVA表、系数、标准误、t统计量、p值等。
总体来说:
如果主要关注预测和机器学习任务,LinearRegression()可能更为方便。如果你对统计信息和模型的详细性质感兴趣,或者进行回归分析,那么statsmodels的OLS模型更适合。在一些情况下,分析中可能会同时使用这两者,根据不同的需求选择合适的工具。
上述代码①-③都不变,只是①中的部分模块用不到了
④用statsmodels库的sm.OLS普通最小二乘法进行线性回归拟合
import statsmodels.api as sm
# 添加截距项
X_train_sm = sm.add_constant(X_train) #将数据转换为 statsmodels 支持的格式
X_test_sm = sm.add_constant(X_test)
# 创建OLS模型(普通最小二乘法)
model = sm.OLS(Y_train, X_train_sm).fit()
查看模型摘要,里面已经包含了一些统计量,也可以调用anova_table =sm.stats.anova_lm(model)函数计算方差分析表,但是实验时报错AttributeError:'PandasData' object has no attribute' design_info'不知道为什么??有知道的友友可以评论区解决下。
# 模型摘要
summary = model.summary()
print("最小二乘(OLS)回归结果:")
print(summary)
也可以调用anova_table = sm.stats.anova_lm(model)函数计算方差分析表,但是实验时报错AttributeError: 'PandasData' object has no attribute 'design_info'不知道为什么??有知道的友友可以评论区解决下。
# 计算各种统计量
y_pred = model.predict(X_test_sm)
residuals = Y_test - y_pred #计算残差
print("残差:" )
print(residuals)
# 数据总离差平方和 SST
total_sum_of_squares = np.sum((Y_test - np.mean(Y_test))**2)
print("总离平方和(SST):%f" % total_sum_of_squares)
# 回归平方和 SSR
regression_sum_of_squares = np.sum((y_pred - np.mean(Y_test))**2)
print("回归平方和(SSR):%f" % regression_sum_of_squares)
# 残差平方和 SSE
residual_sum_of_squares = np.sum(residuals**2)
print("残差平方和(SSE):%f" % residual_sum_of_squares)
# 总离差自由度 DFT
dft = len(Y_test) - 1 #非NaN样本数量-1
print("总离差自由度(DFT):%d" % dft)
# 回归自由度 DFR
dfr = 2-1 # 回归模型参数数量-1
print("回归自由度(DFR):%d" % dfr)
# 残差自由度 DFE
dfe = dft - dfr #非NaN样本数量-回归模型参数数量
print("残差自由度(DFE):%d" % dfe)
# 平均总离差 MST
mean_total_sum_of_squares = total_sum_of_squares / dft
print("平均总离差(MST):%f" % mean_total_sum_of_squares)
# 平均回归平方 MSR
mean_regression_sum_of_squares = regression_sum_of_squares / dfr
print("平均回归平方(MSR):%f" % mean_regression_sum_of_squares)
# 残差平均值 MSE
mean_residual_sum_of_squares = residual_sum_of_squares / dfe
print("残差平均值(MSE):%f" % mean_residual_sum_of_squares)
# 均方根残差 RMSE
root_mean_square_residual = np.sqrt(mean_residual_sum_of_squares)
print("均方根残差(RMSE):%f" % root_mean_square_residual)
#拟合优度决定系数R^2系数(这里一元线性回归,不用修正决定系数)
R2 = regression_sum_of_squares / total_sum_of_squares #SSR/SST或1-SSE/SST
print("R^2系数:%.2f" % R2)
# 对数似然函数
log_likelihood = -0.5 * len(residuals) * (1 + np.log(2 * np.pi * mean_residual_sum_of_squares))
print("对数似然函数值:%f" % log_likelihood)
疑问:为什么检验值和上面的部分统计量与模型摘要里面的不同?有知道的友友可以评论区解决下。
# # F检验
from scipy.stats import f_oneway
# 合并实际值和预测值为一个数组
all_values = np.concatenate([Y_test, y_pred])
# 创建对应组标签的列表
group_labels = ['Actual'] * len(Y_test) + ['Predicted'] * len(y_pred)
# 进行一元方差分析
f_statistic, p_value = f_oneway(Y_test, y_pred)
print(f"F统计量: {f_statistic}")
print(f"F检验的p值: {p_value}")
# 计算t检验
t_test_results = model.t_test([0, 1]) # 这里假设你对的是截距项和斜率的t检验
# 获取 t 统计量和 p 值
t_statistic = t_test_results.tvalue[0, 0]
t_p_value = t_test_results.pvalue.item()
print(f"t统计量: {t_statistic}")
print(f"t检验的p值: {t_p_value}")
如果 F 检验的 p 值较小(小于设定的显著性水平如0.05),则可以拒绝原假设(零假设),表明模型是显著的、整体拟合效果较好,即自变量对因变量有显著影响。
疑问:图中的填充是否存在问题?
# 计算置信区间和预测区间
confidence_interval = model.get_prediction(X_test_sm).conf_int()
prediction_interval = model.get_prediction(X_test_sm).conf_int(obs=True)
import seaborn as sns
# 可视化拟合图
plt.scatter(X_test, Y_test, color='blue', label='Test Data') # 测试集散点图
plt.plot(X_test, y_pred, color='red', linewidth=2, label='Fit Line') # 测试集部分折线图(拟合线)
# 标注置信区间
plt.fill_between(X_test, confidence_interval[:, 0], confidence_interval[:, 1], color='gray', alpha=0.2, label='Confidence Interval')
# 标注预测区间
plt.fill_between(X_test, prediction_interval[:, 0], prediction_interval[:, 1], color='orange', alpha=0.2, label='Prediction Interval')
plt.xlabel('Volume')
plt.ylabel('Price')
plt.title('Price-Volume Data with Confidence and Prediction Intervals')
plt.legend()
plt.show()
①绘制残差分布图
import seaborn as sns
from scipy.stats import probplot
# 绘制残差分布图
sns.histplot(residuals, kde=True)
plt.title('Residuals Distribution')
plt.xlabel('Residuals')
plt.ylabel('Frequency')
plt.show()
②绘制标准化残差Q-Q图
在统计学中,Q-Q 图(Quantile-Quantile Plot)是一种用于检查样本分布是否符合理论分布的图形工具。对于线性回归模型,标准化残差的 Q-Q 图用于检查模型的残差是否近似服从正态分布。
# 标准化残差的Q-Q图
probplot(residuals, plot=plt)
plt.title('Q-Q Plot of Residuals')
plt.xlabel('Theoretical Quantiles')
plt.ylabel('Sample Quantiles')
plt.show()
标准化残差是残差除以其标准差,以确保它们的尺度一致。标准化残差的 Q-Q 图通过将残差的理论分位数与标准正态分布的理论分位数进行比较来显示残差的分布。如果标准化残差的 Q-Q 图呈直线分布,说明残差大致符合正态分布。如果出现弯曲或偏离,可能表示残差不符合正态分布。
在上述代码中,使用 probplot
函数绘制标准化残差的 Q-Q 图。图中的点表示标准化残差的观测值,如果它们落在一条直线上,就意味着残差近似符合正态分布。这个图形提供了一种直观的方式来检查残差的正态性,是判断模型是否符合正态分布假设的一个有用工具。
③Omnibus检验
# Omnibus检验残差的正态性
omnibus_test = sm.stats.omni_normtest(residuals)
print("Omnibus检验结果:")
print(omnibus_test)
①绘制自相关图
自相关图(Autocorrelation Plot)是一种用于检查时间序列数据自相关性的图形工具。在自相关图中,x轴表示滞后的阶数(Lag),y轴表示对应滞后阶数的自相关系数。这个图能够帮助你了解时间序列中是否存在滞后相关性。
from statsmodels.graphics.tsaplots import plot_acf
# 绘制自相关图
plot_acf(residuals, lags=20) # 在lags参数中指定滞后阶数
plt.title('Autocorrelation Plot of Residuals')
plt.xlabel('Lag')
plt.ylabel('Autocorrelation')
plt.show()
对于自相关图的解读:
在自相关图中,一般会显示一个阴影带,表示 95% 的置信区间。如果自相关系数在该置信区间内,则不具有显著性。这里显然都在阴影带内,表示残差之间无显著自相关性。
②Durbin-Watson自相关检测
# Durbin-Watson自相关检测
durbin_watson_statistic = sm.stats.durbin_watson(residuals)
print(f"Durbin-Watson统计量: {durbin_watson_statistic}")
DW值在2附近,表明序列无自相关。具体取值范围及意义见往期博客。
写本次代码实测博客时,也遇到了很多问题,求助了GPT和CSDN等平台都没有解决,希望懂行的博友提提宝贵的意见!另外需要实测数据xls文件的友友可以点赞后在评论区求助!