數據挖掘之旅(1)
本專欄會記錄我本人在學習過程中的一些體會。希望在知乎這個平台能認識更多有志於「煉丹」的小夥伴。
前幾天在kaggle競賽的 House Prices: Advanced Regression Techniques問題下看到很有意思的幾個關於數據挖掘kernels。下面結合我自己的理解,做一些粗淺的總結。
閑言少敘,讓我們快快開始吧!
題目描述:
Ask a home buyer to describe their dream house, and they probably
wont begin with the height of the basement ceiling or the proximity to
an east-west railroad. But this playground competitions dataset proves that much more influences price negotiations than the number of bedrooms or a white-picket fence.With 79 explanatory variables describing (almost) every aspect of residential homes in Ames, Iowa, this competition challenges you to predict the final price of each home.
簡單來說這是一個房價預測的問題,我們需要考慮與之有關的79個變數,首先我們需要在給出的訓練集上訓練出模型,並用我們得到的模型對給的測試集數據給出預測的結果,評判標準自然就是正確率。
首先我們下載數據集:房價預測
導入必要的包並讀取訓練集文件:
import pandas as pdimport matplotlib.pyplot as pltimport seaborn as snsimport numpy as npfrom scipy.stats import normfrom sklearn.preprocessing import StandardScalerfrom scipy import statsimport warningswarnings.filterwarnings(ignore)%matplotlib inlinedf_train = pd.read_csv(../input/train.csv)
查看一下訓練集的列(屬性),最後一個就是房屋的售價,也就是label
df_train.columns
調用describe()函數,看下具體情況。這個函數能返回對象的一些有用的指標,諸如值域,標準差等等
df_train[SalePrice].describe()
接下來我們調用seaborn的distplot函數來畫出直方圖,有人可能會問為什麼不用pandas.DataFrame.hist()來畫,其實也可以,但是,區別就在於會多一條KDE(密度)曲線
sns.distplot(df_train[SalePrice])
去掉KDE曲線:數據可視化
sns.distplot(df_train[SalePrice], kde=False)
我們來觀察這個直方圖,可以看出
- 偏離了正態分布
- 很明顯比較銳利,偏度為正
關於: 偏度和峰度
列印出這兩個值來看看
print("Skeweness: %f" % df_train[SalePrice].skew())print("Kurtosis: %f" % df_train[SalePrice].kurt())
一般我們在考慮買房的時候會考慮哪個變數呢?
建築年份,房屋質量,建築面積,地下室面積,地理位置,對我來說是首要的考察點
那下面我們就來看看他們到底存在什麼關係
我們來看一下GiLiveArea(居住面積)這個參數和售價的關係,用散點圖表示,考慮到我們已知房價的值閾,我們將y軸設定在0~800000
var = GrLivAreadata = pd.concat([df_train[SalePrice], df_train[var]], axis=1)data.plot.scatter(x=var, y=SalePrice, ylim=(0,800000));
和我們預想的差不多,大概是呈線性關係,但是也存在一些比較特殊的點,比如右下角那兩個.
我們可以猜測這兩個點可能是農業用地.
同樣的,我們來看看TotalBsmtSF和售價的關係:
var = TotalBsmtSFdata = pd.concat([df_train[SalePrice], df_train[var]], axis=1)data.plot.scatter(x=var, y=SalePrice, ylim=(0,800000));
seaborn中不僅提供了散點圖,還有很多刻畫數據的有利工具,比如箱形圖,其能可視化得顯示數據的最大值,最小值,中位數,以及上下四分位數.
var = OverallQualdata = pd.concat([df_train[SalePrice], df_train[var]], axis=1)f, ax = plt.subplots(figsize=(8, 6))fig = sns.boxplot(x=var, y="SalePrice", data=data)fig.axis(ymin=0, ymax=800000);
這個圖反映了整體質量與銷售價格之間的關係,房屋質量越高,相應的,售價的中位數也就越大。
那年份呢?是不是越新的房子價格越高?
var = YearBuiltdata = pd.concat([df_train[SalePrice], df_train[var]], axis=1)f, ax = plt.subplots(figsize=(16, 8))fig = sns.boxplot(x=var, y="SalePrice", data=data)fig.axis(ymin=0, ymax=800000);plt.xticks(rotation=90);
整體來看,這樣說是沒問題的,儘管不是很明顯,但是整體來說人們願意為更新的房子支付更多的金錢。(註:rotation是坐標label的旋轉角度)
小結:
- GrLivArea 和 TotalBsmtSF 和SalePrice都呈線性關係,都為正相關,而且TotalBsmtSF的斜率要更大些
- OverallQual 和 YearBuilt 和 SalePrice也存在關聯,OverallQual的相關性更大
剛才我們儘可能客觀得分析了幾個我們認為相對重要的變數和SalePrice的關係,但不得不承認,「我們認為」本身就包含了主觀的挑選,我們所做的分析,相對整體而言是遠遠不夠的。
為了找到彌散在未知之中的真相,這次,我們要拋卻「主觀」,做個「冷血殺手」
相關性矩陣
利用seaborn提供的heatmap(熱圖)我們能輕鬆得做出漂亮的相關性矩陣圖。vmax是指最大值,超過這個限度的方塊(square=True保證了圖中都是方塊),都是白色(顏色越淺,相關性越大).
corrmat = df_train.corr()f, ax = plt.subplots(figsize=(12, 9))sns.heatmap(corrmat, vmax=.8, square=True);
通過上圖,我們可以很直觀得感受任意兩個變數之間的相關性,一個好玩的比喻是,宇宙的初始是一鍋等離子湯(plasma soup),而熱圖就是我們快速瀏覽數據宇宙的最好方法!
設定閾值為2,讓我們來看一看「熱寂」之後的「未來宇宙」
可能有人會問了,「數缺形時少直觀,形少數時難入微」現在直觀是夠直觀了,能不能給出準確的數字呢,答案是,能。只要在heatmap裡面取annot=True即可。(我們取了與SalePrice相關性最大的十個變數)
k = 10 #number of variables for heatmapcols = corrmat.nlargest(k, SalePrice)[SalePrice].indexcm = 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()
小結:
- OverallQual, GrLivArea 和 TotalBsmtSF,YearBuilt 都和 SalePrice 強相關.Bingo!
- GarageCars 和 GarageArea 表現很相似,因此在我們後續的分析中,車庫的車數和車庫的面積只需要留下一個(GarageCars相關度更高)
- FullBath 看來美帝人民對獨立衛浴看得很重,果然是活在水深火熱之中
我們已經知道了相關性最大的幾個變數,不禁有犯了難,難道又要一個個散點圖慢慢看,要是有個工具能一次性畫出來就好了,別說,還真有(再次感謝seaborn):)
sns.set()cols = [SalePrice, OverallQual, GrLivArea, GarageCars, TotalBsmtSF, FullBath, YearBuilt]sns.pairplot(df_train[cols], size = 2.5)plt.show();
雖然我們之前已經看過一些主要特徵的散點圖了,但是這個大的散點圖仍能給我們一些有意思的啟示。
消失的數據
我們希望數據是完備的,但是現實生活中的數據大多數都會伴隨著一些損失,有可能是已經遺失,也有可能是難以採集,當我們考慮missing data的時候,我們需要考慮以下幾點:
- 丟失的數據有多普遍
- 丟失的數據是隨機的還是有模式的
處理丟失的數據是很關鍵的一步,首先,數據的丟失代表著樣本容量的減少,其次,我們需要確保丟失的數據不會對模型造成影響。
total = df_train.isnull().sum().sort_values(ascending=False)percent = (df_train.isnull().sum()/df_train.isnull().count()).sort_values(ascending=False)missing_data = pd.concat([total, percent], axis=1, keys=[Total, Percent])missing_data.head(20)
可以看出有不少特徵都缺失了15%以上的數據,並且這些數據大多數與SalePrice相關性不高(也許這就是數據丟失的原因?),所以我們直接將除了Electrical之外的丟失數據的特徵刪除,對Electrical也刪除掉其丟失的數據.
df_train = df_train.drop((missing_data[missing_data[Total] > 1]).index,1)df_train = df_train.drop(df_train.loc[df_train[Electrical].isnull()].index)df_train.isnull().sum().max() #just checking that theres no missing data missing...
異常數據處理
異常數據的處理一直都是一個很重要的話題,因為如果不處理的話,異常數據可以很輕易得影響我們的模型。回憶一下各種歌唱比賽,是不是都會去掉一個最高分,去掉一個最低分,這其實就是在避免異常數據的影響。
下一篇會討論如何處理這些異常數據,分析異常數據的分布情況。
感謝閱讀
Ref:
- 數據可視化(三)- Seaborn簡易入門
- https://zh.wikipedia.org/wiki/%E7%AE%B1%E5%BD%A2%E5%9C%96
- House Prices: Advanced Regression Techniques
- 偏度和峰度如何影響您的分布 - Minitab
推薦閱讀:
※機器學習萌新必學的Top10演算法
※《大演算:機器學習的終極演演算法將如何改變我們的未來,創造新紀元的文明》
※譯文:如何為機器學習索引,切片,調整 NumPy 數組
※【最優化】無約束優化方法-阻尼牛頓法
※機器學習預測地震,信得過嗎?