Skip to main content
Version: 2.17.1

训练房价预测模型

预测房价

使用的数据是一组房价信息的CSV样本数据。通过对已知数据的分析来预测未来的房价走势。本项目为Python实现。示例程序gitlab地址

数据理解和探索

数据位置:数据 数据科学家在拿到数据时,通常会先对数据对一些大致的了解,我们通过 Panda 的describe()获得统计信息如下:

统计信息:
longitude latitude housing_median_age total_rooms total_bedrooms population households median_income median_house_value
count 20640.000000 20640.000000 20640.000000 20640.000000 20433.000000 20640.000000 20640.000000 20640.000000 20640.000000
mean -119.569704 35.631861 28.639486 2635.763081 537.870553 1425.476744 499.539680 3.870671 206855.816909
std 2.003532 2.135952 12.585558 2181.615252 421.385070 1132.462122 382.329753 1.899822 115395.615874
min -124.350000 32.540000 1.000000 2.000000 1.000000 3.000000 1.000000 0.499900 14999.000000
25% -121.800000 33.930000 18.000000 1447.750000 296.000000 787.000000 280.000000 2.563400 119600.000000
50% -118.490000 34.260000 29.000000 2127.000000 435.000000 1166.000000 409.000000 3.534800 179700.000000
75% -118.010000 37.710000 37.000000 3148.000000 647.000000 1725.000000 605.000000 4.743250 264725.000000
max -114.310000 41.950000 52.000000 39320.000000 6445.000000 35682.000000 6082.000000 15.000100 500001.000000
前十行数据:
longitude latitude housing_median_age total_rooms total_bedrooms population households median_income median_house_value ocean_proximity
0 -122.23 37.88 41.0 880.0 129.0 322.0 126.0 8.3252 452600.0 NEAR BAY
1 -122.22 37.86 21.0 7099.0 1106.0 2401.0 1138.0 8.3014 358500.0 NEAR BAY
2 -122.24 37.85 52.0 1467.0 190.0 496.0 177.0 7.2574 352100.0 NEAR BAY
3 -122.25 37.85 52.0 1274.0 235.0 558.0 219.0 5.6431 341300.0 NEAR BAY
4 -122.25 37.85 52.0 1627.0 280.0 565.0 259.0 3.8462 342200.0 NEAR BAY
5 -122.25 37.85 52.0 919.0 213.0 413.0 193.0 4.0368 269700.0 NEAR BAY
6 -122.25 37.84 52.0 2535.0 489.0 1094.0 514.0 3.6591 299200.0 NEAR BAY
7 -122.25 37.84 52.0 3104.0 687.0 1157.0 647.0 3.1200 241400.0 NEAR BAY
8 -122.26 37.84 42.0 2555.0 665.0 1206.0 595.0 2.0804 226700.0 NEAR BAY
9 -122.25 37.84 52.0 3549.0 707.0 1551.0 714.0 3.6912 261100.0 NEAR BAY
....

通过分析,我们了解到:

  1. 数据总计20640条。
  2. 数据分为longitude,latitude,housing_median_age,total_rooms,total_bedrooms,population,households,median_income,median_house_value,ocean_proximity共10列。
  3. total_bedrooms列数据存在缺失,只有20433条
  4. ocean_proximity是字符串类型的,其他列为数字类型
  5. median_house_value为目标数据列,即需要预测的数据内容

进一步可视化分析数据频度:

数据频度

地理位置分布:

地理位置分布

数据预处理

数据通常无法直接用于训练,需要处理后,才能更好的用于模型的训练。 通过数据探索,我们对数据进行以下处理:

字符串转换

字符串不便于分析,因此我们现将字符串数据转换成数值数据。

通过使用LabelEncoder,替换内容为整数,再使用describe()查看效果:

count    20640.000000
mean 1.165843
std 1.420662
min 0.000000
25% 0.000000VV
50% 1.000000
75% 1.000000
max 4.000000
Name: ocean_proximity, dtype: float64

处理缺失数据

我们使用SimpleImputer,使用中位数进行填充,再使用describe()查看效果:

count    20640.000000
mean 536.838857
std 419.391878
min 1.000000
25% 297.000000
50% 435.000000
75% 643.250000
max 6445.000000
Name: total_bedrooms, dtype: float64

数据缩放

可以看到median_house_value的最大值是500001。而housing_median_age均为两位数。相差较大。在这种情况下,我们通常会对数据进行缩放。我们使用MinMaxScaler做归一化处理,将所有数据缩放在[0, 100]的范围内。

matplotlib前后进行对比,可以看出缩放后并不影响数据分布:

数据缩放对比

数据拆分

为得到预测模型,我们需要将所得到的数据划分成训练集测试集两个部分。

前者用来训练数据模型,后者用来对于模型进行测试和验证。

通常情况下,我们会用大部分的数据来训练,小部分的数据来测试。

在进行数据划分的时候,我们应该做到尽可能的随机。即:训练集和测试集都能尽可能的反应真实的数据模型。

我们使用sklearntrain_test_split进行数据随机和拆分的工作:

train_set, test_set = train_test_split(data, test_size=0.1, random_state=59)

这里的test_size指定了测试集的比例,random_state指定了随机数的种子。

这个函数会返回train_settest_set两个集合。前者占80%的数据,后者占20%

我们打印出了测试集的数据结果:

统计信息:
longitude latitude housing_median_age total_rooms total_bedrooms population households median_income median_house_value ocean_proximity
count 4128.000000 4128.000000 4128.000000 4128.000000 4128.000000 4128.000000 4128.000000 4128.000000 4128.000000 4128.000000
mean 47.597256 32.886500 54.654963 6.643256 8.273561 3.967818 8.178248 22.877475 39.183064 29.505814
std 19.858173 22.687445 24.855729 5.481836 6.598757 3.225293 6.414019 12.951767 23.913496 35.683441
min 0.896414 0.000000 1.960784 0.022890 0.046555 0.016817 0.032889 0.000000 0.000000 0.000000
25% 25.498008 14.771520 35.294118 3.662445 4.546865 2.177051 4.555172 13.901188 21.092903 0.000000
50% 58.416335 18.172157 54.901961 5.399563 6.734947 3.231593 6.660089 20.572130 32.989761 25.000000
75% 63.147410 55.047821 70.588235 7.918765 9.869646 4.881022 9.899688 28.798741 51.041233 25.000000
max 97.509960 98.618491 100.000000 82.977262 100.000000 80.055495 100.000000 100.000000 100.000000 100.000000
前十行数据:
longitude latitude housing_median_age total_rooms total_bedrooms population households median_income median_house_value ocean_proximity
9878 24.800797 43.464400 70.588235 0.854570 1.675978 0.639031 1.628022 14.009462 19.237240 0.0
4356 59.661355 16.471838 72.549020 5.483494 9.016139 2.965330 9.472126 16.995628 70.164865 0.0
1434 23.107570 57.810840 84.313725 3.184292 3.895096 1.387371 3.552047 20.366616 27.608340 75.0
6422 63.247012 16.896918 45.098039 6.566967 8.054004 5.229967 8.255221 19.201114 31.340283 25.0
1624 22.011952 56.323061 45.098039 5.414823 5.307263 2.441212 6.117415 35.413305 70.226721 75.0
1423 22.908367 58.023379 29.411765 2.754464 3.351955 0.989378 3.798717 12.732928 12.371289 75.0
4853 60.258964 15.834219 70.588235 7.068010 11.871508 7.239553 11.971715 9.355043 35.567070 0.0
16893 19.621514 53.560043 100.000000 4.328806 3.491620 1.872250 3.979609 54.968207 100.000000 100.0
4232 60.258964 16.578108 70.588235 13.487461 30.710739 10.908377 30.800855 10.808816 55.319566 0.0
19083 18.625498 61.424017 80.392157 5.351239 8.255742 3.189551 7.301431 18.020441 27.690814 0.0
....

可以看到测试集数据量正好为20%,且数据已经随机打乱。

建模并进行训练

当前的数据,需要我们将其余九个数值作为特征,来预测median_house_value的数值结果。我们使用scikit-learn已经提供好的算法模型,KNN模型k-Nearest Neighbor,来进行目标值的预测。

我们将需要预测的目标值与其他九个属性分离开,得到训练特征train_data,训练目标值train_value,测试特征train_data,测试目标值train_value

接下来我们就可以通过训练集来训练模型了,这里我们把模型所需的参数n作为超参数,尝试n在(1,31)之间,寻找出最佳的模型:

knn_reg = neighbors.KNeighborsRegressor(n)
knn_reg.fit(train_data, train_value)

有了训练好的模型我们就可以用它来进行数据的预测了。这也仅仅只需要一行代码即可:

predict_value = knn_reg.predict(test_data)

最后,我们可以将预测出的结果与实际结果进行对比。以确认我们的预测结果是否准确.

针对实际结果和预测结果各绘制了一个散点图和一个直方图。实际结果是蓝色的,预测结果是绿色的。散点图的点代表数值的大小,而直方图中能看出数值的出现频度。

其结果如下图所示:

测试集数据对比

指标度量

为了确保我们的对比结果是客观可度量的,我们需要采用更加精准的度量指标来帮助我们完成。

回归任务最常用的性能度量是均方误差(mean squared error,简称mse,越小越好),R方(R Squared,简称r2,越大越好,最大是1),均方根误差(Root Mean Squard Error,简称rmse,越小越好)。

我们使用scikit-learnnumpy进行计算后得出结果如下:

rmse:12.449454761714701, mae:8.506994764126478, r2: 0.7289061067771968

交叉验证

由于数据样本不多,我们使用scikit-learn提供的交叉验证来进行模型的比较,找出更优的超参数n,我们记录每种超参数下模型cross_val_score的算数平均值,对比结果如下:

交叉验证

可以得到最佳的超参数n=时,模型最优

通过小波AI全流程管控

现在你已经了解如何训练出你的模型了。但是AI模型的建立和使用,其实是需要数据科学家、算法专家等人员不断地进行试验不断优化的一个过程。如何避免数据流失,模型离散化,管理过程中产生的大量数据和模型信息,是比较困难的一件事情。 但现在只需几步修改,就可以在小波AI平台上实现统一管理了。

管理数据

统一上传训练所需数据到平台进行管控和使用。方便数据科学家、算法专家等不同角色可以更好的实现协同。

  1. 菜单选择 数据中心-数据集管理;
  2. 添加文件类型的数据集,上传房价数据; 上传房价数据
  3. 可以直接查看数据集的数据详情信息; 数据详情
  4. 示例所需数据已上传。 已上传

打包重用你的模型

之前你已经有了模型代码,只需再使用平台约定的代码依赖项入口点,即可完成代码打包,其他数据科学家和算法工程师都可以再平台轻松地重用你的模型。

系统默认使用conda作为系统开发环境,代码依赖包文件约定为conda.yaml,代码入口脚本和参数文件约定为MLproject,均为yaml语法。参考示例代码中内容。

依赖项默认命名为conda.yaml:根据代码环境添加对应的依赖即可,支持配置镜像加速,数据格式符合conda规约,详见官方说明

name: house_price_example
dependencies:
- python=3.7.5
- pip:
- numpy==1.16.5
- scikit-learn==0.22.2.post1
- pandas==0.25.3
- matplotlib==3.2.1

入口点约定为MLproject

指定对应conda文件名称,默认conda.yaml;command为平台运行的脚本;参数使用click标准进行传递;

name: house_price_example
conda_env: conda.yaml
entry_points:
main:
parameters:
min_n: {type: int, default: "1"}
max_n: {type: int, default: "31"}
command: "python train.py -min={min_n} -max={max_n}"

管理模型过程数据

参考示例代码train.py

  1. 添加好配置后,就可以在代码中接收入口脚本的参数了,使用click语法

    入参

  2. 记录模型参数 调用log_param()后,平台会帮你记录对应参数,此数据为常量,不可更改;

    mlflow.log_param("split", 0.2)
    mlflow.log_param("random", True)
    mlflow.log_param("scale", "MinMaxScaler")
    mlflow.log_param("algorithm", "k-nearest neighbors")
    mlflow.log_param("Imputation", "median")
  3. 记录模型指标 调用log_metric()后,平台会帮你记录对应指标,此数据值为float类型;

    mlflow.log_metric("r2", float(r2))
    mlflow.log_metric("rmse", float(rmse))
    mlflow.log_metric("mae", float(mae))
    mlflow.log_metric("cv_score_mean", float(scores.mean()))
  4. 记录过程数据文件 过程中我们生成的文件如果需要,平台都可以完成记录。使用保存文件夹log_artifacts(local_dir,remote_dir)保存文件夹log_artifact(local_path,remote_path),我们就可以轻松的把预处理后的数据以及过程中产生的图片都一起保存下来。

    # 保存文件目录到模型库中
    mlflow.log_artifacts("./image/", "image")
    mlflow.log_artifacts("./data/", "data")
  5. 现在你的算法程序已经可以在平台轻松管理起来了

Git代码协同

  1. 系统支持在资源中心配置添加自己的主机和代码托管(当前为gitlab)地址。实现了代码程序的协同版本管理,并可以共享团队的算力资源。

    资源中心

  2. 示例程序默认提供了ML1设备和wai-examples代码库,可以直接使用体验,在模型中可以直接选择

    代码库选择

管理应用模型

在平台中,你可以以应用的形式,实现应用内部模型的共享和协同开发。

  1. 菜单选择 应用中心-应用管理-添加应用

    添加应用

  2. 菜单选择 模型中心-模型管理-添加模型,选择示例代码

    添加模型

在平台训练模型

在平台训练你的模型,参数为自动读取入口脚本所得,不填为默认值,元数据选择之前的数据集文件,执行对象选择ML1主机,提交训练。

添加模型

点击模型名称,进入模型的详情页,可以看到模型正在训练中,点击详情,进入当前这次训练(实验)的信息面板中

模型详情

在平台中可以看到所属模型,使用的数据来源,训练所需的参数,以及当前运行的状态等面板信息,同时也可以监控当前每一个运行的超参数的结果

实验详情

监控训练的整个过程

  1. 平台提供了完整的日志信息,方便你实时查看模型训练的状态:

    查看日志

    日志

  2. 同时我们记录的参数和指标在每次的运行中都有记录;

    运行记录

  3. 可以根据指标内容来进行排序,找到你所需的模型:

    排序

  4. 选择你要比较的运行记录项,平台提供指标的数据可视化对比:

    统计对比

    对比图

后续步骤

恭喜你!你已经可以在平台上训练你的模型了。

下一步,让我们一起了解如何将已训练完成的模型在平台进行模型校验。