【机器学习】最经典案例:房价预测(完整流程:数据分析及处理、模型选择及微调)

环境:anaconda+jupyter notebook

文章目录

*
数据处理前导:
(一)、数据分析

+ 1、收集数据
+ 2、查看数据结构
+ 3、划分数据集
+ 4、数据相关性可视化
(二)、数据清洗

+ 1、缺失值
+ 2、文本/分类属性
+ 3、自定义转换器
+ 4、特征缩放
+ 5、封装成流水线
(三)、模型选择

+ 1、线性模型
+ 2、决策树
+ 3、随机森林
(四)、模型微调
(五)、预测结果

数据处理前导:

首先要明白一点:
数据决定模型的上限!数据决定模型的上限!数据决定模型的上限!(重要的事情说三遍。)对于数据的处理在一个完整案例中花费精力的比重应该占到一半以上。
以下分为:数据分析、数据清洗两部分。
数据分析主要包括:查看数据内容(行列意义)、属性(数值型、类别型)、非空值数量、属性自身分布、属性之间的关联度、属性与预测目标值之间的关联度高低等。
数据清洗包括:1)数值型的缺省值处理办法、2)文本/类别型数据处理办法3)自定义处理数据方法、4)特征缩放处理、5)对于以上几种方法的封装

(一)、数据分析

这一部分你可以看成是操作数据的一些常用工具罗列,一些是必要的,一些是不必要的,但都可以帮助你更好的了解你的数据。

1、收集数据(必要)->2、查看数据(5个常用函数)->3、分割训练、测试数据(必要)->4、数据相关性及可视化

1、收集数据

创建一个小函数来实现实时下载数据包,不仅可以获取实时数据,而且很方便查看数据。

import os
import tarfile
import urllib

DOWNLOAD_ROOT = "https://raw.githubusercontent.com/ageron/handson-ml2/master/"
HOUSING_URL = DOWNLOAD_ROOT + "datasets/housing/housing.tgz"
HOUSING_PATH = os.path.join("datasets", "housing")

def fetch_housing_data(housing_url = HOUSING_URL, housing_path = HOUSING_PATH):
    os.makedirs(housing_path, exist_ok = True)
    tgz_path = os.path.join(housing_path, "housing.tgz")
    urllib.request.urlretrieve(housing_url, tgz_path)
    housing_tgz = tarfile.open(tgz_path)
    housing_tgz.extractall(path = housing_path)
    housing_tgz.close()

fetch_housing_data()

至此,已经下载好了数据集。

接下来,需要加载你下载好的数据,将数据的pandas DataFrame对象作为返回。

import pandas as pd

def load_housing_data(housing_path = HOUSING_PATH):
    csv_path = os.path.join(housing_path, "housing.csv")
    return pd.read_csv(csv_path)
housing = load_housing_data()

至此,已经将数据加载到housing中,可以对housing进行一系列数据操作了。

2、查看数据结构

共介绍了5个常用函数,注释包含了每个函数实现的功能。

housing.head()

【机器学习】最经典案例:房价预测(完整流程:数据分析及处理、模型选择及微调)
housing.info()

【机器学习】最经典案例:房价预测(完整流程:数据分析及处理、模型选择及微调)
housing.describe()

【机器学习】最经典案例:房价预测(完整流程:数据分析及处理、模型选择及微调)
%matplotlib inline

import matplotlib.pyplot as plt
housing.hist(bins = 50, figsize = (20,15))
plt.show()

【机器学习】最经典案例:房价预测(完整流程:数据分析及处理、模型选择及微调)
housing["ocean_proximity"].value_counts()

【机器学习】最经典案例:房价预测(完整流程:数据分析及处理、模型选择及微调)

至此,我们用一些常用函数查看了数据的一些有用信息。

接下来,我们要划分数据集,分为训练集和测试集两份。测试集比例设为20%。

3、划分数据集

划分方式是灵活的,可以自定义划分数据集,或者调用sklearn提供的train_test_spllit()方法都是可以的。但这种随机划分数据集的方式容易导致数据是有偏的,即存在验本偏差。(举个栗子:某地区一家公司要给1000个人打电话调研一些问题,已知该地区男女比例6:4,那么调查的样本中也应该包含6成男性、4成女性,否则将会存在抽样偏差。)

所以这里介绍分层抽样,一种常用的抽样方法:
分层抽样的前提是要直到对于样本分布的一个重要指标是什么(就像上面的例子中直到==知道该地区的男女比例很重要一样),那么从领域专家那里了解到收入中位数对于房价中位数的预测有重要作用。然而,收入中位数是一个连续值属性,需要先把它进行区间划分,转为类别属性,再从每个类中进行抽样。


import numpy as np
housing["income_cat"] = pd.cut(housing["median_income"], bins = [0., 1.5, 3., 4.5, 6., np.inf], labels = [1, 2, 3, 4, 5])
housing["income_cat"].hist()

【机器学习】最经典案例:房价预测(完整流程:数据分析及处理、模型选择及微调)

至此,已经将income_cat属性从数值型转化为类别型。

接下来,需要进行分层抽样:


from sklearn.model_selection import StratifiedShuffleSplit
split = StratifiedShuffleSplit(n_splits = 1, test_size = 0.2, random_state = 42)
for train_index, test_index in split.split(housing, housing["income_cat"]):
    strat_train_set = housing.loc[train_index]
    strat_test_set = housing.loc[test_index]

strat_test_set["income_cat"].value_counts()/len(strat_test_set)

【机器学习】最经典案例:房价预测(完整流程:数据分析及处理、模型选择及微调)
至此,已经完成了分层抽样,将数据集划分为了strat_train_set、strat_test_set。

接下来,这个类别属性就用不到了,删掉即可:


for set_ in (strat_train_set, strat_test_set):
    set_.drop("income_cat", axis = 1, inplace = True)

4、数据相关性可视化

首先拷贝一份训练数据集的副本,以免伤害原始数据。


housing = strat_train_set.copy()

接下来,查看房价和地理位置(x,y)和人口密度s的关系:(图中横轴表示经度,纵轴表示维度,圆的半径大小代表了人口数量,颜色从蓝到红表示房价由低到高。)


housing.plot(kind = "scatter", x = "longitude", y = "latitude", alpha = 0.4,
             s = housing["population"]/100, label = "population", figsize = (10,7),
             c = "median_house_value", cmap = plt.get_cmap("jet"), colorbar = True,
            )
plt.legend()

【机器学习】最经典案例:房价预测(完整流程:数据分析及处理、模型选择及微调)
从图中可以初步判断:沿海地区的房价要偏高一些,当然也会受到人口等其他因素的影响。

接下来,寻找数据之间的相关性,这里主要查看房价与所有属性之间的相关性:


corr_matrix = housing.corr()

corr_matrix["median_house_value"].sort_values(ascending = False)

【机器学习】最经典案例:房价预测(完整流程:数据分析及处理、模型选择及微调)
可以看出前四行:median_income、total_rooms、housing_median_age与median_house_value的相关度还是挺高的。

接下来,看一下他们几个之间的相关性如何:

from pandas.plotting import scatter_matrix

attributes = ["median_house_value", "median_income", "total_rooms", "housing_median_age"]
scatter_matrix(housing[attributes], figsize = (12,8))

【机器学习】最经典案例:房价预测(完整流程:数据分析及处理、模型选择及微调)
从图中可以看出median_house_value和median_income呈现较为明显的线性相关性。(也印证了:前文所说的从领域专家那里了解到房价和收入中位数有较强的相关性。)

接下来,我们从已有属性中创造一些新的属性,或许新的属性可以和房价之间有较好的相关性,这个相关系数或许会高于已知属性和房价的相关系数。


housing["rooms_per_household"] = housing["total_rooms"]/housing["households"]
housing["bedrooms_per_room"] = housing["total_bedrooms"]/housing["total_rooms"]
housing["population_per_household"] = housing["population"]/housing["households"]
corr_matrix = housing.corr()
corr_matrix["median_house_value"].sort_values(ascending = False)

【机器学习】最经典案例:房价预测(完整流程:数据分析及处理、模型选择及微调)
从结果上可以看出rooms_per_household比一些已有属性具有和房价更高的相关性。所以这个属性或许对我们之后的房价预测起到一定帮助。

(二)、数据清洗

前文介绍了很多关于数据的一些常规操作,这些操作一些是可选的,但可以帮助更好的理解数据。
接下来,是比较重要的数据清洗。
主要介绍几种方法适用于不同情况,最后介绍如何将这些清洗操作封装起来。(封装起来的目的是,训练集、测试集都需要执行清洗一系列操作,封装好可以直接调用,更加简洁)

1、缺失值

对于含有空值的列(如前文交代的total_bedroom列),通常可以采取3种方法: 1)放弃缺失值相应的区域、2)放弃含缺失值的列、3)用中位数/0/均值来代替缺失值。
然而,前两种方法对于数据来说无疑是一种浪费,这里介绍如何用第三种方法,完成缺失值填补。
首先,还是将训练集拷贝下来,注意是训练集。
用drop()和copy()将数据集的标签分离出来,即分理出x,y。


housing  = strat_train_set.drop("median_house_value", axis = 1)
housing_labels = strat_train_set["median_house_value"].copy()
housing.info()

【机器学习】最经典案例:房价预测(完整流程:数据分析及处理、模型选择及微调)
从结果中可以看到:训练集的x为16512*9的,其中total_bedrooms有空值。

接下来,开始用中位数填补空值:
根据sklearn提供的SimpleImputer类,很方便的用中位数填补空值。(助记:0.创建类1.fit() 2.transform())

from sklearn.impute import SimpleImputer
imputer = SimpleImputer(strategy = "median")
housing_num = housing.drop("ocean_proximity", axis = 1)
imputer.fit(housing_num)

X = imputer.transform(housing_num)
housing_tr = pd.DataFrame(X, columns = housing_num.columns, index = housing_num.index)

housing_tr.info()

【机器学习】最经典案例:房价预测(完整流程:数据分析及处理、模型选择及微调)
至此,已经填补好了数值类型的缺失值。

2、文本/分类属性

由于计算机没办法处理文本类型的属性,所以需要对其进行编码,转化为数学表达。常用的编码方式有:转化为数字类别,一种是转化为独热码。
如果转化为 数字编码:从(一)数据分析->2、查看数据结构->函数5可知:ocean_proximity属性共有5种类别,即为0~4,但是这里引入了一个不友好的因素,就是数字相近的类别具有较高的相似度(通俗来说就是,一个样本如果在类别1或2之间徘徊,如果最后评分的时候把它归为了1类,但是它其实含有和类别2相似的因素。)
所以,这里介绍采用 独热码的形式进行编码:
根据sklearn提供的OneHotEncoder类,很方便的用中位数填补空值。(助记:0.创建类1.fit() 2.transform(),1.2可以合并)


from sklearn.preprocessing import OneHotEncoder
housing_cat = housing[["ocean_proximity"]]

cat_encoder = OneHotEncoder()
housing_cat_1hot = cat_encoder.fit_transform(housing_cat)
housing_cat_1hot

housing_cat_1hot.toarray()

【机器学习】最经典案例:房价预测(完整流程:数据分析及处理、模型选择及微调)

至此,完成了对文本/分类属性的编码。

3、自定义转换器

可以根据需要自定义一些转换器,来处理数据,把不论是任何形式的数据,最终都变成数学表达。
在此案例中主要用于处理我们后来新创建的几个联合属性。

from sklearn.base import BaseEstimator, TransformerMixin
rooms_ix, bedrooms_ix, population_ix, household_ix = 3,4,5,6
class CombinedAttributesAdder(BaseEstimator, TransformerMixin):
    def __init__(self, add_bedrooms_per_room = True):
        self.add_bedrooms_per_room = add_bedrooms_per_room
    def fit(self, X, y = None):
        return self
    def transform(self, X):
        rooms_per_household = X[:, rooms_ix]/X[:, household_ix]
        population_per_household = X[:, population_ix]/ X[:, household_ix]
        if self.add_bedrooms_per_room :
            bedrooms_per_room = X[:, bedrooms_ix]/ X[:, rooms_ix]
            return np.c_[X, rooms_per_household, population_per_household, bedrooms_per_room]
        else:
            return np.c_[X, rooms_per_household, population_per_household]
attr_adder = CombinedAttributesAdder(add_bedrooms_per_room = False)
housing_extra_attribs = attr_adder.transform(housing.values)

4、特征缩放

如果输入的数值属性具有较大的比例差异,那么非常必要将其进行缩放。
常用的缩放方法有:01缩放、标准化。
0-1缩放:(x-Min)/(Max-Min)
非常简单,但是容易受到异常值的影响。(举个栗子:本来属性值大部分处于0~ 15之间,突然有一个异常值为100,那么缩放之后大部分的属性值被缩放到0~ 0.15之间,而不是0~ 1之间。)
标准化:(x-均值)/方差
不容易受到异常值的影响。
所以本案例采用标准化方式:根据sklearn提供的standardScaler类,很方便的进行属性缩放。(在后文应用)

5、封装成流水线

将以上几个步骤封装起来,便于对任意数据集处理。
先把数值型数据的操作封装起来,在把数值型和文本/分类型属性一起封装。
首先,根据sklearn提供的Pipeline类,进行初步封装。


from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler

num_pipeline = Pipeline([
    ('imputer', SimpleImputer(strategy = "median")),
    ('attribs_adder', CombinedAttributesAdder()),
    ('std_scaler', StandardScaler()),
])
housing_num_tr = num_pipeline.fit_transform(housing_num)

housing_num_tr = pd.DataFrame(housing_num_tr)
print(housing_num_tr.info(0))

【机器学习】最经典案例:房价预测(完整流程:数据分析及处理、模型选择及微调)
至此封装好了数值型数据的处理。
接下来,根据sklearn提供的ColumnTransformer类进行进一步的封装。
from sklearn.compose import ColumnTransformer
num_attribs = list(housing_num)
cat_attribs = ["ocean_proximity"]

full_pipeline = ColumnTransformer([
    ("num", num_pipeline, num_attribs),
    ("cat", OneHotEncoder(), cat_attribs),
])
housing_prepared = full_pipeline.fit_transform(housing)

至此,将所有的数据清洗操作全部封装在了full_pipeline中。

以上(一)、(二)完成了所有对训练数据集的操作。

(三)、模型选择

1、线性模型

from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error
lin_reg = LinearRegression()
lin_reg.fit(housing_prepared, housing_labels)
housing_predictions = lin_reg.predict(housing_prepared)
lin_mse = mean_squared_error(housing_labels, housing_predictions)
lin_rmse = np.sqrt(lin_mse)
print(lin_rmse)

【机器学习】最经典案例:房价预测(完整流程:数据分析及处理、模型选择及微调)
结果坏掉了,欠拟合:1.选择更大的模型2.选择更好的特征3.减少对模型的限制,如去掉正则化。
线性模型-交叉验证:
from sklearn.model_selection import cross_val_score

lin_scores = cross_val_score(lin_reg, housing_prepared, housing_labels,scoring = "neg_mean_squared_error", cv = 10)
lin_rmse_scores = np.sqrt(-lin_scores)
print("LinearRegression")
display_scores(lin_rmse_scores)

【机器学习】最经典案例:房价预测(完整流程:数据分析及处理、模型选择及微调)

2、决策树

from sklearn.tree import DecisionTreeRegressor
tree_reg = DecisionTreeRegressor()
tree_reg.fit(housing_prepared, housing_labels)
housing_predictions = tree_reg.predict(housing_prepared)
tree_mse = mean_squared_error(housing_labels, housing_predictions)
tree_rmse = np.sqrt(tree_mse)
print(tree_rmse)

【机器学习】最经典案例:房价预测(完整流程:数据分析及处理、模型选择及微调)
训练集上结果太好,猜测严重过拟合:1.选择简单模型2.收集更多训练数据3.减少训练噪声。
决策树-交叉验证:
from sklearn.model_selection import cross_val_score

scores = cross_val_score(tree_reg, housing_prepared, housing_labels, scoring = "neg_mean_squared_error", cv = 10)
tree_rmse_scores = np.sqrt(-scores)

def display_scores(scores):
    print("Scores:", scores)
    print("Mean:", scores.mean())
    print("Standard deviation:", scores.std())

print("DecisionTreeRegressor:")
display_scores(tree_rmse_scores)

【机器学习】最经典案例:房价预测(完整流程:数据分析及处理、模型选择及微调)
发现决策树如果采用交叉验证的话,评分7万,说明在整个测试集上确实过拟合。

3、随机森林

from sklearn.ensemble import RandomForestRegressor
forest_reg = RandomForestRegressor()
forest_reg.fit(housing_prepared, housing_labels)
housing_predictions = forest_reg.predict(housing_prepared)
forest_mse = mean_squared_error(housing_labels, housing_predictions)
forest_rmse = np.sqrt(forest_mse)
print(forest_rmse)

【机器学习】最经典案例:房价预测(完整流程:数据分析及处理、模型选择及微调)
随机森林-交叉验证:
from sklearn.model_selection import cross_val_score

forest_scores = cross_val_score(forest_reg, housing_prepared, housing_labels, scoring = "neg_mean_squared_error", cv =10)
forest_rmse_scores = np.sqrt(-forest_scores)
print("RandomForestRegressor:")
display_scores(forest_rmse_scores)

【机器学习】最经典案例:房价预测(完整流程:数据分析及处理、模型选择及微调)
随机森林单看rmse的值,似乎很有戏,但依旧比交叉验证的评分低很多,意味着模型也是过拟合。
不论如何,相比于前两种模型,表现稍好,所以接下来将随机森林应用于案例。

(四)、模型微调

常用的模型微调方法就是网格搜索。
根据sklearn提供的GridSearchCV类,告知其超参数有哪些、需要尝试的参数值,他就会根据交叉验证来评估所有超参数的可能组合。

from sklearn.model_selection import GridSearchCV
from sklearn.ensemble import RandomForestRegressor
param_grid = [
    {'n_estimators': [3, 10, 30], 'max_features': [2, 4, 6, 8]},
    {'bootstrap': [False], 'n_estimators': [3, 10], 'max_features': [2, 3, 4]},
]
forest_reg = RandomForestRegressor()
grid_search = GridSearchCV(forest_reg, param_grid, cv = 5, scoring = 'neg_mean_squared_error', return_train_score = True)

grid_search.fit(housing_prepared, housing_labels)

grid_search.best_params_

【机器学习】最经典案例:房价预测(完整流程:数据分析及处理、模型选择及微调)
得到最终的最优的一组超参数,使用的数据不同,该结果也会有不同。

(五)、预测结果

将上面选出的最好的超参数对应的模型应用于测试数据。
首先还是现将测试数据及进行标签分离,然后应用前面封装好的数据清洗流水线full_pipeline进行处理,接下来便可用于房价预测:

final_model = grid_search.best_estimator_
X_test = strat_test_set.drop("median_house_value", axis = 1)
y_test = strat_test_set["median_house_value"].copy()

X_test_prepared = full_pipeline.transform(X_test)
final_predictions = final_model.predict(X_test_prepared)

final_mse = mean_squared_error(y_test, final_predictions)
final_rmse = np.sqrt(final_mse)
print(final_rmse)

【机器学习】最经典案例:房价预测(完整流程:数据分析及处理、模型选择及微调)
得到的测试集上的评分往往会略逊于之前交叉验证的表现结果。虽然这里的结果并非如此,但也不要再调整超参数了,因为即使改变在泛化到新数据时也没有什么用了。

至此,整个案例的流程就走完了。

Original: https://blog.csdn.net/weixin_44820505/article/details/125889661
Author: Rosyy_
Title: 【机器学习】最经典案例:房价预测(完整流程:数据分析及处理、模型选择及微调)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/726859/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • python pytest框架

    一、pytest单元测试框架 1. 什么是单元测试框架单元测试是指在软件开发当中,针对软件的最小单位(函数、方法)进行正确性的检查测试。2.单元测试框架Java:junit和tes…

    Python 2023年9月13日
    039
  • Python matplotlib.pyplot 五种常见图形参数

    plt.scatter(x, y, s, c, marker, cmap, norm, alpha, linewidths, edgecolorsl) x: x数据 y: y轴数据…

    Python 2023年9月1日
    061
  • Pygame-飞机大战

    1.游戏介绍 1.1 游戏的基本设定 敌方共有大中小3款飞机,分别为高中低三中速度,自己还可以设置一个游戏等级窗口,来改变自己刚开始进入游戏时难度等级; 子弹的射程并非全屏,而大概…

    Python 2023年9月18日
    030
  • Python中常用的文本转义及编码

    每种语言都有其关键字和保留字符,这样为了能这些特殊字符能正常显示,就需要转义,如Python中\n代表回车,HTML中 代表空格等等。Python中的”是转义控制符,如…

    Python 2023年11月9日
    050
  • Pluggy源码解读—-pluggy源码解读基础准备

    【原文链接】Pluggy源码解读—-pluggy源码解读基础准备 解读pluggy源码,直接使用pytest环境中安装的pluggy即可,比如这里安装的pluggy版本…

    Python 2023年9月12日
    031
  • 遥感影像语义分割难点对应解决思路

    目录 一、像素级精度问题 1. 结合多尺度特征 1.1 空洞卷积 1.2 转置卷积和跳跃连接 1.3 将边缘图集成到分割 2. 基于数据融合的策略 2.1 结合几何和光谱信息来提高…

    Python 2023年9月26日
    043
  • python多线程同步售票系统解决思路

    解决问题场景:假如剩余1000张电影票需要售卖,同时有10家电影App来售卖这1000张电影票。主要的逻辑实现过程是什么,要求使用python技术栈进行解题? 【阅读全文】 1、分…

    Python 2023年5月24日
    068
  • Git:使用conda命令切换虚拟环境(win10)

    目录 1. 问题:在win10电脑的Git中,无法使用conda list命令,也无法使用conda activate base命令激活虚拟环境。 2. 解决: 1)解决在Git中…

    Python 2023年9月7日
    057
  • PYQT5实现图片显示、通过滚轮缩放图片、通过鼠标拖动图片移动,搞懂所有细节

    本文在这篇文章的基础上进行优化: 首先要说明2个重要细节:一般触发paintEvent事件的有如下几种原因: 窗口显隐导致重画窗口大小(重新调整)改变,或者重新排布(布局)导致重画…

    Python 2023年8月3日
    053
  • Conda环境的打包与再创建(其他:pip)

    前提条件:在 conda 环境中,所有包都是 pip 安装 2. 使用 conda 通过 txt 文件先创建一个纯净的 python 虚拟环境conda create &#8211…

    Python 2023年9月8日
    047
  • Python案例实操3-电影数据分析

    Python案例实操3-电影数据分析 一、读取数据 二、数据处理 * 1.索引重命名 2.合并数据集 3.选取子集 4.缺失值处理 5.数据格式转换 三、数据分析及可视化 * 1….

    Python 2023年9月29日
    038
  • 最长上升子序列

    最长上升子序列 一、题目描述 二、思路分析 * 1、问题分析 2、思路分析 – (1)状态转移方程 + 状态表示 状态转移 (2)循环设计 三、代码实现 一、题目描述 …

    Python 2023年10月8日
    049
  • redis队列去重_Python程序员面试必备——分布式爬虫scrapy+redis解析

    最近有许多小伙伴向我私信,说最近准备跳槽,但是面试的机会比较少,好不容易得到面试机会,由于技术点的匮乏,面试直接被刷掉。 根据反馈,很多面试都问到了 分布式爬虫,今天小编就给大家讲…

    Python 2023年10月5日
    057
  • Python数据分析案例10——北向资金流入与沪深300涨跌幅分析

    博主本科是学投资的,最近看了b站邢不行up主的一些量化策略视频,和自己本科毕业论文很像,便想自己也来做一下这个实操的项目。 案例背景 北向资金是从中国最南方——中国香港流入内陆的资…

    Python 2023年8月17日
    089
  • Mindspore-训练模型

    前言 MindSpore:新一代AI开源计算框架。 创新编程范式,AI科学家和工程师更易使用,便于开放式创新 ;该计算框架可满足终端、边缘计算、云全场景需求,能更好保护数据隐私 ;…

    Python 2023年10月7日
    043
  • 初识Python系列(三)

    对于Python selenium操作的总结(三) —— 利用本地储存cookies自动化登录任意网站(在此以b站为示例) 一、思路 自动化登录网站的方式有三种: 与人机识别硬刚,…

    Python 2023年11月10日
    049
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球