学习目标:
1·理解什么是线性回归;
2·使用Python进行的线性回归分析各大城市的降水与气温之间的关系。
首先,什么是线性回归?
线性是自然界、人类社会中比较普遍的一种关系,比如说房价的预测、金融的预测等等都会运用到线性的知识。但是我们在看待问题的时候一定要注意:相关性不代表因果性!!! 举个例子:有一个管理沙滩旅游的经理,因沙滩上溺水的人数较多,想去探究一下原因。发现雪糕卖得越多,游泳溺水死亡的人数越高。难道就表明雪糕会增加游泳溺水的可能性吗?这显然是不恰当的。
让我们来捋一下思路:夏天温度高 --> 去海边玩耍的人数增加 --> 游泳的人多了
夏天温度高 --> 去海边玩耍的人数增加 -->买雪糕的人多了
两者之间根本没有任何的因果性,所以不要被表面的相关性所误导。
-------- 回归正题 --------
“上帝”在一开始制定线性规则的时候,在他的视角线性规律可能会是下图所示:
等式右边最后一项,我们称之为随机数Error(遵循正态分布)。
为了更好的理解随机数这个概念,我们举一个生活中的例子:Y是工作的收入,X是学历。按照一般的社会法则,我们可以预见学历越高,一般收入也就越高(受线性关系的支配)。但是总有一些“被上帝眷顾的宠儿”在相同的学历程度中,最后一个随机数,随出来很大,那么他的收入自然也就变高了,像马云等。
但是在人类视角,我们是看不到Error是如何运作的,并且只能通过以前的数据去猜出常数项和斜率,如下图:
(具体如何建模我们会在下文提到)
我们如何去求解常数项和斜率呢?他的数学原理是什么?
按照上述的公式我们可以对任何线性关系写成如下数学表达式:
再将其写成矩阵形式:
从理论上来讲我们是可以解出其中的解析解,就可以顺利写出常数项和斜率值:
其实在建模的过程中就是把数学表达式转化为代码的形式。
我们如何去评价一个模型建立的好坏呢?
先来介绍几个常用的量:
1·SST(Sum of Square Total):(Yi为实际值,Ybar为均值)
2·SSR(Sum of Square Regression):(Yhat为预测值)
3·SSE(Sum of Square Error):(下图也表示了这三者之间的关系)
计算出上述值之后,我们在实际中常用RMSE去评价(越接近于1越好):
Ps:当然还有MAE、MSE、(R‘)^2等可以很好的评价这个模型的好坏。
在使用过程中,我们要注意一下几点使用条件:
1·因变量与自变量之间呈线性关系(可以先跑跑代码试试看);
2·误差项的独立性(Error自己不会影响自己);
3·同方差性;
4·Error遵循正态分布;
5.没有多重共线性(自变量之间没有强相关性)。
学习完理论知识后,我们接下来上手实战一波!
实战我们以Python进行的线性回归分析各大城市的降水与气温之间的关系为例。
在气候科学领域有如下公式(可以看出理论上的温度与降水满足线性关系):
利用此公式,我们可以通过使用理想气体的参量,解出在理想状态下气温对降水的影响系数(如下图):
我们可以清楚的看到在理想状态下温度每升高1摄氏度,降水增加6.1094%,但是在现实中是怎么样的呢?我们就来一探究竟吧:
首先读入数据,因为数据是.nc格式,我们需要使用netCDF4读入。
数据可以从这里找到:
CMIP5 long-term Experiments of MPI-Mwww.dkrz.de在开始之前我们可以用Panoply先预览一下:
可以看到数据的分辨率不是非常的高……我们把经纬度一起读进来方便后续挑选城市。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from netCDF4 import Dataset
file1 = "tas_Amon_GFDL-ESM2M_historical_r1i1p1_186101-200512.nc"
file2 = "pr_Amon_GFDL-ESM2M_historical_r1i1p1_186101-200512.nc"
ds1 = Dataset(file1,'r')
ds2 = Dataset(file2,'r')
tas = ds1.variables['tas'][:,:,:]
pr = ds2.variables['pr'][:,:,:]
lon = ds1.variables['lon'][:]
lat = ds1.variables['lat'][:]
因为全球范围太广,所以我们以北京为例:
#site Cities
#BeiJing(40N,116E),把北京的真实经纬度转化成相应分辨率
lon_BJ_index = int(116/(360/len(lon)))
lat_BJ_index = int(40/(180/len(lat)) + len(lat)/2)
pr_BJ = pr[:,lat_BJ_index,lon_BJ_index]
tas_BJ = tas[:,lat_BJ_index,lon_BJ_index]
#先预览数据的分布(因为对于线性建模来讲,数据最好接近正态分布!!!!)
plt.subplot(1,2,1)
plt.hist(pr_BJ)
plt.subplot(1,2,2)
plt.hist(tas_BJ)
#数据可能的几种预处理手段:取对数、取倒数、开根号
plt.subplot(2,2,1)
plt.hist(pr_BJ)
plt.subplot(2,2,2)
plt.hist(np.log(pr_BJ))
plt.subplot(2,2,3)
plt.hist(1/pr_BJ)
plt.subplot(2,2,4)
plt.hist(np.sqrt(pr_BJ))
#转换数据
pr_BJ_tf = np.log(pr_BJ)
tas_BJ_tf = np.log(tas_BJ)
我们通过对原始数据进行一系列数学运算,并画出图像进行比较,这里我们选择对原始数据进行取对数的操作方法(当然可以使用BoxCox方法,这会在后续讲到)。
我们把数据准备成矩阵形式,就可以套用数学公式来解出解析解啦!
#准备数据
X = np.insert(tas_BJ.reshape(-1,1), 0, 1, axis=1)
y = ((pr_BJ_tf - pr_BJ_tf[0])/pr_BJ_tf[0]).reshape(-1,1)*100
#B = (XT * X)^-1 * XT *y //B就是我们要求的解析解的矩阵
B = np.dot(np.dot(np.linalg.inv(np.dot(np.transpose(X),X)),np.transpose(X)),y)
print(B[1])
至此我们就粗略的猜出了简单线性回归的常数项和斜率值,线性回归的学习也就告一段落啦!
新手第一次写,如果找到了错误请及时通知我哦~如果大家想更加深入的了解机器学习这方面的知识还可以关注我CSDN的博客哦(ID:Alphoseven)
CSDN-个人空间me.csdn.net