【Python】鏈家網二手房購房決策樹

整體流程:
1.數據抓取;
2.數據清洗;
3.建模及優化;
4.業務意義;
5.反思。

一、數據抓取

環境:python3.7

from parsel import Selector
import requests
import time
lines=[ ]
for i in range (1,3): #先測試,再抓取總數
    base_url='https://tj.lianjia.com/ershoufang/pg%s/'
    url=base_url % i
    content=requests.get(url)
    time.sleep(2) #休眠2秒,防止操作太頻繁
    sel=Selector(text=content.text)
    for x in sel.css('.info.clear'): #Chrome開發者工具,查詢路徑
        title=x.css('a::text').extract_first()
        community=x.css('.houseInfo>a::text').extract_first()
        address=x.css('.address>::text').getall() 
        flood=x.css('.flood>::text').getall()  
        totalPrice=x.css('.totalPrice>span::text').extract()
        lines.append('%s,天津%s,%s,%s,%sW' % (title,community,address,flood,totalPrice))
        #print("lines",lines)
with open('tianjin_datas.csv','w') as f:
    for line in lines:
        f.write (line)
        f.write('\n')

二、數據清洗

將抓取的48359條數據,進行重複值、缺失值、異常值、字符類型轉變、數值轉換等處理,爲建模做準備:

清洗前:
在這裏插入圖片描述

清洗代碼:

import pandas as pd
import numpy as np  #引入,修改數值類型
  
#讀取數據
lianjia=pd.read_csv('lianjia_raw_data.csv')
    
#剔除重複值、不需要的列、缺失值、異常值
lianjia=lianjia.drop_duplicates() #剔除重複項
lianjia=lianjia.drop(['location','community','attention','look_times','release_days','title'],axis=1) #剔除不需要的列
lianjia.isnull().sum() #計算空值數量
lianjia=lianjia.dropna(axis=0,how='any') #剔除空值
#lianjia.head()
#lianjia.shape

#剔除空格
lianjia['elevator']=lianjia['elevator'].map(str.strip)
lianjia['hall']=lianjia['hall'].map(str.strip)
lianjia['oriented']=lianjia['oriented'].apply(str.strip)

#替換值
lianjia['floor']=lianjia['floor'].replace(['低','中','高'],['low','middle','hige']) #改變列的值,爲建模做準備
lianjia['elevator']=lianjia['elevator'].replace(['有','無'],['yes','no'])
lianjia['decoration']=lianjia['decoration'].replace(['毛坯','簡裝','精裝','其他'],['blank','lite','fine','others'])
lianjia['hall']=lianjia['hall'].replace(['1室0廳','1室1廳','1室2廳','2室0廳','2室1廳','2室2廳','2室3廳','3室1廳','3室2廳','3室3廳','4室1廳','4室2廳','4室3廳','5室0廳','5室1廳','5室2廳','5室3廳','6室3廳'],['one room zero hall','one room one hall','one room two hall','two room zero hall','two room one hall','two room two hall','two room three hall','three room one hall','three room two hall','three room three hall','four room one hall','four room two hall','four room three hall','five room zero hall','five room one hall','five room two hall','five room three hall','six room three hall'])
lianjia['tag']=lianjia['tag'].replace(['近地鐵','房本滿兩年','房本滿五年','隨時看房'],['near subway','house over two years','house over five years','visit any time'])
lianjia['oriented']=lianjia['oriented'].str[:1] #切片,保留第一個字符
lianjia['oriented']= lianjia['oriented'].replace(['南','東','西','北'],['south','east','east','north'])
lianjia.head(10) #替換後,查看效果

#更改數據格式
lianjia['total_price']=lianjia['total_price'].astype(np.int64)
lianjia['avg_price']=lianjia['avg_price'].astype(np.int64)
lianjia['layers']=lianjia['layers'].astype(np.int64)
lianjia.head(10) #查看效果

#保存數據
lianjia.to_csv('lianjia_tree_model.csv') #保存文件

清洗後:
在這裏插入圖片描述

構建意向數據(intention):
在這裏插入圖片描述

三、構建決策樹

模塊:pandas、scikit-learn;
算法:CART;
環境:IPython3。

import pandas as pd
from sklearn.preprocessing import LabelEncoder
from collections import defaultdict
from sklearn import tree
from IPython.display import Image as PImage
from PIL import ImageDraw
from subprocess import check_call

df = pd.read_csv('lianjia_tree_model.csv')
# df.head()
# df.shape

X = df.drop('intention', axis=1)
y = df.intention

d = defaultdict(LabelEncoder)
X_trans = X.apply(lambda x: d[x.name].fit_transform(x))
# X_trans.head()

clf = tree.DecisionTreeClassifier(max_depth=4)  #此步,需要單獨運行
clf = clf.fit(X_train, y_train)

with open("house_buy.dot", 'w') as f:
     f = tree.export_graphviz(clf,
                              out_file=f,
                              max_depth=4,
                              impurity = True,
                              feature_names = list(X_train),
                              class_names = ['not buy','buy'],
                              rounded = True,
                              filled= True )

check_call(['dot','-Tpng','house_buy.dot','-o','house_buy.png'])

#draw = ImageDraw.Draw(img)
img.save('house_buy.png')
PImage("house_buy.png")

初步效果如下,接下來逐步調整模型:
在這裏插入圖片描述

調試前:
1.模型是否過度擬合:
(1)從分支效果來看,邏輯無誤;
(2)從gini係數來看,底部gini係數非常接近0,樣本特徵不錯,但能否通過調整樣本數量及樹的深度,使模型更優,接下來將進行調整。

2.模型準確度:98.13%,是否能更爲精確?
在這裏插入圖片描述

調試方法:
1.平均樣本數量;
2.前後剪枝 (剔除了非關鍵字段,並調整樹的深度,加以對比)。

調試後:
1.決策樹模型:
(1)邏輯:無誤;
(2)gini係數:亦很接近0,樣本特徵不錯。
在這裏插入圖片描述

2.準確度:98.71%,提升了0.59%(幅度,非數值差),調試效果還不錯。
在這裏插入圖片描述

四、模型的業務意義
1.策略制定:根據模型進行判斷,客戶熱衷與哪類房源,怎麼才能最快去庫存,避免盲目搶房,造成積壓;
2.銷售推廣:針對各類人羣需求,按模型層層推薦,快速滿足客戶的需求;
3.人力精簡:提升了決策與銷售的效率,降低人力成本;
4.業務方向:模型是根據現時的數據進行搭建的,那尚未開發的客戶市場會不會與現今模型相反,造成未來決策失誤?值得我們反思。

五、反思
1.擬合:

欠擬合:
前/後期剪枝太多,枝葉沒有展開,會有欠擬合的風險;

過度擬合:
(1)樣本量:如何篩選數據源,哪些纔是最關鍵的字段;
(2)剪枝:先剪枝葉,還是後剪枝。

2.複雜情況:
對於異或,是否需要換成神經網絡模型建模。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章