文章目录
- 机器学习-随机森林算法预测房租模型
- 解决问题
- 数据集
- 探索性数据分析
- 数据预处理
- 构建模型并训练
- 结果分析与评估
- 参数调优
- 结果预测
- 模型保存
- 经验总结
- 参考文章
机器学习-随机森林算法预测房租模型
解决问题
根据待租房源相关信息,通过随机森林机器学习算法构件预测模型,预测房租。属于机器学习监督学习中的回归问题。
数据集
数据集来源
https://www.datacastle.cn/taskIndex.html?id=2
探索性数据分析
# 1.1 简单查看 前几行和统计信息
print(df.head())
print(df.describe())
结果如下:
ID 位置 出租方式 区 卧室数量 卫的数量 厅的数量 地铁站点 地铁线路 小区名 小区房屋出租数量 居住状态 \
0 0 118.0 NaN 11.0 1 1 1 4.0 2.0 3072 128.90625 NaN
1 1 100.0 NaN 10.0 1 0 0 5.8 4.0 3152 132.81250 NaN
2 2 130.0 NaN 12.0 2 2 1 3.7 5.0 5575 42.96875 NaN
3 3 90.0 NaN 7.0 3 2 2 6.3 2.0 3103 85.93750 NaN
4 4 31.0 NaN 3.0 2 1 1 NaN NaN 5182 214.84375 NaN
总楼层 房屋朝向 房屋面积 时间 楼层 装修情况 距离 Label
0 23.636364 东南 86.279378 1 2 NaN 76.416667 5.602716
1 38.181818 东 170.456802 1 1 NaN 70.916667 16.977929
2 29.090909 东南 105.925190 1 0 NaN 57.250000 8.998302
3 58.181818 南 191.989407 1 2 NaN 65.833333 5.602716
4 54.545455 东北 104.270109 1 0 NaN NaN 7.300509
ID 位置 出租方式 区 \
count 196539.000000 196508.000000 24230.000000 196508.000000
mean 98269.000000 67.945982 0.900289 7.905139
std 56736.066616 43.522394 0.299621 4.025696
min 0.000000 0.000000 0.000000 0.000000
25% 49134.500000 33.000000 1.000000 4.000000
50% 98269.000000 61.000000 1.000000 9.000000
75% 147403.500000 103.000000 1.000000 11.000000
max 196538.000000 152.000000 1.000000 14.000000
统计信息太长了,只粘贴部分
#查看每列直方图
import matplotlib.pyplot as plt
df.hist()
plt.rcParams['font.sans-serif'] = ['FangSong']
plt.show()
结果如下:
可以通过直方图查看每列数据分布情况
数据预处理
# 2.1 查看缺失值列 为true表示有缺失值
print(df.isnull().any())
结果如下:
ID False
位置 True
出租方式 True
区 True
卧室数量 False
卫的数量 False
厅的数量 False
地铁站点 True
地铁线路 True
小区名 False
小区房屋出租数量 True
居住状态 True
总楼层 False
房屋朝向 False
房屋面积 False
时间 False
楼层 False
装修情况 True
距离 True
Label False
dtype: bool
缺失值处理一般有两种方式,删除和填充:
删除
:删除掉含缺失值的列
填充
:使用均值、0值、或者其他规则填充缺失值
先来看删除
print('删除之前行数', df.shape[0])
df1 = df.dropna()
print('删除之后行数', df1.shape[0])
结果如下:
删除之前行数 196539
删除之后行数 6711
删除后,数据集数量锐减,模型训练数据集越大越好,所以,不能采取删除策略
下面看下填充
填充的话,要根据字段实际含义理解去选择用啥填充,连续值列可以选择使用列均值去填充,离散值列,暂时没想好策略,但肯定不能使用均值,例如装修情况列,低(0)中(1)高(2),还有的列本来确实存在缺失值,例如地铁站点列,并不是所有小区都有地铁站点。
情况比较复杂,缺失值暂先不处理。
下面看字符(汉字)列处理,一般处理方式是使用独热编码,将字符转成数值
# 将字符值转成数值
df = pd.get_dummies(df)
下面看数据分割,
features = df.loc[:, df.columns != 'Label']
labels = df.loc[:, 'Label']
# 数据分割
from sklearn.model_selection import train_test_split
train_features, test_features, train_labels, test_labels = train_test_split(features, labels, test_size=0.2,random_state=1)
构建模型并训练
# 建立模型
from sklearn.ensemble import RandomForestRegressor
rf = RandomForestRegressor(random_state=1, n_jobs=2)
rf.fit(train_features, train_labels)
结果分析与评估
# 评估
def evaluate(model, test_features, test_labels):
import numpy as np
pre = model.predict(test_features)
errors = abs(pre - test_labels)
print('误差是:', round(np.mean(errors), 2))
# 得分
score = model.score(test_features, test_labels)
print('score:', score)
import sklearn.metrics as sm
print('MAE是:', sm.mean_absolute_error(pre, test_labels))
print('MSE是:', sm.mean_squared_error(pre, test_labels))
print('RMSE是:', np.sqrt(sm.mean_squared_error(pre, test_labels)))
evaluate(rf, test_features, test_labels)
将分析评估代码抽成了函数,直接调用函数
结果如下:
误差是: 0.64
score: 0.9298738756799909
MAE是: 0.6418076884170861
MSE是: 2.8114669514602704
RMSE是: 1.6767429592696284
参数调优
定义模型参数优化函数,根据训练数据集,训练性能最佳的模型,并返回训练好的最佳模型,如下:
# 定义模型参数调优化函数
def randomfit(train_features, train_labels):
# # 建立模型
rf = RandomForestRegressor(random_state=1, n_jobs=2)
n_estimators = [int(x) for x in np.linspace(start=100, stop=1000, num=10)]
max_features = [1.0, 'sqrt', 'log2']
max_depth = [int(x) for x in np.linspace(10, 200, 10)]
max_depth.append(None)
min_samples_split = [2, 5, 10]
min_samples_leaf = [1, 2, 4]
bootstrap = [True, False]
random_grid = {'bootstrap': bootstrap,
'max_depth': max_depth,
'max_features': max_features,
'min_samples_leaf': min_samples_leaf,
'min_samples_split': min_samples_split,
'n_estimators': n_estimators
}
rf_random = RandomizedSearchCV(estimator=rf, param_distributions=random_grid, n_iter=100,scoring='neg_mean_absolute_error', cv=3, verbose=2, random_state=42)
rf_random.fit(train_features, train_labels)
return rf_random.best_estimator_
定义模型评估函数,如下:
# 定义评估函数
def evaluate(model, test_features, test_labels):
import numpy as np
pre = model.predict(test_features)
errors = abs(pre - test_labels)
print('误差是:', round(np.mean(errors), 2))
# 得分
score = model.score(test_features, test_labels)
print('score:', score)
import sklearn.metrics as sm
print('MAE是:', sm.mean_absolute_error(pre, test_labels))
print('MSE是:', sm.mean_squared_error(pre, test_labels))
print('RMSE是:', np.sqrt(sm.mean_squared_error(pre, test_labels)))
执行模型优化函数和评估函数,如下:
import numpy as np
from sklearn.model_selection import RandomizedSearchCV
from sklearn.ensemble import RandomForestRegressor
#调用优化函数
model = randomfit(train_features,train_labels)
#调用评估函数
evaluate(model, test_features, test_labels)
由于数据量大,本人笔记本内存不足,无法跑出结果,暂时不贴结果了。
可以同时参考其他文章
机器学习-随机森林温度预测模型优化
结果预测
在使用数据集中无标签数据集进行预测时,遇到一个问题,记录如下:
在数据预处理阶段,朝向列是字符,要进行独热编码,独热编码是根据列字符的种类数进行增加对应列,
训练数据集和无标签数据集的朝向列字符种类是不一样的,这就导致,使用无标签数据集进行预测时,报错提示相关列没有训练 或者 训练的相关列没有输入。
暂时没找到合适解决方式,记录下来,后续再来更新。。。
模型保存
完成模型训练后,通常需要将模型持久化,即保存模型到磁盘,以便将来可以重新加载和使用,而无需重新训练。
from joblib import dump, load
# 模型持久化 到磁盘
dump(model,'D:/XXX/租房价格预测/rf.onnx')
输出存储的路径
# 装载已保存的模型文件,进行评估
model1 = load('D:/XXX/租房价格预测/rf.onnx')
evaluate(model1, test_features, test_labels)
输出如下:
误差是: 0.64
score: 0.9298738756799909
MAE是: 0.6418076884170861
MSE是: 2.8114669514602704
RMSE是: 1.6767429592696284
可以看到,和上面评估结果一致的。
模型持久化的格式问题
- 跨平台格式:ONNX、PMML
- 非跨平台格式:joblib
经验总结
1、数据预处理阶段,数据缺失值处理,要根据数据集实际含义,去选择合适的处理方式
2、机器学习模型训练评估,实际工作量会在数据探索性分析和数据预处理环节,至于建模和训练只需调用封装好的函数即可
参考文章
机器学习-随机森林温度预测模型优化
机器学习-随机森林算法预测温度
pandas数据分析常用函数(持续更新)