多元线性回归——水平渗透率

1 问题概述

数据集data.xlsx中包含238行的深度、岩性描述、水饱和度、油饱和度、岩心和毛管等相关参数信息,挑取有较好线性相关性的信息用以拟合水平渗透率。


图1 数据集信息

任务要求:

  1. 将所给数据集进行预处理,优选特征后切分成训练集和测试集(建议按4:1切分);
  2. 使用Python或自己熟知的语言对训练数据建模(模型不限);
  3. 使用建立的模型对测试集的渗透率进行预测,将预测渗透率值作为最后一列合并到测试集数据表中,并计算平均误差。

下面结合任务要求展开本次回归分析实验的介绍。

2 数据预处理

1 剔除无效数据

首先加载数据集,将'岩性描述'一列剔除(汉字无法被拟合),'油饱和度,%','水饱和度,%'残缺数据过多,故剔除;'孔隙度,%'和'水平渗透率,10-3μm2'中含有空余数据,将空数据所在行整体剔除,实现代码如下:

data = pd.read_excel(r'G:\Loong_2021\bd_fhw\data.xlsx')#加载数据集
data = data.dropna(subset=['孔隙度,%', '水平渗透率,10-3μm2'])  #剔除无效行数据
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完全负相关。
相关性系数公式

下面展示相关性热点图实现代码及展示效果解读。

import seaborn as sns

plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False        #汉字编码

sns.heatmap(data.corr())               #相关性热点图,corr()判断相关性
图2 相关性热点图

上图中横纵坐标对称,颜色越淡代表相关性(正)越强,越深则代表负相关行越强。根据相关性热点图可初步选定正负相关性较好的数据,如孔隙度、总进汞量、最大进汞饱和度、残留汞饱和度、最大饱和度增量、峰态和最大增量对应直径具有较好的正相关性,而退汞效率具有较好的负相关性。故首先选择如上数据进行训练拟合,并划分训练集和测试集。

x = data[['孔隙度,%','总进汞量,ml','残留汞饱和度,%','最大饱和度增量,%','峰态','最大增量对应直径,μm','最大进汞饱和度,%','退汞效率,%']]
y = data['水平渗透率,10-3μm2']

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库中有很多线性回归的模型,本次作业选取其中的LinearRegressionLasso以及最小二乘法进行数据测试。

LinearRegression 基本形式

Loss Function
梯度下降

原文链接

最小二乘法


原文链接

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的平方

train= 0.6523736250935579

对拟合的相关系数(coef)进行输出.

coeff_df = pd.DataFrame(lr.coef_,x.columns,columns=['Coefficient']) #coef_即W1,...,Wn;intercept_即W0
coeff_df

用拟合的回归模型对测试集进行预测.

predictions=lr.predict(x_test)
predictions.reshape(-1)

array([-2.59539925e+01, 4.31076612e+01, 1.30399742e+02, 5.04344867e+02,
-3.63570322e+01, 1.66409337e+02, 1.48233902e+02, 3.55917832e+02,
-2.06434297e+02, -8.96603664e+00, 4.48635127e+02, 9.75490295e+02,
3.90789114e+01, 1.58733681e+02, 3.00272800e+02, 1.40844112e+03,
2.18009116e+02, -1.09460260e+02, -6.74002294e-01, -6.27163724e+01,
5.40043178e+02, 7.71473581e+02, 5.46043428e+02, -1.25653783e+02,
1.95655312e+03, 2.33817042e+02, 3.39778641e+02, 2.69956394e+02,
-9.97752566e+01, 4.11430872e+02, 3.75070273e+02, 1.13961297e+03,
9.64772236e+01, 1.11353584e+02, 1.34962988e+03, -1.15255627e+02,
5.24330593e+02, -2.21775276e+02, 4.39584814e+02, -1.56036405e+02,
9.57150250e+02, 3.19622873e+02, -1.06216261e+01, 3.56941046e+02,
7.05463731e+02])

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)) #计算平均误差
图3 y_test-predictions

平均误差: 187.7708660295839

由图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)
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容