回帰のアンサンブル学習

アンサンブル学習でちょっと思ったこと。
回帰で学習させた場合、アンサンブルのブレンディングで平均をとったり重みを加えたり、
kaggleで涙ぐましい努力を見かけますがブレンディングをする時、それぞれのモデルに多重for文で重みを微調整すると割と精度が上がったので忘備録として残しておく。

単純に0.1刻みとかで多重for文を回して回帰モデルに重みをかけるのが割と良いので試して見て欲しいです

# 【ブレンディング】

精度があがるとは、検証用データに対する平均二乗誤差（MSE）が小さくなることを示します。

kaggleの住宅価格予測からデータを引っ張ってきています。
https://www.kaggle.com/c/house-prices-advanced-regression-techniques/data


```python
import numpy as np
import pandas as pd
from sklearn.linear_model import ElasticNet
from sklearn.tree import DecisionTreeRegressor
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler
import lightgbm as lgb
```


```python
df = pd.read_csv('train.csv')
```


```python
clf1 = lgb.LGBMRegressor()
clf2 = DecisionTreeRegressor(max_depth=2)
clf3 = ElasticNet()
```


```python
X =df.loc[:,['GrLivArea','YearBuilt']]
y = df.loc[:,['SalePrice']]
```


```python
X.describe()
```




<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>GrLivArea</th>
      <th>YearBuilt</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>count</th>
      <td>1460.000000</td>
      <td>1460.000000</td>
    </tr>
    <tr>
      <th>mean</th>
      <td>1515.463699</td>
      <td>1971.267808</td>
    </tr>
    <tr>
      <th>std</th>
      <td>525.480383</td>
      <td>30.202904</td>
    </tr>
    <tr>
      <th>min</th>
      <td>334.000000</td>
      <td>1872.000000</td>
    </tr>
    <tr>
      <th>25%</th>
      <td>1129.500000</td>
      <td>1954.000000</td>
    </tr>
    <tr>
      <th>50%</th>
      <td>1464.000000</td>
      <td>1973.000000</td>
    </tr>
    <tr>
      <th>75%</th>
      <td>1776.750000</td>
      <td>2000.000000</td>
    </tr>
    <tr>
      <th>max</th>
      <td>5642.000000</td>
      <td>2010.000000</td>
    </tr>
  </tbody>
</table>
</div>




```python
y.describe()
```




<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>SalePrice</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>count</th>
      <td>1460.000000</td>
    </tr>
    <tr>
      <th>mean</th>
      <td>180921.195890</td>
    </tr>
    <tr>
      <th>std</th>
      <td>79442.502883</td>
    </tr>
    <tr>
      <th>min</th>
      <td>34900.000000</td>
    </tr>
    <tr>
      <th>25%</th>
      <td>129975.000000</td>
    </tr>
    <tr>
      <th>50%</th>
      <td>163000.000000</td>
    </tr>
    <tr>
      <th>75%</th>
      <td>214000.000000</td>
    </tr>
    <tr>
      <th>max</th>
      <td>755000.000000</td>
    </tr>
  </tbody>
</table>
</div>




```python
num_test = 0.20
sc = StandardScaler()
X=np.array(X)
y=np.array(y)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=num_test, random_state=23)
sc.fit(X_train)
X_train=sc.transform(X_train)
sc.fit(X_test)
X_test=sc.transform(X_test)
```



```python
clf1.fit(X_train,y_train) #LGBM
y_pred1 = clf1.predict(X_test)
np.log(mean_squared_error(y_test ,y_pred1))
```






    21.3135193002795




```python
clf2.fit(X_train,y_train) #決定木
y_pred2 = clf2.predict(X_test)
np.log(mean_squared_error(y_test, y_pred2))
```




    21.734726609958688




```python
clf3.fit(X_train,y_train) #ElasticNet
y_pred3 = clf3.predict(X_test)
np.log(mean_squared_error(y_test, y_pred3))
```




    21.292246763650407




```python
y_pred_all = (y_pred1 + y_pred2 + y_pred3)/3 #単純に三つの回帰を足している
np.log(mean_squared_error(y_test, y_pred_all))
```




    21.198264315267572



凝ったブレンディング。数値を微調整して良い回帰係数を出している。


```python
y3= 100
best_param={}
for x1 in np.arange(0.1,3.0,0.2):
    for x2 in np.arange(0.1,3.0,0.2):
        for x3 in np.arange(0.1,3.0,0.2):
            y_pred_all = (y_pred1*x1+ y_pred2 * x2+ y_pred3 * x3)/3
            y1 = (np.log(mean_squared_error(y_test, y_pred_all)))
            best_param[y1] = [x1,x2,x3]
            y3 = min(y3,y1)

print(y3)
print(best_param[y3]) #もっとも値の良い重みを出している
```

    21.059275607804445
    [1.5000000000000004, 0.1, 1.3000000000000003]