Python 数据分析学习(2)统计学基础
前言
本文主要记录数据分析的学习。
一、统计学的一些基础知识。
数据可以划分为两种类型,分类数据和数值数据。分类数据指的是包含有限数量的不同类别的数据,比如出生时的性别就两种类别是有限的,奥运会的奖牌、金银铜也是有限的。狗子的种类虽然有很多种,甚至还有各种串,但归根结底还是有限的。数值,数据指的是测量出的观测值,是个具体的数值,对它进行求和或求平均等数学运算是有意义的,比如班级人数、身高工资数等等。你对分类数据做数学运算就没有意义,比如男性乘女性金牌减铜牌,这都行不通。那再具体一些,分类数据和数值数据各自可以被进一步分类数据可以被分为定序和定类,定序表示数据是可以有顺序的,比如金银铜可以按顺序排,而定类表示数据没有顺序,比如狗子的种类,这咋排?我要非说萨摩耶的排序高于金毛,那养金毛的人也不会同意。
值数据分为连续和离散,连续表示数据没有最小的表示单位,两个数值之间可以取无数不同的值,比如头发的长度, 3 厘米和 4 厘米之间有无数种可能的数字,比如 3.1415926535 厘米。而离散表示数据只能以整数或自然数为单位,比如两台电脑 ,3 个人,你就没法说今天聚会来了 3.1个人.数值数据通常是分析的重点,可以有三个分析维度,集中趋势、离散趋势以及分布形状。
二、线性回归。
线性回归,一个听起来神秘莫测的数学模型,其实存在于我们生活中的方方面面。假如我们有某班级学生每日学习平均时长和学期绩点的数据,想探索这两个变量之间的关系,那学生的学习时长可以看成是自变量,它是可以改变和控制的,而绩点是因变量,它的值是被其他因素所影响的,那我们把这些数据画在一个平面直角坐标系上, x 轴对应自变量学习时长, y 轴对应因变量弃点的话会发现它可能长成这样。我们关注的是当自变量变化的时候,因本量会如何随之改变。如果随着自变量的增加,因变量也增加,我们说它们之间存在正相关,那从这个图表来看,绩点和学习时长之间是存在正相关的。如果我们画一条直线去尽可能的贴合图上的数据点,会发现这条直线是向上走的,这也说明是正相关。
假如我们还有另一个每日刷短视频时长和学期绩点的数据在坐标系上长成这样,可以看出这个上面随着自变量的增加,因变量减少这种情况我们说他们之间存在负相关。如果我们画一条直线去尽可能的贴合图上的数据点,会发现这条直线是向下走的,也说明是负相关。
假如我们还有学生身高和学期绩点的数据在坐标系上长成这样,这看起来就毫无规律了。那这种情况下,我们说它们之间不存在相关系数,就是用来研究变量之间线性关系的相关程度的。
这个值一般用 r 来表示, r 的值会介于一和- 1 之间,正数表示正相关,负数表示负相关。绝对值越大,也就是越接近一或-1,说明线性相关性越强。绝对值越小,也就是越接近0,说明线性相关性越弱。如果是0,就说明不存在线性相关了。
再来看线性回归又是什么?相关系数的核心在于衡量已知数据的相关性,也就是两个变量之间关系的强弱程度。而线性回归模型的核心在于预测未知数据。比如,如果我们知道一个学生每日平均学习时长是 3.2 小时,那它的绩点可以预测为是多少。具体来说,线性回归模型会以数学的方式把自变量和因变量用一个线性方程来表示,从而让我们可以使用自变量的值来预测未知的因变量的值。如果你还记得数学里的线性方程的话,它可以被这样表示,其中 y 表示因变量, x 表示自变量,而 m 和 b 是线性回归模型的参数。这里面 b 的值对应了 y 轴结距,也就是说,当自变量的值为 0 时,因变量的值是多少? m 的值对应了斜率,也就是说,当自变量的值增加一时,因变量的值增加多少,所以线性回归。就是我们想在坐标系上画出一条直线,让这条直线拟合图中的数据点,也就是尽可能的去靠近图中的每个数据点,从而针对任何 x 值,我们都能用这条线去预测它所对应的 y 值。
这条线也被叫做回归线,但问题是这条线怎么才算拟合呢?我们如何评估说这条线是这样更靠近各个点,还是这样用眼睛看自然是不行的,我们需要用数学来进行客观评估,回归线索估计的外置和样本里实际的外置,它们之间的差别被称为残差。比如这个图里面第二个点残差是4,第三个残差是-2。也有一种求解线性回归方程的方法,就是根据让所有残差的平方加起来的和最小这个目标去进行拟合。我为什么要去平方呢?因为如果我们直接对残差求和的话,负残差会抵消正残差,但平方后一定都是正数,不会正负数相抵消。
如果说红色这条线所产生的残差的平方和要小于绿色这条线,我们就认为红色这条线更拟合当前数据,也能更好地帮助我们通过自变量来预测因变量。
三、多元线性回归。
线性回归就是一个通过建立线性方程来描述自变量和因变量之间关系的分析方法。通过回归线,我们可以根据自变量的值来预测因变量的值,但我们在前面举的例子里只涉及了一个自变量,但现实中因变量可能会受到多个自变量的影响。举个例子,房价可能会随着面积的上涨而上涨,但是房离距离地铁的距离是否为一线城市等也是影响因素。我们当然可以对每个自变量都去建立单独的线进方程,但这样让我们很难直接预测因变量,因为不同方程得到的结果不同。更好的办法是用一个线性方程把这些存在潜在影响的 4 倍量都囊括进去,这被称为多元线性回归。
元可以理解为自变量,所以在简单的一元线性回归里,图上只有 X 自变量可以用 2D 图来表示。因变量和自变量,二元线性回归里,图上 X1 和 X2 都是自变量,所以要用三维的图来表示因变量和两个自变量多元线性回归的方程会长成这样,其中 y 还是因变量,但多元线性回归里有多个自变量,假设一个有 n 个,那X1, X2 一直到x, n 都是不同的自变量,而 B0 是结句,它表示当自变量都是 0 的时候,因变量的值B1, B2 一直到b, n 是方程的斜率,不过在线性回归里,它们也被叫做系数。那仍然是基于让残差的平方和最小这个目标。
关于线性回归模型,还有一个要解决的问题是如何在线性方程中表示分类变量,比如在我们预测房价的例子中,面积、房林到地铁站距离这些都是数值变量,可以直接用数字表达,但是否为一线城市是分类变量,它的值分为是和否,这咋表示?要把分类变量纳入线性方程的自变量,我们要引入虚拟变量,也就是直取 0 和一这两个值的变量。我们要做的是把那个变量转换为 0 和1,分别用来表示否合适,然后把虚拟变量作为自变量进行回归分析。具体用一表示是还是用 0 表示是,其实都是无所谓的,因为这最多会把得到结果的系数值正负调换一下,也不影响模型预测的结果。假如我们用一表示是用 0 表示否得到了这样的线性方程,那使用这个模型去预测时是一线城市,我们就把自变量的值带入一,不是就代入0,然后计算预测结果,就是这么简单。
那再进一步,假如这个分类变量不只有两种,举个例子,自变量现在不再是否为一线城市那么简单了,而是属于 1234 里的几线城市。那现在这个分类变量就存在四种可能的值,没法用一对 0 和一来表示了。有人可能会说,那我们分别用数字 1234 来表示属于几线城市不就行了?这其实会导致不准确的结果,因为拿房龄这个数值变量来说, 1 年到 2 年和 2 年到 3 年之间的间隔是一样的。但从几线城市这个分类变样来说,二线城市到一线城市的差别和三线城市到二线城市的差别不一定是一样的,所以我们不应该直接用 1234 去表示。
那正确的做法是什么呢?假如有 n 种类型,我们要引入 n 减一个虚拟变量。比如这个例子里引入是否是一线,是否是二线,是否是三线?这三个虚拟变属于那个分类的话,就用一表示。比如如果是二线城市的话,那第二个虚拟变量的值就是一,第一个和第三个是0,如果是四线城市的话怎么办呢?那我们就让这三个虚拟变量的值都为0,同时不符合一二三线,说明就是四线。
需要注意的是,引入虚拟变量的数量一定是种类数减一,不能引入和种类数相同数量的虚拟变量,否则会导致共线性问题。什么是共性问题呢?这和我们进行线性回归分析要注意的一个点有关,那就是多元线性回归模型里的自备量之间应该是独立的,不应该高度相关,如果其中有两个变量之间存在高度相关性,会导致对系数的估计不准确,这个就被称为共性问题。比如说预测房价的时候,面积和卧室数的增加都会导致房价增加,但是面积和卧室数之间存在较强的相关性。因为通常来说面积大的房子就有更多的卧室,所以如果我们同时把它们纳入进线性回归模型里,就会有共线性问题。
再比如说生理性别存在两种可能,我们应该只引入一个虚拟变量,比如一表示女, 0 表示男,如果我们同时引入两个虚拟变量,一个用一表示女, 0 表示男,一个用 0 表示女,一表示男,那实际上这两个变量之间是完全相关的,也会导致贡献性问题,这解释了我们前面的疑问。
那所以在建立线性回归模型前,我们应该先做一下相关性分析,具体来说就是针对各个变量的组合,计算一下我们之前学过的相关系数。如果发现两个自变量相关系数绝对值比较大,比如超过 0.8 或 0.9 的话,可以考虑把其中一个移除掉,再做回归分析。另外一个要注意的是,得到线性回归模型的参数之后,我们仍然要去留意各个自变量在模型中所对应的 p 值。如果说某个变量在线性回归里的 p 值很大,说明那个变量其实对因变量没有什么显着的预测作用,那我们可以考虑做的是把那个自变量从模型中剔除,再去进行一轮拟合。也就是对剩下的变量再去计算一轮截距和系数,这样能得到更简单也更可靠的线性回归模型。因为对因变量没有显著影响的变量没有必要留着,这也能降低对预测值的干扰和误导。
现在我们有了 p 值来衡量自备量对因变量的预测作用,但要如何衡量线性回归模型整体和实际值之间有多拟合呢?这个时候 r 方这个指标就派上了用场,如果你好奇的话,它的计算公式长这样,当我们用代码计算时,也是可以轻松得到 r 方的值的。它的数值范围是 0- 1,看的是线性回归模型和实际值之间有多相关,所以可以用来评估模型拟合度。具体来说就是 r 方的值越接近,一说明模型的预测值和实际观测值越拟合越接近0,说明模型的预测值与实际观察值相差越大。
四、线性回归模型
假设我们有一个房价相关的数据集,能分别知道面积、卧室数、厕所数、所在城市以及对应的价格。我们希望能够建立一个线性回归模型,同样能在给定自备量的值以后,基于已有数据来预测任意房子的房价。
首先第一步我们要引入帮助我们做线性回归的模块,那就是statsmodels的api模块,然后给他一个简短的别名
import statsmodels.api as sm
假设我们这个时候已经拿到数据了,那接下来要做的是如果说数据里面存在分类变量,我们得引入虚拟变量,也就是用 0 和一来分别表示是否属于该分类。这个例子里所在城市就属于分类变量,我们也不需要手动把分类变量转换成 0 和1。
pandas 有个现成的方法叫pd.get_dummies,就是用来把分类变量转换成虚拟变量的,传入我们的 data frame,然后把 columns 这个可选参数指定为列表里面放入分类变量。里面包含了根据分类变量引入的虚拟变量,而且原先那个分类变量也被自动删除了,但是这些虚拟变量的类型是布尔值,并不是我们想要的数字类型,比如一,表示是0,表示否,那我们需要再指定一个参数 d type 赋值为int,表示指定虚拟变量类型为整数,这样那些列的值就变成 0 和一了。
虽然现在我们顺利引入了虚拟变量,但是我这里建议调用get_dummies的时候再额外传入一个可选参数 drop_first,复制为true。这样做的目的是删除引入的第一个虚拟变量,因为上一节说过,当分类变量有 n 种类型时,我们应该只引入 n 减一个虚拟变量,而不是 n 个,否则会引起共线性。get_dummies执行完后他并不会修改原始的 data frame,所以我们要进行重新的赋值,那现在就得到了引入虚拟变量的新数据。
当有些变量高度相关的时候,如果我们把它们都包含进自变量里,有可能极大影响模型准确性,因为这个就是我们之前说的共线性问题,所以在进行线性回归建模前,我们还要进行一个额外的步骤,是检查当前自变量之间的相关性。要计算两个变量的相关系数,我们可以用 pandas series 的 corr 方法。 corr就是 correlation 相关性的简写,对其中一个 series 调用 corr 方法把另外一个 series 作为参数,就能得到它们之间的相关系数。
绝对值越接近一说明越相关,越接近 0 说明越不相关。我们进行多元线性回归分析的时候,为了避免共线性,要查看各个自变量之间的相关性。如果说有很多自变量,一对对查也是有点麻烦。DataFrame其实也有corr方法,[DataFrame名].corr,直接调用它就能一次性得到所有变量之间的相关系数。可以直接检查其中有没有哪对变量相关性较高,自变量和他自己的相关性,因为他和他自己本身肯定是完全相关,所以这个可以忽略。
一般我们认为当不同变量之间相关系数的绝对值大于 0.8 的时候,可能导致严重贡献性,应该舍弃其中一个,只保留一个,所以我们检查的时候找大于 0.8 或小于- 0.8 的值即可。那因为我们只关注绝对值,大小正负其实无所谓。
如果你觉得一个个看数字还是麻烦,那还可以更直观可视化。那我们就可以把自变量之间的相关系数作为热力图数据,借助颜色一眼找到里面大的数值,那这里计算出来的相关系数都不高,所以可以保留所有自变量进入到下一个步骤。
当我们确保包含的自备量不会导致共线性后,下一步是调用 states models 点 API 里的 add constant 函数传入自变量作为参数,那这个步骤是用来干啥的呢?我们看线性回归模型的线性方程,每个字边上前面都有个系数,但除此之外还有 y 轴截距需要求值。这个结距可以被视为是另一个要求值的系数乘以常量一这个值,所以我们调用 ad constant 函数就是在把这个结句也纳入模型。如果没有这个步骤,回归结果里,我们只能得到线性方程里自变量的系数,结局就被视为 0 了,这样得到的模型不一定准确,因此这个步骤是需要的。
x=sm.add_constant(X)
现在自变量和因变量终于都准备好了,我们可以给 STAS models. API 的 OSL 函数,分别传入我们的因变量和自备量。注意是因变量在前面。 OSL 的全称是 ordinary s square s,就是我们之前接触到的最小二乘法,即根据残差最小平方和这个目标来寻找最优参数。
#3建立线性回归模型
model=Sm.OLS(y, x)
用后我们会得到一个线性回归模型的实例,但用模型去拟合数据的话,还要继续调用它的 fit方法。 fit执行完后,模型参数的结果就有了,可以先用一个变量去储存这个结果,如果要查看结果的话,直接打入 result 是没用的,它只是线性回归结果类的一个实例。但我们可以调用它的 summary 方法把结果进行汇总展示。这个 summary 是一个非常强大的方法,它会把所有和这个回归模型相关的数据都展示出来。
#建立线性回归模型,对数据进行拟合
result = sm.OLS(y, X).fit()
对结果进行汇总展示
result.summary()
我们要关注的是第二个表格里 coef 这一列。 Coif 是 coefficient 的意思,表示系数。所以要知道各个自备量在线性方程里的系数,就看 coef 那一列的值是什么。
在得到所有参数值以后,仍然需要去留意 p 值。p 值位于第二个表格,我们要看的是 p 大于 t 的绝对值,那一列的值在这个输出结果里面, p 值都小于0.05,说明这些自变量都是能预测因变量的关键因素。但是假如说其中有一个的 p 值大于我们设定的显著水平,说明它对因变量没有显著影响,我们可以把它从自变量中剔除,然后再去进行一轮线性回归,查看新的输出结果。那总之机器学习就是这样,很多时候没有标准答案,需要我们不断尝试调整验证。
那另外 r 方这个可用于判断模型拟合度的指标也非常贴心的直接帮我们计算了出来,它就位于最右上角, r 方的值越接近一说明模型对因变量变化的解释程度越高,也就是模型拟合度越好。
但得到线性违规模型不是我们的最终目的,我们的目的是能够利用这个模型去进行预测,也就是根据自变量们来预测未知的因变量预测的话,可以调用之前得到的回归结果的 predict 方法里面传入要预测的 data frame 数据,这个 data frame 要包含模型所有的自变量,不能多不能少。比如如果模型的自变量里包含某个虚拟变量的话,用来预测 data frame 里也要有对应的虚拟变量。如果模型包含截距的话,用来预测 data 分里也要有对应结句的常数。
result = sm.OLS(y, X).fit()
result.summary()4
result.predict(...)→预测未知数据
五.逻辑回归
逻辑回归专门用于处理二分类问题。二分类问题是指将数据集中的样本分为两类,比如把贷款申请人分为低风险和高风险。邮件分为非垃圾和垃圾等,和线性回归不同逻辑回归模型的输出不是任意数字,而是介于 0 和一之间。这个数字表示的是某事件会发生的概率, 0 表示不会发生,一表示会发生。举个例子,如果银行用逻辑回归预测某个申请人违约的概率是0.75,但应该考虑拒绝贷款申请,减少风险。
来看看这个模型拟合的方程长什么样。可以看出来和线性方程不一样,逻辑回归会拟合出一条有点像 s 的曲线,并且两端无限接近 0 和1。这个例子展示的是学生学习时长与考试考过概率之间的关系。如果我们看一个学习时长很长的数据点,可以看到,学生考过的概率就很高。我们看一个学习时长很短的数据点,可以看到学生考过的概率就很低,所以这个逻辑回归的拟合线是比较符合现实的。当学生根本没怎么学习时,我们基本上可以断定他考不过。但当学习时长再多一些的时候,是否考过就变得很难判断了,有可能一点点差别就导致两种不同的结果。
逻辑回归函数的方程是这样的:
逻辑回归我们和线性回归用的是同一模块
import statsmodels.api as sm
这个作为例子的数据,假设它是从肺癌患者和非肺癌患者中抽样的,包含了年龄、性别、是否抽烟这些自变量。那么性别和是否抽烟都是分类数据,我们需要创建虚拟变量,然而性别是否为男和性别是否为女这两个虚拟变量是完全相关的,因为它们之间是相反关系。性别是否为男和性别是否为女这两个虚拟变量是完全相关的,因为它们之间是相反关系。如果同时作为模型的自备量,就违反了自备量之间应该不相关的原则。
import statsmodels.api as sm
pd.get_dummies(data,
columns=["gender", "smoking"],
dtype=int,
drop_first=True)
在下一步,我们也要检查已有变量之间的相关性。可以直接使用corr 方法,一次性计算所有变量之间的相关系数,检查有没有其中哪两个变量相关性较高,即绝对值大于0.8。如果有的话,可以考虑只保留其中某一个,从而避免拟合时最大似然优化无法收敛得到最优解的问题。
一步是调用 States modelsAPI 里的 add constant 函数传入自变量作为参数。这个在学习线性回归的时候也见过,因为 线性回归和逻辑回归默认都不包含结句,所以我们要手动添加常数。在自变量和因变量都准备好了,我们可以给 states models 点 API 库的 logit函数,分别传入我们的因变量和自变量。这个 logi 就是用来构建逻辑回归模型的函数。调用后我们会得到一个线性回归模型的实例,但要去拟合数据的话,还要继续调用它的 fit方法, fit执行完毕后模型参数的结果就有了,我们可以先用一个比如叫 result 变量去储存这个结果。如果要查看结果的话,直接答应 result 是没用的,我们还是要调用它的 summary 方法查看输出。
#建立逻辑回归模型
result = sm.Logit(y, X).fit()
先还是看 p 值,这个可以告知我们哪些变量没有显著预测作用。如果我们把显著水平设定为0.05,那么这个结果里年龄和表示拮据的常数被判断为没有显著预测作用,而性别和是否抽烟有显著预测作用。但和线性回归不同的是,变量前面的系数并不直接代表倍数。要理解它的含义,我们要计算的是自然常数的次方。num py有一个函数叫EXP,可以直接用来计算自然常数的某次方,所以我们可以把num py也进行引入,调用时直接传入变量对应的系数。
那可以看到根据样本数据模型预测男性的肺癌概率是女性的 6 倍,吸烟的人的肺癌概率是不吸烟的人的 78 倍,当然这个只是根据有限的样本数据得出的结论,只是作为例子,不一定符合现实。那要拿这个模型去预测新数据的话,我们仍然是调用 predict 方法传入要预测的自变量组成的 data frame。和线性回归一样,传入的数据要包含模型里所有的自备量,不能多不能少,输出的结果会长成类似。