kaggle--House Price(房價預測)--線性迴歸模型

關於kaggle–House Price(房價預測)的入門級解答
本文只涉及入門級的完成,所以對於數據的處理和模型較爲粗略,並不涉及詳細優化,所以kaggle的提交測試了一下應該是處於中間水平,後續優化請按照個人蔘考修改。

數據集的讀取與導入

import numpy as np
import pandas as pd
train = pd.read_csv("路徑/train.csv")
test = pd.read_csv("路徑/test.csv")

探索性可視化(ExploratoryVisualization)

查看分佈:
首先查看預測值分佈如何,在此處預測值爲‘’SalePrice‘’

import seaborn as sns
sns.distplot(train["SalePrice"])  
plt.show()

觀察發現圖像不服從標準的正態分佈,一般希望特徵分佈最好符合正態分佈。是否符合則是檢測數據的偏度skewness。如果skew()值大於0.75, 則需要進行分佈變換。

具體可參考特徵工程的特徵分佈

1

 train["SalePrice"].skew()
 1.8828757597682129

這裏skewness明顯大於0.75,是顯著的左偏分佈,故使用對數進行變換:

y = np.log(train["SalePrice"])

查看各個指標與目標值的關聯程度:
各個數值屬性與Y值的關聯程度,去除關聯程度非常低的屬性
corr()返回相關係數矩陣,絕對值越接近1,線性相關越強烈

data = train.corr()
sns.heatmap(data)
plt.show()

在這裏插入圖片描述
熱力圖如果顯示的不明顯,尤其屬性特別多的時候,可以選擇直接查看。

data = train.corr()
data["SalePrice"].sort_values()

1
可以按照線性相關性對於部分項目進行剔除

數據清洗預處理及特徵工程

數據清洗包括檢查數據一致性,尋找異常值處理缺失值,而特徵工程是指對數據特徵值做進一步的提取處理。
特徵工程決定了機器學習模型的上限,因爲本篇是入門級只做了最基礎的量綱消除特徵工程,也就決定了這個模型的上限不會很高

尋找異常值:

sns.lmplot(x="GrLivArea", y="SalePrice", 
data=train,fit_reg=False,scatter=True)
plt.show()

在這裏插入圖片描述
根據異常值刪除數據:

train = train[-((train.SalePrice < 200000) &  (train.GrLivArea > 4000))]

填補缺失值:
看各屬性裏面的空值情況,根據該屬性的分佈,對空值進行處理。在競賽中提供了說明文檔,用以說明各個屬性代表的信息,例如泳池質量代表有無,此處可以用None值填充,而關於面積等則用0填充,對於像LotFrontage這樣的特殊屬性,是與LotAreaCut和Neighborhood有比較大的關係,所以這裏可以用這兩個屬性分組後的中位數進行插補。
查看訓練集下的屬性空值個數:

aa = train.isnull().sum()
aa[aa>0].sort_values(ascending=False)

在這裏插入圖片描述
因爲本例中的屬性很多,以上填充都是較爲繁瑣的填充方法,所以我們採取一種更直接的方法(但會影響精確度)
這裏有個地方需要注意:不止train的數據裏面有空值,test數據裏面也會有空值。而且可能分佈在不同屬性裏面。所以,需要一開始對train和test的數據進行彙總,根據二者的總體分佈來處理空值。
如果某個屬性空值過多,直接從數據中刪除該屬性。
如果空值佔比不大,如果是數字類型,就填寫均值。如果是字符串類型,就填寫出現次數最多的字符串。

#一半是刪除過多空值的屬性,一半是刪除無關聯的屬性 
 train = train.drop(["MiscFeature", "Id", "PoolQC", "Alley", "Fence","GarageFinish", "KitchenAbvGr", "EnclosedPorch", "MSSubClass", "OverallCond", "YrSold", "LowQualFinSF", "MiscVal", "BsmtHalfBath", "BsmtFinSF2", "3SsnPorch", "MoSold", "PoolArea"], axis=1)

 test = test.drop(["MiscFeature", "PoolQC", "Alley", "Fence","GarageFinish", "KitchenAbvGr", "EnclosedPorch", "MSSubClass", "OverallCond", "YrSold", "LowQualFinSF", "MiscVal", "BsmtHalfBath", "BsmtFinSF2", "3SsnPorch", "MoSold", "PoolArea"], axis=1)

#彙總train和test的數據
all_data = pd.concat((train, test))
#如果數字,填寫均值。如果字符串,填寫次數最多的
for col in train.columns:
    if train[col].isnull().sum() > 0:
        if train[col].dtypes == 'object':
            val = all_data[col].dropna().value_counts().idxmax()
            train[col] = train[col].fillna(val)
        else:
            val = all_data[col].dropna().mean()
            train[col] = train[col].fillna(val)
for col in test.columns:
     if test[col].isnull().sum() > 0:
         if test[col].dtypes == 'object':
             val = all_data[col].dropna().value_counts().idxmax()
             test[col] = test[col].fillna(val)
         else:
             val = all_data[col].dropna().mean()
             test[col] = test[col].fillna(val)

特徵工程無量綱化:
因爲不同屬性的量綱不同,人的性別有男女,祖國有中國,美國,法國等。
這些特徵值並不是連續的,而是離散的,無序的。通常我們需要對其進行特徵數字化。
這裏使用get_dummies()來對train數據和test數據進行轉換。有個地方要注意:test數據裏面屬性的取值範圍可能跟train數據裏面屬性的取值範圍部分不同。這樣如果直接對test數據和train數據做get_dummies,很可能會導致test和train數據轉化後出現了不同的列。所以需要綜合處理。

#綜合處理,轉值類型
for col in all_data.select_dtypes(include = [object]).columns:
      train[col] = train[col].astype('category', categories = all_data[col].dropna().unique())
      test[col] = test[col].astype('category', categories = all_data[col].dropna().unique())

for col in train.columns:
      if train[col].dtype.name == 'category':
         tmp = pd.get_dummies(train[col], prefix = col)
         train = train.join(tmp)
         train = train.drop(col, axis=1)

for col in test.columns:
      if test[col].dtype.name == 'category':
           tmp = pd.get_dummies(test[col], prefix = col)
           test = test.join(tmp)
           test = test.drop(col, axis=1)

建立線性迴歸模型&交叉驗證

使用linear_model.LinearRegression建立線性迴歸模型
linear_model.LinearRegression()線性迴歸實例:
https://www.cnblogs.com/FYZHANG/p/12030202.html
使用cross_val_score進行交叉驗證
cross_val_score講解:
https://blog.csdn.net/qq_36523839/article/details/80707678

from sklearn.model_selection import cross_val_score
from sklearn import linear_model
from sklearn import metrics    
lr = linear_model.LinearRegression()
X = train.drop("SalePrice", axis=1)
y = np.log(train["SalePrice"])
score = cross_val_score(lr, X,y, scoring='mean_squared_error')
print (score)

預測並提交結果

lr = lr.fit(X, y)
results = lr.predict(test.drop("Id", axis = 1))
final = np.exp(results)
   
   
submission = pd.DataFrame()
submission['Id'] = test.Id
submission['SalePrice'] = final
submission.to_csv("路徑/submission.csv", index= False)

附錄:全代碼

import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

train = pd.read_csv("路徑/train.csv")
test = pd.read_csv("路徑/test.csv")
#plt.figure(figsize=(15,8))
#sns.boxplot(train.YearBuilt, train.SalePrice)


#一半是刪除過多空值的屬性,一半是刪除無關聯的屬性 
train = train.drop(["MiscFeature", "Id", "PoolQC", "Alley", "Fence","GarageFinish", "KitchenAbvGr", "EnclosedPorch", "MSSubClass", "OverallCond", "YrSold", "LowQualFinSF", "MiscVal", "BsmtHalfBath", "BsmtFinSF2", "3SsnPorch", "MoSold", "PoolArea"], axis=1)

test = test.drop(["MiscFeature", "PoolQC", "Alley", "Fence","GarageFinish", "KitchenAbvGr", "EnclosedPorch", "MSSubClass", "OverallCond", "YrSold", "LowQualFinSF", "MiscVal", "BsmtHalfBath", "BsmtFinSF2", "3SsnPorch", "MoSold", "PoolArea"], axis=1)

#彙總train和test的數據
all_data = pd.concat((train, test))

#彙總train和test的數據
all_data = pd.concat((train, test))
#如果數字,填寫均值。如果字符串,填寫次數最多的
for col in train.columns:
    if train[col].isnull().sum() > 0:
        if train[col].dtypes == 'object':
            val = all_data[col].dropna().value_counts().idxmax()
            train[col] = train[col].fillna(val)
        else:
            val = all_data[col].dropna().mean()
            train[col] = train[col].fillna(val)
for col in test.columns:
     if test[col].isnull().sum() > 0:
         if test[col].dtypes == 'object':
             val = all_data[col].dropna().value_counts().idxmax()
             test[col] = test[col].fillna(val)
         else:
             val = all_data[col].dropna().mean()
             test[col] = test[col].fillna(val)
             
             
             
#綜合處理,轉值類型
for col in all_data.select_dtypes(include = [object]).columns:
      train[col] = train[col].astype('category', categories = all_data[col].dropna().unique())
      test[col] = test[col].astype('category', categories = all_data[col].dropna().unique())

for col in train.columns:
      if train[col].dtype.name == 'category':
         tmp = pd.get_dummies(train[col], prefix = col)
         train = train.join(tmp)
         train = train.drop(col, axis=1)

for col in test.columns:
      if test[col].dtype.name == 'category':
           tmp = pd.get_dummies(test[col], prefix = col)
           test = test.join(tmp)
           test = test.drop(col, axis=1)
           
from sklearn.model_selection import cross_val_score
from sklearn import linear_model
from sklearn import metrics    
lr = linear_model.LinearRegression()
X = train.drop("SalePrice", axis=1)
y = np.log(train["SalePrice"])
score = cross_val_score(lr, X,y, scoring='mean_squared_error')
print (score)


lr = lr.fit(X, y)
results = lr.predict(test.drop("Id", axis = 1))
final = np.exp(results)
   
   
submission = pd.DataFrame()
submission['Id'] = test.Id
submission['SalePrice'] = final
submission.to_csv("路徑/submission.csv", index= False)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章