In [5]:
import numpy as np
import pandas as pd
In [6]:
train_df = pd.read_csv('../input/train.csv', index_col=0)
test_df = pd.read_csv('../input/test.csv', index_col=0)
In [7]:
train_df.head()
Out[7]:
这时候大概心里可以有数,哪些地方需要人为的处理一下,以做到源数据更加好被process。
In [1]:
%matplotlib inline
prices = pd.DataFrame({"price":train_df["SalePrice"], "log(price + 1)":np.log1p(train_df["SalePrice"])})
prices.hist()
可见,label本身并不平滑。为了我们分类器的学习更加准确,我们会首先把label给“平滑化”(正态化)
这一步大部分同学会miss掉,导致自己的结果总是达不到一定标准。
这里我们使用最有逼格的log1p, 也就是 log(x+1),避免了复值的问题。
记住哟,如果我们这里把数据都给平滑化了,那么最后算结果的时候,要记得把预测到的平滑数据给变回去。
按照“怎么来的怎么去”原则,log1p()就需要expm1(); 同理,log()就需要exp(), ... etc.
In [ ]:
y_train = np.log1p(train_df.pop('SalePrice'))
然后我们把剩下的部分合并起来
In [ ]:
all_df = pd.concat((train_df, test_df), axis=0)
此刻,我们可以看到all_df就是我们合在一起的DF
In [ ]:
all_df.shape
而y_train则是SalePrice那一列
In [2]:
y_train.head()
In [3]:
all_df['MSSubClass'].dtypes
In [4]:
all_df['MSSubClass'] = all_df['MSSubClass'].astype(str)
变成str以后,做个统计,就很清楚了
In [5]:
all_df['MSSubClass'].value_counts()
In [6]:
pd.get_dummies(all_df['MSSubClass'], prefix='MSSubClass').head()
此刻MSSubClass被我们分成了12个column,每一个代表一个category。是就是1,不是就是0。
同理,我们把所有的category数据,都给One-Hot了
In [7]:
all_dummy_df = pd.get_dummies(all_df)
all_dummy_df.head()
In [8]:
all_dummy_df.isnull().sum().sort_values(ascending=False).head(10)
可以看到,缺失最多的column是LotFrontage
处理这些缺失的信息,得靠好好审题。一般来说,数据集的描述里会写的很清楚,这些缺失都代表着什么。当然,如果实在没有的话,也只能靠自己的『想当然』。。
在这里,我们用平均值来填满这些空缺。
In [9]:
mean_cols = all_dummy_df.mean()
mean_cols.head(10)
In [10]:
all_dummy_df = all_dummy_df.fillna(mean_cols)
看看是不是没有空缺了?
In [11]:
all_dummy_df.isnull().sum().sum()
In [12]:
numeric_cols = all_df.columns[all_df.dtypes != 'object']
numeric_cols
计算标准分布:(X-X')/s
让我们的数据点更平滑,更便于计算。
注意:我们这里也是可以继续使用Log的,我只是给大家展示一下多种“使数据平滑”的办法。
In [13]:
numeric_col_means = all_dummy_df.loc[:, numeric_cols].mean()
numeric_col_std = all_dummy_df.loc[:, numeric_cols].std()
all_dummy_df.loc[:, numeric_cols] = (all_dummy_df.loc[:, numeric_cols] - numeric_col_means) / numeric_col_std
In [14]:
dummy_train_df = all_dummy_df.loc[train_df.index]
dummy_test_df = all_dummy_df.loc[test_df.index]
In [15]:
dummy_train_df.shape, dummy_test_df.shape
In [16]:
from sklearn.linear_model import Ridge
from sklearn.model_selection import cross_val_score
这一步不是很必要,只是把DF转化成Numpy Array,这跟Sklearn更加配
In [17]:
X_train = dummy_train_df.values
X_test = dummy_test_df.values
用Sklearn自带的cross validation方法来测试模型
In [ ]:
alphas = np.logspace(-3, 2, 50)
test_scores = []
for alpha in alphas:
clf = Ridge(alpha)
test_score = np.sqrt(-cross_val_score(clf, X_train, y_train, cv=10, scoring='neg_mean_squared_error'))
test_scores.append(np.mean(test_score))
存下所有的CV值,看看哪个alpha值更好(也就是『调参数』)
In [ ]:
import matplotlib.pyplot as plt
%matplotlib inline
plt.plot(alphas, test_scores)
plt.title("Alpha vs CV Error");
可见,大概alpha=10~20的时候,可以把score达到0.135左右。
In [ ]:
from sklearn.ensemble import RandomForestRegressor
In [ ]:
max_features = [.1, .3, .5, .7, .9, .99]
test_scores = []
for max_feat in max_features:
clf = RandomForestRegressor(n_estimators=200, max_features=max_feat)
test_score = np.sqrt(-cross_val_score(clf, X_train, y_train, cv=5, scoring='neg_mean_squared_error'))
test_scores.append(np.mean(test_score))
In [ ]:
plt.plot(max_features, test_scores)
plt.title("Max Features vs CV Error");
用RF的最优值达到了0.137
In [ ]:
ridge = Ridge(alpha=15)
rf = RandomForestRegressor(n_estimators=500, max_features=.3)
In [ ]:
ridge.fit(X_train, y_train)
rf.fit(X_train, y_train)
上面提到了,因为最前面我们给label做了个log(1+x), 于是这里我们需要把predit的值给exp回去,并且减掉那个"1"
所以就是我们的expm1()函数。
In [18]:
y_ridge = np.expm1(ridge.predict(X_test))
y_rf = np.expm1(rf.predict(X_test))
一个正经的Ensemble是把这群model的预测结果作为新的input,再做一次预测。这里我们简单的方法,就是直接『平均化』。
In [19]:
y_final = (y_ridge + y_rf) / 2
In [20]:
submission_df = pd.DataFrame(data= {'Id' : test_df.index, 'SalePrice': y_final})
我们的submission大概长这样:
In [21]:
submission_df.head(10)
走你~
In [ ]: