利用Python建立回归模型来预测房价

最近在做DC竞赛上面的房价预测,因为题目要求用回归分析,而数据自变量有13列,因此采用多元回归分析。 在上网搜索过资料后,决定先分别用linearRegression和Statsmodels做一下看看效果。 之后有空会补上逐步回归的试验过程。

画图

先画散点图,看看数据的关系。

代码如下:

import xlrd
import matplotlib.pyplot as plt
import numpy as np

data = np.loadtxt(open(r'C:\Users\LENOVO\Desktop\kc_train.csv','r'), delimiter =",",skiprows=0)
#在Python中\是转义符,\u表示其后是UNICODE编码,因此\User在这里会报错,在字符串前面加个r表示就可以了

for i in range(3,14):
    plt.subplot(2,6,(i-2))                    #12个自变量,循环画子图
    plt.scatter(data[:,i],data[:,1])
    plt.title('x= %d'%i)
plt.show() 

效果如下:

建立回归模型

from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error

def linr(dtrain,dres,ztest):
    xtrain,xtest,ytrain,ytest = train_test_split(dtrain,dres,test_size=.3)
#把样本随机划分成训练集和测试集,test_size测试集占样本的比例
    regr=LinearRegression() 
    regr.fit(xtrain,ytrain)                #利用划分好的训练集进行回归
    ypred = regr.predict(xtest)            #对测试集进行预测
    zpred = regr.predict(ztest)
    MSE2 = mean_squared_error(ytest, ypred)    #题目以平武预测误差为评判标准,在此查看平均预测误差
    return (MSE2,zpred)

当然为了查看拟合效果,最直接的还是看图。

plt.figure()
plt.plot(ypred,'b',label = "predict")
plt.plot(ytest,'r',label = "fact")
plt.legend(loc = "upper right")
plt.show()

正是通过看图,才发现了,不对数据分段,直接拟合的话,高房价的根本无法预测出来。

数据处理及完整模型构建

因为发现高房价的无法预测,所以决定对数据分段回归。而且发现房价的高低主要受房屋面积的影响,因此,先对训练数据依据房价划分三段:(分两段和分三段都试过,但发现分三段的效果好很多。但是即使分了三段,高于500万的房价还是不能很好的拟合,说明高房价的预测需要综合很多因素,估计需要对因素设置权重,或者需要把经纬度具现化,根据房屋地段来设置权重。)

房价低于200万的,房价居于200万与500万之间的,高于500万的。

发现房屋面积的分水岭大概是3800和5000。因此对测试数据以房屋面积为依据划分为三段,并分别用对应的回归方程去拟合。

最后循环进行10次,分别保存在10个excel里,最后分别依据均值差取最优值。

完整代码:(把画图部分给去掉了)

import xlwt
import xlrd
from xlutils.copy import copy
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error

data = np.loadtxt(open(r'C:\Users\LENOVO\Desktop\kc_train.csv','r'), delimiter =",",skiprows=0)
#在Python中\是转义符,\u表示其后是UNICODE编码,因此\User在这里会报错,在字符串前面加个r表示就可以了
dset = np.loadtxt(open(r'C:\Users\LENOVO\Desktop\kc_test.csv','r'), delimiter =",",skiprows=0)    #读入数据
workbook = xlrd.open_workbook(r'C:\Users\LENOVO\Desktop\kc_test.xls') 
wb = copy(workbook)
ws = wb.get_sheet(0)

z  =dset[:,7]
y = data[:,1]
a = np.where((4000000>y)&(y>2000000))                  #划分数据
a1 = len(a[0])                                         #注意,a为元组类型,想知道数据的列数,需提取数组元素后,再求长度
b = np.where(y<2000000)
b1 = len(b[0])
e = np.where(y>4000000)
e1 = len(e[0])
c = np.where((5000>=z)&(z>=3800))
c1 = len(c[0])
d = np.where(z<3800)
d1 = len(d[0])
f = np.where(z>5000)
f1 = len(f[0])
              
d1r = data[a,2:13].reshape(a1,11)
d1e = data[a,1].reshape(-1,1)                     #需要置换
d2r = data[b,2:13].reshape(b1,11)
d2e = data[b,1].reshape(-1,1)
z1r = dset[c,1:12].reshape(c1,11)
z2r = dset[d,1:12].reshape(d1,11)
d3r = data[e,2:13].reshape(e1,11)
d3e = data[e,1].reshape(-1,1)
z3r = dset[f,1:12].reshape(f1,11)

def linr(dtrain,dres,ztest):
    xtrain,xtest,ytrain,ytest = train_test_split(dtrain,dres,test_size=.3)
    regr=LinearRegression() 
    regr.fit(xtrain,ytrain)               
    ypred = regr.predict(xtest)          
    zpred = regr.predict(ztest)
    MSE2 = mean_squared_error(ytest, ypred)   
    return (MSE2,zpred)
                                            
m = np.zeros((10,3))
for j in range(10):
    [m1,z1] = linr(d1r,d1e,z1r)
    m[j,0] =m1
    [m2,z2] = linr(d2r,d2e,z2r)
    m[j,1] =m2
    for i in range(c1):
        ws.write((c[0])[i], 14, str(z1[i]))                  #写入excel,并记录均值差
    for k in range(d1):
        ws.write((d[0][k]),14,str(z2[k]))
    [m3,z3] = linr(d3r,d3e,z3r)
    m[j,2] =m3
    for i in range(f1):
        ws.write((f[0])[i], 14, str(z3[i]))    
    wb.save(str(j)+'.xls')    
print(m)