博主得分不是很高(55%),后期还需进一步探讨,先做一个阶段性小结。有不对的地方还需多多指教。
先导入可能用到的模块
import pandas as pd
import numpy as np
import math
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.decomposition import PCA
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import r2_score, mean_squared_error, mean_absolute_error
from sklearn.metrics import accuracy_score
from sklearn.preprocessing import MinMaxScaler,StandardScaler
import pandas_profiling
from keras import models
from keras import layers
from keras import optimizers
import xgboost as xgb
- 按照常规先读取数据,查看相关性。由于Id对房价没有影响,而相关性矩阵图中Id与SalePrice的相关性排在第31位,故选择相关性更强的30个特征
train_csv = 'F:/kaggle/House_Prices/data/train.csv'
test_csv = 'F:/kaggle/House_Prices/data/test.csv'
df_train = pd.read_csv(train_csv)
df_test = pd.read_csv(test_csv)
#相关性矩阵热力图
corrmat = df_train.corr()
plt.subplots(figsize=(12,9))
sns.heatmap(corrmat, vmax=0.9, square=True)
#查看影响最终价格的十个变量
k = 31 # 去掉SalePrice一共30个特征
plt.figure(figsize=(12,9))
cols = corrmat.nlargest(k, 'SalePrice')['SalePrice'].index
cm = np.corrcoef(df_train[cols].values.T)
sns.set(font_scale=1.25)
hm = sns.heatmap(cm, cbar=True, annot=True, square=True, fmt='.2f', annot_kws={'size': 10}, yticklabels=cols.values, xticklabels=cols.values)
plt.show()
- 将选取特征的训练集标准化、归一化
- 对于测试集采用同样的方式标准化、归一化
(标准化测试集的数据时需要采用训练集的均值和标准差,否则会导致数据泄露,使得模型泛化性降低,虽然Kaggle上很多kernel都是一开始就将训练集和测试集拼接在一起,但是个人认为有必要防止一下)
label = df_train['SalePrice']
df_train = df_train[cols].drop('SalePrice',axis = 1)
df_train = df_train.fillna(df_train.mean())
#将训练集标准化、归一化
scaler1 = StandardScaler()#标准化
scaler2 = MinMaxScaler()#归一化
scaler1.fit(df_train)
scaler2.fit(df_train)
df_train = scaler1.transform(df_train)
df_train = scaler2.transform(df_train)
df_train = pd.DataFrame(df_train)
df_train.columns = cols.drop('SalePrice')
df_train.info()
df_train.head()
- 根据散点图删除异常值(这里可能有些主观,但是结果确实会好一些),主要删除不符合常理的值(例如面积更大而价格更低则考虑删除等)
sns.pairplot(data, size = 2.5)
plt.show();
data = pd.DataFrame(data)
data=data[data['GrLivArea']<=-0.062]
data=data[data['TotalBsmtSF']<=0.002]
data=data[data['1stFlrSF']<=-0.075]
data=data[data['MasVnrArea']<=0.005]
data=data[data['BsmtFinSF1']<=0.002]
data=data[data['LotFrontage']<=-0.04]
data=data[data['LotArea']<=-0.006025]
data=data[data['MiscVal']<=0.001]
data.info()
- 观察SalePrice分布不均匀,考虑对其取对数
plt.hist(data['SalePrice'],bins = 20)
label_log = data['SalePrice']
label_log = label_log.apply(lambda x : np.log(x+1))
plt.hist(label_log,bins = 20)
- 接着将train划分为训练集和测试集,用不同模型测试结果
#划分训练集和测试集
train_x,test_x,train_y,test_y = train_test_split(train_data,label_log,test_size = 0.25)
#XGBoost模型—————————score最高为0.90左右
rfr = xgb.XGBRegressor(max_depth=6, learning_rate=0.1, n_estimators=160, silent=False)
rfr.fit(train_x,train_y)
print("rfr.score为:", rfr.score(test_x,test_y).mean())
rfr.fit(train_data,label_log)
#RandomForest模型—————————score最高为0.88左右
rfr1 = RandomForestRegressor()
rfr1.fit(train_x,train_y)
rfr1_y_predict = rfr1.predict(test_x)
print("rfr.score为:", rfr1.score(test_x,test_y).mean())
- 最后将测试集预测的结果逆运算变回原始SalePrice即可
需要改进的问题
- 特征提取较为粗糙,若时间充足逐个击破为好。后期尝试采用get_dummies和PCA来综合特征,效果可能会不一样。
- 对于XGBoost算法只能是会调用,没有更深层次的理解,初衷是将多个模型融合提高分数。
- sklearn模块使用并不是很熟练,接触此类问题有必要系统认识一下sklearn、keras等机器学习模块。在熟悉比赛整套流程后,则需要进一步思考如何改进模型