多元线性回归模型预测房价

一、基础包与数据导入

导入需要用到的包

import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt

读取数据

df = pd.read_csv('house_prices.csv')

部分数据如图
在这里插入图片描述

二、数据清洗

1.常用数据清洗方法

数字异常值|Numeric Outlier

数字异常值方法是一维特征空间中最简单的非参数异常值检测方法,异常值是通过IQR(InterQuartile Range)计算得的。计算第一和第三四分位数(Q1、Q3),异常值是位于四分位数范围之外的数据点x i:使用四分位数乘数值k=1.5,范围限制是典型的上下晶须的盒子图。这种技术是使用KNIME Analytics Platform内置的工作流程中的Numeric Outliers节点实现的。

Z-score

Z-score是一维或低维特征空间中的参数异常检测方法。该技术假定数据是高斯分布,异常值是分布尾部的数据点,因此远离数据的平均值。距离的远近取决于使用公式计算的归一化数据点z i的设定阈值Zthr:其中xi是一个数据点,μ是所有点xi的平均值,δ是所有点xi的标准偏差。然后经过标准化处理后,异常值也进行标准化处理,其绝对值大于Zthr。Zthr值一般设置为2.5、3.0和3.5。该技术是使用KNIME工作流中的行过滤器节点实现的。

2.函数实现

函数定义

# 异常值处理
# ================ 异常值检验函数:iqr & z分数 两种方法 =========================
def outlier_test(data, column, method=None, z=2):
    """ 以某列为依据,使用 上下截断点法 检测异常值(索引) """
    """ 
    full_data: 完整数据
    column: full_data 中的指定行,格式 'x' 带引号
    return 可选; outlier: 异常值数据框 
    upper: 上截断点;  lower: 下截断点
    method:检验异常值的方法(可选, 默认的 None 为上下截断点法),
            选 Z 方法时,Z 默认为 2
    """
    # ================== 上下截断点法检验异常值 ==============================
    if method == None:
        print(f'以 {column} 列为依据,使用 上下截断点法(iqr) 检测异常值...')
        print('=' * 70)
        # 四分位点;这里调用函数会存在异常
        column_iqr = np.quantile(data[column], 0.75) - np.quantile(data[column], 0.25)
        # 1,3 分位数
        (q1, q3) = np.quantile(data[column], 0.25), np.quantile(data[column], 0.75)
        # 计算上下截断点
        upper, lower = (q3 + 1.5 * column_iqr), (q1 - 1.5 * column_iqr)
        # 检测异常值
        outlier = data[(data[column] <= lower) | (data[column] >= upper)]
        print(f'第一分位数: {q1}, 第三分位数:{q3}, 四分位极差:{column_iqr}')
        print(f"上截断点:{upper}, 下截断点:{lower}")
        return outlier, upper, lower
    # ===================== Z 分数检验异常值 ==========================
    if method == 'z':
        """ 以某列为依据,传入数据与希望分段的 z 分数点,返回异常值索引与所在数据框 """
        """ 
        params
        data: 完整数据
        column: 指定的检测列
        z: Z分位数, 默认为2,根据 z分数-正态曲线表,可知取左右两端的 2%,
           根据您 z 分数的正负设置。也可以任意更改,知道任意顶端百分比的数据集合
        """
        print(f'以 {column} 列为依据,使用 Z 分数法,z 分位数取 {z} 来检测异常值...')
        print('=' * 70)
        # 计算两个 Z 分数的数值点
        mean, std = np.mean(data[column]), np.std(data[column])
        upper, lower = (mean + z * std), (mean - z * std)
        print(f"取 {z} 个 Z分数:大于 {upper} 或小于 {lower} 的即可被视为异常值。")
        print('=' * 70)
        # 检测异常值
        outlier = data[(data[column] <= lower) | (data[column] >= upper)]
        return outlier, upper, lower

调用函数

outlier, upper, lower = outlier_test(data=df, column='price', method='z')
outlier.info(); outlier.sample(5)

清洗数据后数据大小如图
在这里插入图片描述
原数据大小如图
在这里插入图片描述
删除错误数据

df.drop(index=outlier.index, inplace=True)

三、分析数据

通过热力图查看变量之间的相关性

# 热力图 
def heatmap(data, method='pearson', camp='RdYlGn', figsize=(10 ,8)):
    """
    data: 整份数据
    method:默认为 pearson 系数
    camp:默认为:RdYlGn-红黄蓝;YlGnBu-黄绿蓝;Blues/Greens 也是不错的选择
    figsize: 默认为 10,8
    """
    ## 消除斜对角颜色重复的色块
    #     mask = np.zeros_like(df2.corr())
    #     mask[np.tril_indices_from(mask)] = True
    plt.figure(figsize=figsize, dpi= 80)
    sns.heatmap(data.corr(method=method), \
                xticklabels=data.corr(method=method).columns, \
                yticklabels=data.corr(method=method).columns, cmap=camp, \
                center=0, annot=True)
    # 要想实现只是留下对角线一半的效果,括号内的参数可以加上 mask=mask

函数调用

由于只能分析数值变量之间的相关性,所以 style 与 neighborhood 两者与 price 的关系未知

heatmap(data=df, figsize=(6,5))

热力图如图
在这里插入图片描述

四、拟合

1.引入模型

## 利用回归模型中的方差分析
## 只有 statsmodels 有方差分析库
## 从线性回归结果中提取方差分析结果
import statsmodels.api as sm
from statsmodels.formula.api import ols # ols 为建立线性回归模型的统计学库
from statsmodels.stats.anova import anova_lm

注意点
在这里插入图片描述

2.建模

代码:

from statsmodels.formula.api import ols

lm = ols('price ~ area + bedrooms + bathrooms', data=df).fit()
lm.summary()

结果:
在这里插入图片描述

3.模型优化

# 设置虚拟变量
# 以名义变量 neighborhood 街区为例
nominal_data = df['neighborhood']

# 设置虚拟变量
dummies = pd.get_dummies(nominal_data)
dummies.sample()  # pandas 会自动帮你命名

# 每个名义变量生成的虚拟变量中,需要各丢弃一个,这里以丢弃C为例
dummies.drop(columns=['C'], inplace=True)
dummies.sample()

# 将结果与原数据集拼接
results = pd.concat(objs=[df, dummies], axis='columns')  # 按照列来合并
results.sample(3)
# 对名义变量 style 的处理可自行尝试

效果如图
在这里插入图片描述

4.再次建模

代码:

lm = ols('price ~ area + bedrooms + bathrooms + A + B', data=results).fit()
lm.summary()

结果:
在这里插入图片描述

5.处理多元共线性

自定义方差膨胀因子的检测公式

def vif(df, col_i):
    """
    df: 整份数据
    col_i:被检测的列名
    """
    cols = list(df.columns)
    cols.remove(col_i)
    cols_noti = cols
    formula = col_i + '~' + '+'.join(cols_noti)
    r2 = ols(formula, df).fit().rsquared
    return 1. / (1. - r2)

函数调用

test_data = results[['area', 'bedrooms', 'bathrooms', 'A', 'B']]
for i in test_data.columns:
    print(i, '\t', vif(df=test_data, col_i=i))

输出结果
在这里插入图片描述
发现bedrooms 和 bathrooms 这两个变量的方差膨胀因子较高,也印证了方差膨胀因子大多成对出现的原则,这里我们丢弃膨胀因子较大的 bedrooms 即可

再次拟合

lm = ols(formula='price ~ area + bathrooms + A + B', data=results).fit()
lm.summary()

结果
在这里插入图片描述
还是存在多元共线性

再次进行多元共线性检测

test_data = df[['area', 'bathrooms']]
for i in test_data.columns:
    print(i, '\t', vif(df=test_data, col_i=i))

输出结果
在这里插入图片描述
精度没变,但具体问题还是需要结合具体业务来分析

参考

【经典案例】 | 多元线性回归模型预测房价(附Python代码与数据)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值