基于python厦门思明区二手房价分析和预测


            基于python厦门思明区二手房价分析和构建基于机器学习的房价预测模型

一,选题背景

  网上有条段子,某地房价5w每平,月收入刚好过万,掐指一算,命中注定买房是不可能的,这辈子都不可能买房,所以要定个小目标:“我真的还想再活500年······”。当然,房子虽贵,但是我可以学学科学的方法了解房价趋势,做到心中有数,万一买的起呢?

 

二,设计方案

1,爬虫名称:基于python厦门思明区二手房价分析和预测

2,爬虫爬取的内容与数据特征分析:内容主要是:房屋信息;数据特征:房屋信息的归一化与存储

3,设计方案概述:房屋信息的爬取并归一化与存储,进行数据预处理与数据可视化,构建房价预测模型进行多特征模型训练,得到构建基于机器学习的房价预测模型结果

 

三,结果特征分析

1,利用网络爬虫获取厦门市思明区二手房信息

 

 

 

 

 

 

四,爬虫程序设计

1,数据爬取与采集

# 使用 HTML.parser 解析器

1 import requests
2 from bs4 import BeautifulSoup
3 # requests返回网页内容
4 res = requests.get(r'https://xm.esf.fang.com/house-a0352/')
5 #res.text
6 
7 # BeautifulSoup解析网页
8 soup = BeautifulSoup(res.text,'html.parser') # 使用 HTML.parser 解析器
 1 def get_house(url):
 2     '获取页面中每个房子的信息'
 3     information = {} # 存储房屋所有信息
 4     res = requests.get(url)
 5     soup = BeautifulSoup(res.text,'html.parser')
 6     
 7     # 获取户型、建筑面积、单价、朝向、楼层、装修情况
 8     houses = soup.select('.tab-cont-right .trl-item1') 
 9     #print(houses)
10     for house in houses:
11         me = house.text.strip().split('\n')
12         information[me[1]] = me[0].strip()
13     
14     # 获取小区名字
15     name = soup.select('.rcont .blue')
16     information['小区名称'] = name[0].text
17     
18     # 获取房屋总价
19     price = soup.select('.trl-item')
20     information['房屋总价'] = price[0].text
21     print(information)
22 
23 # 函数测试
24 get_house("https://xm.esf.fang.com/chushou/3_346676334.htm?channel=1,2&psid=1_15_60") # 每一页中房子的url(注意:链接可能失效)

 

 

 

 1 def get_page(n):
 2     '分页爬取数据'
 3     for i in range(1,n+1): # n:爬取页数
 4         url = r'https://xm.esf.fang.com/house-a0352/i3{}/'.format(i) # 总共多少页
 5         res = requests.get(url)
 6         houses = BeautifulSoup(res.text,'html.parser')
 7         print(url)
 8         j  = 1
 9         houses = houses.select('.shop_list .clearfix h4 a') # 获取每套房子的href
10         for house in houses:
11             try:
12                 demo_url = house['href']
13                 url = r'https://xm.esf.fang.com' + demo_url + '?channel=1,2&psid=1_{}_60'.format(j) # 每一页中有多少套房子
14                 # 获取当前页面中每套房子的信息
15                 #get_house(url) 
16                 j += 1
17             except Exception as e:
18                 print('-------->',e)
19 get_page(1)

 

 

 

房屋信息的归一化与存储

 1 import requests
 2 from bs4 import BeautifulSoup
 3 
 4 def get_house(url):
 5     '获取页面中每个房子的信息'
 6     information = {} # 存储房屋所有信息
 7     res = requests.get(url)
 8     soup = BeautifulSoup(res.text,'html.parser')
 9     
10     # 获取户型、建筑面积、单价、朝向、楼层、装修情况
11     houses = soup.select('.tab-cont-right .trl-item1') 
12     for house in houses:
13         m = house.text.strip().split('\n')
14         me = m[1]
15         if '朝向' in me:
16             me = me.strip('进门') 
17         if '楼层'in me:
18             me = me[0:2]
19         if '地上层数' in me:
20             me = '楼层'
21         if '装修程度' in me:
22             me = '装修'
23         information[me] = m[0].strip()
24     
25     # 获取小区名字
26     name = soup.select('.rcont .blue')
27     information['小区名称'] = name[0].text
28     
29     # 获取房屋总价
30     price = soup.select('.trl-item')
31     information['房屋总价'] = price[0].text
32     return information
33 
34 # 函数测试
35 get_house("https://xm.esf.fang.com/chushou/3_346676334.htm?channel=1,2&psid=1_15_60") # 每一页中房子的url

 

 

 

 1 import pandas as pd
 2 import time
 3 
 4 def get_page(i):
 5     '分页爬取数据'
 6     url = r'https://xm.esf.fang.com/house-a0352/i3{}/'.format(i) # 总共多少页
 7     res = requests.get(url)
 8     houses = BeautifulSoup(res.text,'html.parser')
 9     #print(url)
10     j  = 1
11     houses = houses.select('.shop_list .clearfix h4 a')
12     page_information = [] # 数据存储
13     for house in houses:
14         try:
15             demo_url = house['href']
16             url = r'https://xm.esf.fang.com' + demo_url + '?channel=1,2&psid=1_{}_60'.format(j) # 每一页中有多少套房子
17             # 获取当前页中每套房子的信息
18             information = get_house(url)
19             print('正在爬取第{}页第{}套房子···'.format(i,j),end='\r')
20             page_information.append(information)
21             j += 1
22             time.sleep(0.5) # 预防爬取频繁,防止ip被封
23         except Exception as e:
24             print('-------->',e)
25     #将爬取的数据转换为DataFrame格式
26     df = pd.DataFrame(page_information)
27     #df.to_csv('house_information.csv')
28     return df
29 #get_page(1)
 1 # 正式爬取数据并保存为csv数据
 2 
 3 df = pd.DataFrame() # 创建一个空的DataFrame
 4 name_csv = 'house_information_'
 5 for i in range(1,101): # 总共爬取100页数据
 6     try:
 7         df_get = get_page(i)
 8         df = df.append(df_get)
 9         print(df)
10     except Exception as e:
11         print('------->',e)
12     if i/100 == 1:
13         df.to_csv(name_csv+str(i)+'.csv')
14         df = pd.DataFrame() # 清空当前爬取完成的数据,防止内存溢出

 

 

 

2、数据预处理

1 import numpy as np
2 import pandas as pd
3 
4 data = pd.read_csv(r'house_information.csv') # 如果用pandas打不开数据,可以使用记事本打开把编码格式改成utf-8另存
5 data.head()

 

 

 

1 data.drop('index',axis=1,inplace=True) # 删除index列(用del更方便)
2 data.head()

 

 

 

1 # Series的extract支持正则匹配抽取,返回的值是字符串
2 data[['','','']] = data['户型'].str.extract(r'(\d+)室(\d+)厅(\d+)卫')
3 
4 # 把字符串格式转化为float,并删除户型
5 data[''] = data[''].astype(float)
6 data[''] = data[''].astype(float)
7 data[''] = data[''].astype(float)
8 del data['户型']
9 data.head()

 

 

 

1 # 将建筑面积后的平方米去除,并将数据类型改成浮点型
2 data['建筑面积'] = data['建筑面积'].map(lambda e:e.replace('平米',''))# Series中的map
3 data['建筑面积'] = data['建筑面积'].astype(float)
4 data.head()

 

 

 

1 # 将单价后的元/平米去除,并将数据类型改成浮点型
2 data['单价'] = data['单价'].map(lambda e:e.replace(r'元/平米',''))
3 data['单价'] = data['单价'].astype(float)
4 data.head()

 

 

 

1 # 将房屋总价后的万去除,并将数据类型改成浮点型
2 data['房屋总价'] = data['房屋总价'].map(lambda e:e.replace('',''))
3 data['房屋总价'] = data['房屋总价'].astype(float)
4 data.head()

 

 

 

1 # 使用pd.get_dummies() 量化数据
2 data_direction = pd.get_dummies(data['朝向'])
3 data_direction.head()

 

 

 

1 # 使用pd.get_dummies() 量化数据
2 data_floor = pd.get_dummies(data['楼层'])
3 data_floor.head()

 

 

 

1 # 使用pd.get_dummies() 量化数据
2 data_decoration = pd.get_dummies(data['装修'])
3 data_decoration.head()

 

 

 

1 # 使用pd.concat矩阵拼接,axis=1:水平拼接
2 data = pd.concat([data,data_direction,data_floor,data_decoration],axis=1) 
1 # 拼接后的列名
2 data.columns

 

 

 

 1 # 特征帅选
 2 del data['小区名称']
 3 del data['朝向']
 4 del data['楼层']
 5 del data['装修']
 6 del data['东西']
 7 del data['南北']
 8 del data['暂无'] # 两列都删除
 9 del data['中层'] # 多重共线性问题(线性回归)
10 del data['中装修']
11 data.columns

 

 

 

1 data.head()

 

 

 

1 data.info() # 发现 室厅卫中 有缺失值

 

 

 

3、数据可视化

1 import matplotlib.pyplot as plt
2 area = data['建筑面积']
3 price = data['房屋总价']
4 plt.scatter(area,price)
5 plt.show() # 有离群点数据,对线性分析不利,需要过滤

 

 

 

1 df = data[data['建筑面积'] <=300] # 正常住宅面积小于等于300平米
2 area = df['建筑面积']
3 price = df['房屋总价']
4 #print(area.count()) #过滤后的数据量
5 plt.scatter(area,price)
6 plt.xlabel("area")
7 plt.ylabel("price")
8 plt.show()

 

 

 

4、构建房价预测模型

1 # 先根据建筑面积和房屋总价训练模型(一元线性回归)
2 from sklearn.linear_model import LinearRegression
3 linear = LinearRegression()
4 area = np.array(area).reshape(-1,1) # 这里需要注意新版的sklearn需要将数据转换为矩阵才能进行计算
5 price = np.array(price).reshape(-1,1)
6 # 训练模型
7 model = linear.fit(area,price)
8 # 打印截距和回归系数
9 print(model.intercept_, model.coef_)

 

 

 

1 # 线性回归可视化(数据拟合)
2 linear_p = model.predict(area)
3 plt.figure(figsize=(12,6))
4 plt.scatter(area,price)
5 plt.plot(area,linear_p,'red')
6 plt.xlabel("area")
7 plt.ylabel("price")
8 plt.show()

 

 

 

多特征模型训练

1 cols = ['建筑面积','', '', '', '', '东北', '东南', '', '', '西',
2        '西北', '西南', '低层', '高层', '毛坯', '简装修', '精装修', '豪华装修']
1 X = df[cols]
2 X.head()

 

 

 

1 y = df['房屋总价']
2 y.head()

 

 

 

1 print(type(X))
2 print(type(y))
3 # 使用train_test_split进行交叉验证
4 from sklearn.model_selection import train_test_split
5 x_train, x_test, y_train, y_test = train_test_split(X,y,test_size=0.2,random_state=12)
6 print(x_train.shape,y_train.shape)
7 print(x_test.shape,y_test.shape)

 

 

 

1 # 模型训练
2 linear = LinearRegression()
3 model = linear.fit(x_train,y_train)
4 print(model.intercept_, model.coef_)

 

 

 

1 # 模型性能评分
2 price_end = model.predict(x_test)
3 score = model.score(x_test,y_test) 
4 print("模型得分:",score)# 一般模型在0.6以上就表现的不错

 

 

 

使用多种特征组合都可以预测房价,那么怎么找出最佳组合,这里使用假设验证法,选出最佳特征组合

 1 # 使用假设验证法,选出最佳特征组合
 2 cols = ['建筑面积','', '', '', '', '东北', '东南', '', '', '西',
 3        '西北', '西南', '低层', '高层', '毛坯', '简装修', '精装修', '豪华装修']
 4 import statsmodels.api as sm
 5 Y = df['房屋总价']
 6 X = df[cols]
 7 X_ = sm.add_constant(X) #增加一列值为1的const列,保证偏置项的正常
 8 #print(X_)
 9 # 使用最小平方法
10 result = sm.OLS(Y,X_)
11 # 使用fit方法进行计算
12 summary = result.fit()
13 # 调用summary2方法打印出假设验证信息(性能指标)
14 summary.summary2() # R-squared:模型评分 AIC:组合完越小越好

 

 

 #特征超过16个将发生异常

1 import itertools
2 
3 list1 = [1, 2,3, 4, 5,6,7,8,9,10,11,12,13,14,15,16] 
4 list2 = []
5 for i in range(1, len(list1)+1):
6     iter1 = itertools.combinations(list1, i)
7     list2.append(list(iter1))
8 #print(list2)

# 使用itertools,找出AIC最小值的特征组合作为模型训练的特征
# 寻找最小AIC值的特征组合

1 import itertools
2 fileds = ['建筑面积','', '', '', '','', '', '西','低层', '高层', '毛坯', '简装修', '精装修', '豪华装修']
3 acis = {}
4 for i in range(1,len(fileds)+1):
5     for virables in itertools.combinations(fileds,i): #从fileds中随机选择i个特征机型组合,返回的virables为元组类型
6         x1 = sm.add_constant(df[list(virables)])
7         x2 = sm.OLS(Y,x1)
8         res = x2.fit()
9         acis[virables] = res.aic # AIC评分越小越好
1 from collections import Counter
2 # 对字典进行统计
3 counter = Counter(acis)
4 # 降序选出AIC最小的10个数,也就是最佳特征组合
5 counter.most_common()[-10:]

 

 

 

 

1 # 接下来使用AIC值最小的特征组合进行预测
2 col2 = ['建筑面积', '', '', '', '', '高层', '毛坯', '精装修', '豪华装修']
3 X = df[col2]
4 y = df['房屋总价']
5 x_train, x_test, y_train, y_test = train_test_split(X,y,test_size=0.2,random_state=13)
6 linear = LinearRegression()
7 model = linear.fit(x_train,y_train)
8 model.score(x_test,y_test) # 模型性能有所提高,但是提升的不明显

 

 

5、房价的预测

现在我可以根据给定的最佳特征组合进行预测房价

1 # 假设我要买一套房子(想想就觉得很美),房子面积120平米,3室,1厅,南面,高层,精装修
2 my_house = [120,3,1,0,1,1,0,1,0] #根据col2特征
3 my_house = np.array(my_house).reshape(-1,1).T
4 #print(x_test)
5 model.predict(my_house)# 预测价格

 

 完整代码:

  1 import requests
  2 from bs4 import BeautifulSoup
  3 # requests返回网页内容
  4 res = requests.get(r'https://xm.esf.fang.com/house-a0352/')
  5 #res.text
  6 
  7 # BeautifulSoup解析网页
  8 soup = BeautifulSoup(res.text,'html.parser') # 使用 HTML.parser 解析器
  9 
 10 
 11 
 12 def get_house(url):
 13     '获取页面中每个房子的信息'
 14     information = {} # 存储房屋所有信息
 15     res = requests.get(url)
 16     soup = BeautifulSoup(res.text,'html.parser')
 17     
 18     # 获取户型、建筑面积、单价、朝向、楼层、装修情况
 19     houses = soup.select('.tab-cont-right .trl-item1') 
 20     #print(houses)
 21     for house in houses:
 22         me = house.text.strip().split('\n')
 23         information[me[1]] = me[0].strip()
 24     
 25     # 获取小区名字
 26     name = soup.select('.rcont .blue')
 27     information['小区名称'] = name[0].text
 28     
 29     # 获取房屋总价
 30     price = soup.select('.trl-item')
 31     information['房屋总价'] = price[0].text
 32     print(information)
 33 
 34 # 函数测试
 35 get_house("https://xm.esf.fang.com/chushou/3_346676334.htm?channel=1,2&psid=1_15_60") # 每一页中房子的url(注意:链接可能失效)
 36 
 37 
 38 
 39 def get_page(n):
 40     '分页爬取数据'
 41     for i in range(1,n+1): # n:爬取页数
 42         url = r'https://xm.esf.fang.com/house-a0352/i3{}/'.format(i) # 总共多少页
 43         res = requests.get(url)
 44         houses = BeautifulSoup(res.text,'html.parser')
 45         print(url)
 46         j  = 1
 47         houses = houses.select('.shop_list .clearfix h4 a') # 获取每套房子的href
 48         for house in houses:
 49             try:
 50                 demo_url = house['href']
 51                 url = r'https://xm.esf.fang.com' + demo_url + '?channel=1,2&psid=1_{}_60'.format(j) # 每一页中有多少套房子
 52                 # 获取当前页面中每套房子的信息
 53                 #get_house(url) 
 54                 j += 1
 55             except Exception as e:
 56                 print('-------->',e)
 57 get_page(1)
 58 
 59 
 60 
 61 import requests
 62 from bs4 import BeautifulSoup
 63 
 64 def get_house(url):
 65     '获取页面中每个房子的信息'
 66     information = {} # 存储房屋所有信息
 67     res = requests.get(url)
 68     soup = BeautifulSoup(res.text,'html.parser')
 69     
 70     # 获取户型、建筑面积、单价、朝向、楼层、装修情况
 71     houses = soup.select('.tab-cont-right .trl-item1') 
 72     for house in houses:
 73         m = house.text.strip().split('\n')
 74         me = m[1]
 75         if '朝向' in me:
 76             me = me.strip('进门') 
 77         if '楼层'in me:
 78             me = me[0:2]
 79         if '地上层数' in me:
 80             me = '楼层'
 81         if '装修程度' in me:
 82             me = '装修'
 83         information[me] = m[0].strip()
 84     
 85     # 获取小区名字
 86     name = soup.select('.rcont .blue')
 87     information['小区名称'] = name[0].text
 88     
 89     # 获取房屋总价
 90     price = soup.select('.trl-item')
 91     information['房屋总价'] = price[0].text
 92     return information
 93 
 94 # 函数测试
 95 get_house("https://xm.esf.fang.com/chushou/3_346676334.htm?channel=1,2&psid=1_15_60") # 每一页中房子的url
 96 
 97 
 98 
 99 import pandas as pd
100 import time
101 
102 def get_page(i):
103     '分页爬取数据'
104     url = r'https://xm.esf.fang.com/house-a0352/i3{}/'.format(i) # 总共多少页
105     res = requests.get(url)
106     houses = BeautifulSoup(res.text,'html.parser')
107     #print(url)
108     j  = 1
109     houses = houses.select('.shop_list .clearfix h4 a')
110     page_information = [] # 数据存储
111     for house in houses:
112         try:
113             demo_url = house['href']
114             url = r'https://xm.esf.fang.com' + demo_url + '?channel=1,2&psid=1_{}_60'.format(j) # 每一页中有多少套房子
115             # 获取当前页中每套房子的信息
116             information = get_house(url)
117             print('正在爬取第{}页第{}套房子···'.format(i,j),end='\r')
118             page_information.append(information)
119             j += 1
120             time.sleep(0.5) # 预防爬取频繁,防止ip被封
121         except Exception as e:
122             print('-------->',e)
123     #将爬取的数据转换为DataFrame格式
124     df = pd.DataFrame(page_information)
125     #df.to_csv('house_information.csv')
126     return df
127 #get_page(1)
128 
129 
130 
131 
132 # 正式爬取数据并保存为csv数据
133 
134 df = pd.DataFrame() # 创建一个空的DataFrame
135 name_csv = 'house_information_'
136 for i in range(1,101): # 总共爬取100页数据
137     try:
138         df_get = get_page(i)
139         df = df.append(df_get)
140         print(df)
141     except Exception as e:
142         print('------->',e)
143     if i/100 == 1:
144         df.to_csv(name_csv+str(i)+'.csv')
145         df = pd.DataFrame() # 清空当前爬取完成的数据,防止内存溢出
146 
147 
148 
149 import numpy as np
150 import pandas as pd
151 
152 data = pd.read_csv(r'house_information.csv') # 如果用pandas打不开数据,可以使用记事本打开把编码格式改成utf-8另存
153 data.head()
154 
155 
156 data.drop('index',axis=1,inplace=True) # 删除index列(用del更方便)
157 data.head()
158 
159 
160 # Series的extract支持正则匹配抽取,返回的值是字符串
161 data[['','','']] = data['户型'].str.extract(r'(\d+)室(\d+)厅(\d+)卫')
162 
163 
164 # 把字符串格式转化为float,并删除户型
165 data[''] = data[''].astype(float)
166 data[''] = data[''].astype(float)
167 data[''] = data[''].astype(float)
168 del data['户型']
169 data.head()
170 
171 
172 
173 # 将建筑面积后的平方米去除,并将数据类型改成浮点型
174 data['建筑面积'] = data['建筑面积'].map(lambda e:e.replace('平米',''))# Series中的map
175 data['建筑面积'] = data['建筑面积'].astype(float)
176 data.head()
177 
178 
179 
180 # 将单价后的元/平米去除,并将数据类型改成浮点型
181 data['单价'] = data['单价'].map(lambda e:e.replace(r'元/平米',''))
182 data['单价'] = data['单价'].astype(float)
183 data.head()
184 
185 
186 
187 # 将房屋总价后的万去除,并将数据类型改成浮点型
188 data['房屋总价'] = data['房屋总价'].map(lambda e:e.replace('',''))
189 data['房屋总价'] = data['房屋总价'].astype(float)
190 data.head()
191 
192 
193 
194 # 使用pd.get_dummies() 量化数据
195 data_direction = pd.get_dummies(data['朝向'])
196 data_direction.head()
197 
198 
199 
200 # 使用pd.get_dummies() 量化数据
201 data_floor = pd.get_dummies(data['楼层'])
202 data_floor.head()
203 
204 
205 
206 # 使用pd.get_dummies() 量化数据
207 data_decoration = pd.get_dummies(data['装修'])
208 data_decoration.head()
209 
210 
211 
212 # 使用pd.concat矩阵拼接,axis=1:水平拼接
213 data = pd.concat([data,data_direction,data_floor,data_decoration],axis=1) 
214 
215 
216 
217 # 拼接后的列名
218 data.columns
219 
220 
221 # 特征帅选
222 del data['小区名称']
223 del data['朝向']
224 del data['楼层']
225 del data['装修']
226 del data['东西']
227 del data['南北']
228 del data['暂无'] # 两列都删除
229 del data['中层'] # 多重共线性问题(线性回归)
230 del data['中装修']
231 data.columns
232 
233 
234 
235 data.head()
236 
237 data.info() # 发现 室厅卫中 有缺失值
238 
239 
240 # 删除缺失值
241 data.dropna(inplace=True)
242 data.info() 
243 
244 
245 import matplotlib.pyplot as plt
246 area = data['建筑面积']
247 price = data['房屋总价']
248 plt.scatter(area,price)
249 plt.show() # 有离群点数据,对线性分析不利,需要过滤
250 
251 
252 
253 df = data[data['建筑面积'] <=300] # 正常住宅面积小于等于300平米
254 area = df['建筑面积']
255 price = df['房屋总价']
256 #print(area.count()) #过滤后的数据量
257 plt.scatter(area,price)
258 plt.xlabel("area")
259 plt.ylabel("price")
260 plt.show()
261 
262 
263 
264 
265 # 先根据建筑面积和房屋总价训练模型(一元线性回归)
266 from sklearn.linear_model import LinearRegression
267 linear = LinearRegression()
268 area = np.array(area).reshape(-1,1) # 这里需要注意新版的sklearn需要将数据转换为矩阵才能进行计算
269 price = np.array(price).reshape(-1,1)
270 # 训练模型
271 model = linear.fit(area,price)
272 # 打印截距和回归系数
273 print(model.intercept_, model.coef_)
274 
275 
276 
277 # 线性回归可视化(数据拟合)
278 linear_p = model.predict(area)
279 plt.figure(figsize=(12,6))
280 plt.scatter(area,price)
281 plt.plot(area,linear_p,'red')
282 plt.xlabel("area")
283 plt.ylabel("price")
284 plt.show()
285 
286 
287 
288 
289 cols = ['建筑面积','', '', '', '', '东北', '东南', '', '', '西',
290        '西北', '西南', '低层', '高层', '毛坯', '简装修', '精装修', '豪华装修']
291 
292 X = df[cols]
293 X.head()
294 
295 y = df['房屋总价']
296 y.head()
297 
298 print(type(X))
299 print(type(y))
300 # 使用train_test_split进行交叉验证
301 from sklearn.model_selection import train_test_split
302 x_train, x_test, y_train, y_test = train_test_split(X,y,test_size=0.2,random_state=12)
303 print(x_train.shape,y_train.shape)
304 print(x_test.shape,y_test.shape)
305 
306 
307 
308 # 模型训练
309 linear = LinearRegression()
310 model = linear.fit(x_train,y_train)
311 print(model.intercept_, model.coef_)
312 
313 
314 
315 # 模型性能评分
316 price_end = model.predict(x_test)
317 score = model.score(x_test,y_test) 
318 print("模型得分:",score)# 一般模型在0.6以上就表现的不错
319 
320 
321 
322 # 使用假设验证法,选出最佳特征组合
323 cols = ['建筑面积','', '', '', '', '东北', '东南', '', '', '西',
324        '西北', '西南', '低层', '高层', '毛坯', '简装修', '精装修', '豪华装修']
325 import statsmodels.api as sm
326 Y = df['房屋总价']
327 X = df[cols]
328 X_ = sm.add_constant(X) #增加一列值为1的const列,保证偏置项的正常
329 #print(X_)
330 # 使用最小平方法
331 result = sm.OLS(Y,X_)
332 # 使用fit方法进行计算
333 summary = result.fit()
334 # 调用summary2方法打印出假设验证信息(性能指标)
335 summary.summary2() # R-squared:模型评分 AIC:组合完越小越好
336 
337 
338 
339 
340 import itertools
341 
342 list1 = [1, 2,3, 4, 5,6,7,8,9,10,11,12,13,14,15,16] 
343 list2 = []
344 for i in range(1, len(list1)+1):
345     iter1 = itertools.combinations(list1, i)
346     list2.append(list(iter1))
347 #print(list2)
348 
349 
350 
351 
352 import itertools
353 fileds = ['建筑面积','', '', '', '','', '', '西','低层', '高层', '毛坯', '简装修', '精装修', '豪华装修']
354 acis = {}
355 for i in range(1,len(fileds)+1):
356     for virables in itertools.combinations(fileds,i): #从fileds中随机选择i个特征机型组合,返回的virables为元组类型
357         x1 = sm.add_constant(df[list(virables)])
358         x2 = sm.OLS(Y,x1)
359         res = x2.fit()
360         acis[virables] = res.aic # AIC评分越小越好
361 
362 
363 
364 from collections import Counter
365 # 对字典进行统计
366 counter = Counter(acis)
367 # 降序选出AIC最小的10个数,也就是最佳特征组合
368 counter.most_common()[-10:] 
369 
370 
371 
372 
373 # 接下来使用AIC值最小的特征组合进行预测
374 col2 = ['建筑面积', '', '', '', '', '高层', '毛坯', '精装修', '豪华装修']
375 X = df[col2]
376 y = df['房屋总价']
377 x_train, x_test, y_train, y_test = train_test_split(X,y,test_size=0.2,random_state=13)
378 linear = LinearRegression()
379 model = linear.fit(x_train,y_train)
380 model.score(x_test,y_test) # 模型性能有所提高,但是提升的不明显
381 
382 
383 
384 
385 # 假设我要买一套房子(想想就觉得很美),房子面积120平米,3室,1厅,南面,高层,精装修
386 my_house = [120,3,1,0,1,1,0,1,0] #根据col2特征
387 my_house = np.array(my_house).reshape(-1,1).T
388 #print(x_test)
389 model.predict(my_house)# 预测价格

 

五,总结

  经过对数据的分析与可视化,可以得到:使用假设验证法,选出最佳特征组合,打印出假设验证性能指标,对预期的目标已经达到了,这设计多特征模型训练机器学习的模型结果表现不错。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM