房产估值模型训练及预测结果

0.下载数据集

本文房产估值模型源数据为厦门市房价数据,文件下载链接: https://pan.baidu.com/s/1vOact6MsyZZlTSxjmMqTbw 密码: 8zg6
下载文件打开后如下图所示:

文件打开图示.png

从上图中可以看出数据已经经过简单的处理,只需要再稍微调整就可以投入模型的训练中。

1.MLPR和GBR模型对比

df_y = df['unitPrice']得到DataFrame的unitPrice字段数据;
y = df_y.values得到shape为(21935,),类型为numpy.ndarray的矩阵,即长度为21935的一维矩阵;
df_x = df.drop(['unitPrice'],axis=1)得到DataFrame的除了unitPrice字段的其他字段;
x = df_x.values得到shape为(21935,120),类型为numpy.ndarray的矩阵,即大小为21935*120的二维矩阵。
用sklearn中的预处理函数preprocessing.StandardScaler()对数据标准化处理,处理过程是先用训练集fit,再把测试集也标准化处理。
调用MLPRegresso()获得多层感知器-回归模型,再用训练集进行训练,最后对测试集进行测试得分。
调用GradientBoostingRegressor()获得集成-回归模型,再用训练集进行训练,最后对测试集进行测试得分。

from sklearn.model_selection import train_test_split
from sklearn import preprocessing
from sklearn.neural_network import MLPRegressor
from sklearn.ensemble import GradientBoostingRegressor
import pandas as pd

#boston = load_boston()
df = pd.read_excel("数据处理结果.xlsx")
df_y = df['unitPrice']
df_x = df.drop(['unitPrice'],axis=1)
x = df_x.values
y = df_y.values

train_x,test_x,train_y,test_y = train_test_split(x,y,train_size=0.8,\
                                                  random_state=33)
ss_x = preprocessing.StandardScaler()
train_x1 = ss_x.fit_transform(train_x)
test_x1 = ss_x.transform(test_x)

ss_y = preprocessing.StandardScaler()
train_y1 = ss_y.fit_transform(train_y.reshape(-1,1))
test_y1 = ss_y.transform(test_y.reshape(-1,1))

model_mlp = MLPRegressor(solver='lbfgs',hidden_layer_sizes=(20,20,20),random_state=1)
model_mlp.fit(train_x1,train_y1.ravel())
mlp_score = model_mlp.score(test_x1,test_y1.ravel())
print("sklearn多层感知器-回归模型得分",mlp_score)

model_gbr = GradientBoostingRegressor()
model_gbr.fit(train_x1,train_y1.ravel())
gbr_score = model_gbr.score(test_x1,test_y1.ravel())
print("sklearn集成-回归模型得分",gbr_score)

打印的结果是:

sklearn多层感知器-回归模型得分 0.683941816792
sklearn集成-回归模型得分 0.762351806857

对于第一次调整模型,这个结果还可以接受。

2.异常值处理

image.png

从图中我们可以看到有的房子单价达到几十上百万,这种异常值需要删除。
暂时没有发现可以直接调用处理异常值的函数,所以需要自己写。下面的代码中定义了一个cleanOutlier函数,函数的功能主要是删除异常值。首先得清楚下四分位数和上四分位数的概念:例如总共有100个数,中位数是从小到大排序第50个数的值,低位数是从小到大排序第25个数,高位数是从小到大排序第75个数。
四分位距是上四分位数减下四分位数所得值,例如:上四分位数为900,下四分位数为700,则四分位距为200
异常值指的是过大或者过小的值。在我们这个删除异常值的方法中,低于(下四分位数-3四分位距)的值或者高于(上四分位数+3四分位距)的值会被判定为异常值并删除。例如,上四分位数为900,下四分位数为700,则低于100或者高于1500的数被删除。
将DataFrame转换为ndarray只需要用df.values就可以获得,训练模型时数值类型一般为float,所以用df.values.astype('float')来获得浮点类型数值的矩阵。
cleanOutlier函数删除异常值,然后把第0列负值给y变量,把1列到最后一列赋值给x变量
因为x大多是1-hot编码,所以不需要再进行标准化。

from sklearn.model_selection import train_test_split
from sklearn import preprocessing
from sklearn.neural_network import MLPRegressor
from sklearn.ensemble import GradientBoostingRegressor
import pandas as pd

def cleanOutlier(data,column,mul=3):
    data = data[data[:,column].argsort()] #得到排序后的ndarray
    l = len(data)
    low = int(l/4)
    high = int(l/4*3)
    lowValue = data[low,column]
    highValue = data[high,column]
    print("下四分位数为{}  上四分位数{}".format(lowValue,highValue))
    if lowValue - mul * (highValue - lowValue) < data[0,column] :
        delLowValue = data[0,column]
    else:
        delLowValue = lowValue - mul * (highValue - lowValue)
    if highValue + mul * (highValue - lowValue) > data[-1,column]:
        delHighValue = data[-1,column]
    else:
        delHighValue = highValue + mul * (highValue - lowValue)
    print("删除第{}列中数值小于{}或者大于{}的部分".format(column,\
          delLowValue,delHighValue))
    for i in range(low):
        if data[i,column] >= delLowValue:
            recordLow = i 
            break
    for i in range(len(data)-1,high,-1):
        if data[i,column] <= delHighValue:
            recordHigh = i
            break
    #打印处理异常值的相关信息
    print("原矩阵共有{}行".format(len(data)),end=',')
    print("保留{}到{}行".format(recordLow,recordHigh),end=',')
    data = data[recordLow:recordHigh+1]
    print("删除第{}列中的异常值后剩余{}行".format(column,\
          recordHigh+1-recordLow))
    return data

df = pd.read_excel("数据处理结果.xlsx")
data = df.values.astype('float')
data = cleanOutlier(data,0)
x = data[:,1:]
y = data[:,0]

train_x,test_x,train_y,test_y = train_test_split(x,y,train_size=0.8,\
                                                  random_state=33)

ss_y = preprocessing.StandardScaler()
train_y = ss_y.fit_transform(train_y.reshape(-1,1))
test_y = ss_y.transform(test_y.reshape(-1,1))

model_mlp = MLPRegressor(solver='lbfgs',hidden_layer_sizes=(20,20,20),random_state=1)
model_mlp.fit(train_x,train_y.ravel())
mlp_score = model_mlp.score(test_x,test_y.ravel())
print("sklearn多层感知器-回归模型得分",mlp_score)

model_gbr = GradientBoostingRegressor(learning_rate=0.1)
model_gbr.fit(train_x,train_y.ravel())

ss_y = preprocessing.StandardScaler()
train_y = ss_y.fit_transform(train_y.reshape(-1,1))
test_y = ss_y.transform(test_y.reshape(-1,1))

gbr_score = model_gbr.score(test_x,test_y.ravel())
print("sklearn集成-回归模型得分",gbr_score)

打印的结果是:

sklearn多层感知器-回归模型得分 0.795028773029
sklearn集成-回归模型得分 0.767157061712

对于第二次调整模型,我们可以看到sklearn多层感知器-回归模型得分明显提高,而对于sklearn集成-回归模型则没有太大提高。总之,这次异常值处理是成功的。

3.正态化

正态化就是将y的值以e为底取对数,得到新的一列赋值给y。
正态化用一个循环完成:for i in range(len(y)): y[i] = math.log(y[i])
正态化之后按照原理是不用再标准化了,但是经过实验,对x,y标准化都可以提高得分。

from sklearn.model_selection import train_test_split
from sklearn import preprocessing
from sklearn.neural_network import MLPRegressor
from sklearn.ensemble import GradientBoostingRegressor
import pandas as pd
import math

def cleanOutlier(data,column,mul=3):
    data = data[data[:,column].argsort()] #得到排序后的ndarray
    l = len(data)
    low = int(l/4)
    high = int(l/4*3)
    lowValue = data[low,column]
    highValue = data[high,column]
    print("下四分位数为{}  上四分位数{}".format(lowValue,highValue))
    if lowValue - mul * (highValue - lowValue) < data[0,column] :
        delLowValue = data[0,column]
    else:
        delLowValue = lowValue - mul * (highValue - lowValue)
    if highValue + mul * (highValue - lowValue) > data[-1,column]:
        delHighValue = data[-1,column]
    else:
        delHighValue = highValue + mul * (highValue - lowValue)
    print("删除第{}列中数值小于{}或者大于{}的部分".format(column,\
          delLowValue,delHighValue))
    for i in range(low):
        if data[i,column] >= delLowValue:
            recordLow = i 
            break
    for i in range(len(data)-1,high,-1):
        if data[i,column] <= delHighValue:
            recordHigh = i
            break
    #打印处理异常值的相关信息
    print("原矩阵共有{}行".format(len(data)),end=',')
    print("保留{}到{}行".format(recordLow,recordHigh),end=',')
    data = data[recordLow:recordHigh+1]
    print("删除第{}列中的异常值后剩余{}行".format(column,\
          recordHigh+1-recordLow))
    return data

df = pd.read_excel("数据处理结果.xlsx")
data = df.values.astype('float')
data = cleanOutlier(data,0)
x = data[:,1:]
y = data[:,0]
for i in range(len(y)):
    y[i] = math.log(y[i])
    
train_x,test_x,train_y,test_y = train_test_split(x,y,train_size=0.8,\
                                                  random_state=33)

ss_x = preprocessing.StandardScaler()
train_x = ss_x.fit_transform(train_x)
test_x = ss_x.transform(test_x)

ss_y = preprocessing.StandardScaler()
train_y = ss_y.fit_transform(train_y.reshape(-1,1))
test_y = ss_y.transform(test_y.reshape(-1,1))

model_mlp = MLPRegressor(solver='lbfgs',hidden_layer_sizes=(20,20,20),random_state=1)
model_mlp.fit(train_x,train_y.ravel())
mlp_score = model_mlp.score(test_x,test_y.ravel())
print("sklearn多层感知器-回归模型得分",mlp_score)

model_gbr = GradientBoostingRegressor(learning_rate=0.1)
model_gbr.fit(train_x,train_y.ravel())
gbr_score = model_gbr.score(test_x,test_y.ravel())
print("sklearn集成-回归模型得分",gbr_score)

打印的结果是:

sklearn多层感知器-回归模型得分 0.831448099649
sklearn集成-回归模型得分 0.780133207248

相比较于前一次,分数又得到了提高,是一次成功的调整。

4.交叉验证

主要使用的是sklearn.model_selection中的KFold方法选择训练集和测试集
kf = KFold(n_splits=5,shuffle=True)这一行代码初始化KFold对象
for train_index,test_index in kf.split(x):这一行代码可以看出kf.split(x)得到的是一个长度为n_splits的列表,即长度为5的列表,列表中元素是元组,元组中的元素是训练集和测试集的索引。

from sklearn import preprocessing
from sklearn.neural_network import MLPRegressor
from sklearn.ensemble import GradientBoostingRegressor
import pandas as pd
import math
from sklearn.model_selection import KFold

def cleanOutlier(data,column,mul=3):
    data = data[data[:,column].argsort()] #得到排序后的ndarray
    l = len(data)
    low = int(l/4)
    high = int(l/4*3)
    lowValue = data[low,column]
    highValue = data[high,column]
    print("下四分位数为{}  上四分位数{}".format(lowValue,highValue))
    if lowValue - mul * (highValue - lowValue) < data[0,column] :
        delLowValue = data[0,column]
    else:
        delLowValue = lowValue - mul * (highValue - lowValue)
    if highValue + mul * (highValue - lowValue) > data[-1,column]:
        delHighValue = data[-1,column]
    else:
        delHighValue = highValue + mul * (highValue - lowValue)
    print("删除第{}列中数值小于{}或者大于{}的部分".format(column,\
          delLowValue,delHighValue))
    for i in range(low):
        if data[i,column] >= delLowValue:
            recordLow = i 
            break
    for i in range(len(data)-1,high,-1):
        if data[i,column] <= delHighValue:
            recordHigh = i
            break
    #打印处理异常值的相关信息
    print("原矩阵共有{}行".format(len(data)),end=',')
    print("保留{}到{}行".format(recordLow,recordHigh),end=',')
    data = data[recordLow:recordHigh+1]
    print("删除第{}列中的异常值后剩余{}行".format(column,\
          recordHigh+1-recordLow))
    return data

df = pd.read_excel("数据处理结果.xlsx")
data = df.values.astype('float')
data = cleanOutlier(data,0)
x = data[:,1:]
y = data[:,0]
for i in range(len(y)):
    y[i] = math.log(y[i])

kf = KFold(n_splits=5,shuffle=True)

for train_index,test_index in kf.split(x):
    train_x = x[train_index]    
    test_x = x[test_index]
    train_y = y[train_index]
    test_y = y[test_index]
 
    ss_x = preprocessing.StandardScaler()
    train_x = ss_x.fit_transform(train_x)
    test_x = ss_x.transform(test_x)
    
    ss_y = preprocessing.StandardScaler()
    train_y = ss_y.fit_transform(train_y.reshape(-1,1))
    test_y = ss_y.transform(test_y.reshape(-1,1))
    
    model_mlp = MLPRegressor(solver='lbfgs',hidden_layer_sizes=(20,20,20),random_state=1)
    model_mlp.fit(train_x,train_y.ravel())
    mlp_score = model_mlp.score(test_x,test_y.ravel())
    print("sklearn多层感知器-回归模型得分",mlp_score)
    
    model_gbr = GradientBoostingRegressor(learning_rate=0.1)
    model_gbr.fit(train_x,train_y.ravel())
    gbr_score = model_gbr.score(test_x,test_y.ravel())
    print("sklearn集成-回归模型得分",gbr_score)

打印结果是:

sklearn多层感知器-回归模型得分 0.8427725943791746
sklearn集成-回归模型得分 0.7915684454283963
sklearn多层感知器-回归模型得分 0.8317854959807023
sklearn集成-回归模型得分 0.7705608099963528
sklearn多层感知器-回归模型得分 0.8369280445356948
sklearn集成-回归模型得分 0.7851823734454625
sklearn多层感知器-回归模型得分 0.8364897250676866
sklearn集成-回归模型得分 0.7833199279062474
sklearn多层感知器-回归模型得分 0.8335782493590231
sklearn集成-回归模型得分 0.7722233325504181

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 230,501评论 6 544
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 99,673评论 3 429
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 178,610评论 0 383
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 63,939评论 1 318
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 72,668评论 6 412
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 56,004评论 1 329
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 44,001评论 3 449
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 43,173评论 0 290
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 49,705评论 1 336
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 41,426评论 3 359
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 43,656评论 1 374
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 39,139评论 5 364
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 44,833评论 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 35,247评论 0 28
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 36,580评论 1 295
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 52,371评论 3 400
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 48,621评论 2 380

推荐阅读更多精彩内容