1 问题概述
数据集data.xlsx包含238行深度、岩性描述、水饱和度、油饱和度、岩心和毛细管等相关参数信息,为拟合水平渗透率拾取具有较好线性相关性的信息。
图1数据集信息
任务要求:
1 .优选对给定数据集进行预处理,提取特征后分为训练集和测试集(建议用4:1分割);
使用Python或自己熟悉的语言对训练数据进行建模(模型不限);
3 .利用建立的模型预测测试集的渗透率,将预测渗透率值作为最后一列合并到测试集数据表中,计算平均误差。
结合任务要求展开这次回归分析实验的介绍。
2 数据预处理
1删除无效数据首先加载数据集,删除“岩性描述”列,因“油饱和度、%”、“水饱和度、%”缺失数据过多而删除; “空隙率”、“%”和“水平渗透率”、“10-3m2”中含有空白数据,去除有空白数据的行整体,实现代码如下。
data=PD.read _ excel (r ‘ g : (长2021 (BD _ fhw )数据. xlsx ) )负载数据集
DATA=data.dropna(subset=[ ‘空隙率、% ‘、’水平渗透率、10-3m2’] )删除无效的行数据
删除data=data.drop([ (岩性描述、水饱和度、%、油饱和度、% ) ]无效列数据
2 数据分析及选取
,利用seaborn数据包进行数据可视化。
seaborn是一个基于Matplotlib的Python数据可视化库。 提供高级界面,用于绘制引人注目、内容丰富的统计图形,同时将Matplotlib打包为更高级的API以方便绘图。 seaborn面向统计绘图,可以满足90%的数据分析绘图需求。 需要复杂的自定义图表,也需要用于Matplotlib。
seaborn的相关性热点图初步发现数据中含有的线性关系。 corr(x,y )是相关系数,描绘出二维随机变量的两个分量之间的相互关系程度。
corr(x,y )在-1到1之间,也就是相关系数在-1到1之间,如果corr ) x,y )=0,则x,y被称为不相关,但不相关意味着x,y没有线性关系,也可以是其他关系,例如如果corr(x,y )=1,则说x和y完全正相关,如果corr ) x,y )=-1,则说x,y完全负相关。
以下给出相关热点图实现代码,并给出效果的解读。
导入赛博恩as SNS
PLT.RCParams [ ‘字体. Sans-serif ‘ ]=[ ‘ Simhei ‘ ]
PLT.rcparams [ ‘ axes.unicode _ MINUS ‘ ]=假#汉字代码
SnS.heatmap(data.corr ) ) #相关性热点图,corr ) )判断相关性OUTPUT:
图2相关热点图
p>
上图中横纵坐标对称,颜色越淡代表相关性(正)越强,越深则代表负相关性越强。根据相关性热点图可初步选定正负相关性较好的数据,如孔隙度、总进汞量、最大进汞饱和度、残留汞饱和度、最大饱和度增量、峰态和最大增量对应直径具有较好的正相关性,而退汞效率具有较好的负相关性。故首先选择如上数据进行训练拟合,并划分训练集和测试集。
X
OUTPUT:
from sklearn.model_selection import train_test_split #sklearn中包含数据集切分的函数train_test_split,直接调取使用
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2) #random_state
#测试集参数设0.2,及1:4切分
3 线性回归模型
sklearn库中有很多线性回归的模型,本次作业选取其中的LinearRegression, Lasso以及最小二乘法进行数据测试。
LinearRegression
线性回归算法模型很简单,每条数据有n个特征,每个特征对应着一个自己的权重值,与权重的乘积再加上一个偏置值,这个就是线性回归模型,公式如下(n代表特征数目,m代表样本数目):
y=w1∗x1+w2∗x2+…+wn∗xn+b
假设有m个样本,写成矩阵的形式就是:
权重 w也可以写成矩阵的形式:
W=[w0,w1,w2,…,wn]
写成一种简单明了的方式:
Y=XWT
LinearRegression的损失函数是可以一定程度上衡量模型的好坏的一个算法,在回归问题中比较常用的损失是均方误差(MSE):
为了减少损失函数的值,需要一种优化器:梯度下降算法。假设我们的样本只有一个特征,且偏置项为0,那么我们的损失函数就可以写为:
最小二乘法
Lasso回归
Lasso是在最小二乘回归的基础上加上L1正则表达式得到,L1正则表达式同样可以防止模型过拟合。
sklearn对线性回归方法已经做好了封装,调用起来非常方便,如下:
from sklearn.linear_model import LinearRegression #引入LinearRegression模型
#from sklearn.linear_model import Lasso
#import statsmodels.api as sm
lr = LinearRegression()
lr.fit(x_train,y_train) #用LinearRegression回归模型拟合训练集
# las = Lasso(alpha=0.01)
#las.fit(x_train,y_train) #用Lasso回归模型拟合训练集
#model_ols=sm.OLS(y,x).fit() #最小二乘拟合
print(“train=”,lr.score(x_train,y_train)) #对回归效果进行打分,lr.score方法及计算R的平方
OUTPUT:
train= 0.6523736250935579
对拟合的相关系数(coef)进行输出:
coeff_df=pd.DataFrame(lr.coef_,x.columns,columns=[‘Coefficient’]) #coef_即W1,…,Wn;intercept_即W0
coeff_df
OUTPUT:
用拟合的回归模型对测试集进行预测:
predictions=lr.predict(x_test)
predictions.reshape(-1)
OUTPUT:
4 预测效果评价
得到预测数据后,可以发现预测效果与真实情况存在偏差。首先预测结果中存在少量负值,这与实际情况中渗透率为正不符。为了更加直观地展示预测结果与真实值的分布情况,我画出了测试集的真实值与对应的预测值之差,以此观察偏差效果,并计算平均绝对误差。
sns.distplot((y_test-predictions),bins=50) #y_test-predictions概率分布
predictions_all=lr.predict(x)
# predictions.reshape(-1)
print(“平均误差:”,(sum(abs(y-predictions_all)))/len(predictions_all)) #计算平均误差
OUTPUT:
图3 y_test-predictions
由图3可知,y_test-predictions的值主要分布在0附近的范围,大致呈现正态分布,表明预测结果有效,但仍有偏差较大的数据存在。计算平均误差得到平均误差为187.77,由于数据集中渗透率数据主要集中在0-1000,故误差较大。
最后完成将预测值输入到Excel表格中的任务。
def insert_pdt(predictions_all): #将预测数据插入到excel表格
wb=openpyxl.load_workbook(r’G:\Loong_2021\bd_fhw\data.xlsx’)
sheetNames = wb.sheetnames
print(sheetNames)
sheet1 = wb.worksheets[0]
for i in range(len(predictions_all)):
sheet1.cell(i+2, 24).value=predictions_all[i] #excel中单元格为X2开始,即第24列,第2行
wb.save(r’G:\Loong_2021\bd_fhw\data.xlsx’)
insert_pdt(predictions_all)