ランダムフォレスト

2016年に作った資料を公開します。もう既にいろいろ古くなってる可能性が高いです。

```python
import numpy as np
#import sklearn.ensemble as ske
import matplotlib.pyplot as plt
from sklearn import svm, grid_search, datasets
from sklearn.ensemble import RandomForestClassifier as RFC
import pandas as pd
%matplotlib inline
import random
from sklearn.metrics import confusion_matrix
from sklearn import cross_validation as cv
from sklearn.utils import shuffle
```

# データをロードしてシャッフル


```python
# データをロードしてシャッフル
iris = datasets.load_iris()
data,target=shuffle(iris.data,iris.target)
```

# ランダムフォレスト分類器の作成


```python
# ランダムフォレスト分類器の作成
classifier=RFC()
```

# ２分割クロスバリデーション


```python
# ２分割クロスバリデーション
n_samples, n_features = data.shape
half = n_samples / 2
# シャッフル後のデータの前半を用いて学習する
classifier.fit(data[:half],target[:half])
```




    RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini',
                max_depth=None, max_features='auto', max_leaf_nodes=None,
                min_samples_leaf=1, min_samples_split=2,
                min_weight_fraction_leaf=0.0, n_estimators=10, n_jobs=1,
                oob_score=False, random_state=None, verbose=0,
                warm_start=False)

# シャッフル後のデータの後半を予測する



```python
# シャッフル後のデータの後半を予測する
pred = classifier.predict(data[half:])
pred
```




    array([1, 0, 2, 0, 2, 2, 1, 1, 1, 2, 2, 0, 0, 2, 1, 0, 0, 2, 1, 0, 1, 1, 2,
           0, 0, 1, 1, 1, 2, 2, 2, 2, 1, 2, 0, 2, 0, 0, 2, 0, 2, 2, 2, 2, 1, 0,
           0, 2, 1, 2, 0, 2, 0, 2, 0, 0, 2, 1, 0, 2, 1, 2, 1, 0, 1, 0, 2, 2, 0,
           1, 1, 0, 0, 2, 1])


# 正解はこちら


```python
# 正解はこちら
target_test = target[half:]
target_test
```




    array([1, 0, 2, 0, 2, 2, 1, 1, 1, 2, 2, 0, 0, 1, 1, 0, 0, 2, 1, 0, 1, 1, 2,
           0, 0, 1, 1, 1, 2, 2, 2, 2, 1, 1, 0, 2, 0, 0, 2, 0, 2, 2, 2, 2, 1, 0,
           0, 2, 1, 2, 0, 2, 0, 2, 0, 0, 2, 1, 0, 2, 1, 2, 1, 0, 1, 0, 2, 2, 0,
           1, 1, 0, 0, 2, 1])


# 予測と正解の比較。第一引数が行、第二引数が列を表す。


```python
# 予測と正解の比較。第一引数が行、第二引数が列を表す。
#pd.DataFrame(confusion_matrix([0, 0, 0],[1,1,1])) #縦横が分からなくなったらこれを実行する
pd.DataFrame(confusion_matrix(pred, target_test))
```




<div>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>0</th>
      <th>1</th>
      <th>2</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>25</td>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <th>1</th>
      <td>0</td>
      <td>21</td>
      <td>0</td>
    </tr>
    <tr>
      <th>2</th>
      <td>0</td>
      <td>2</td>
      <td>27</td>
    </tr>
  </tbody>
</table>
</div>




```python
# cv=5 で５分割クロスバリデーションし精度を計算
score=cv.cross_val_score(classifier,data,target,cv=5,n_jobs=-1)
print("Accuracy: {0:04.4f} (+/- {1:04.4f})".format(score.mean(),score.std()))
```

    Accuracy: 0.9400 (+/- 0.0389)


#どのレコードがどのラベルっぽいか予測された数字。



```python
#どのレコードがどのラベルっぽいか予測された数字。
pd.DataFrame(classifier.predict_proba(data[half:])).T
```




<div>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>0</th>
      <th>1</th>
      <th>2</th>
      <th>3</th>
      <th>4</th>
      <th>5</th>
      <th>6</th>
      <th>7</th>
      <th>8</th>
      <th>9</th>
      <th>...</th>
      <th>65</th>
      <th>66</th>
      <th>67</th>
      <th>68</th>
      <th>69</th>
      <th>70</th>
      <th>71</th>
      <th>72</th>
      <th>73</th>
      <th>74</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>...</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>0.9</td>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <th>1</th>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>1</td>
      <td>1</td>
      <td>0</td>
      <td>...</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>1</td>
      <td>0</td>
      <td>0.1</td>
      <td>0</td>
      <td>1</td>
    </tr>
    <tr>
      <th>2</th>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>1</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>...</td>
      <td>0</td>
      <td>1</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0.0</td>
      <td>1</td>
      <td>0</td>
    </tr>
  </tbody>
</table>
<p>3 rows × 75 columns</p>
</div>


# 各説明変数の寄与度



```python
# 各説明変数の寄与度
classifier.feature_importances_
```




    array([ 0.07622649,  0.04457678,  0.43818701,  0.44100972])


# 寄与度の大きい順に並べる



```python
# 寄与度の大きい順に並べる
ranking = np.argsort(classifier.feature_importances_)[::-1]
ranking
```




    array([3, 2, 0, 1])



# 大きい順に並んだ寄与度


```python
# 大きい順に並んだ寄与度
important_features = classifier.feature_importances_[ranking]
important_features
```




    array([ 0.44100972,  0.43818701,  0.07622649,  0.04457678])

# 寄与度の大きい成分



```python
# 寄与度の大きい成分
ax = plt.subplot(111)
plt.bar(np.arange(len(important_features)),
       important_features, width=1, lw=2)
ax.set_xticks(np.arange(len(important_features))+.5)
ax.set_xticklabels([iris.feature_names[n] for n in ranking], rotation='vertical')
plt.xlim(0, len(important_features))
```




    (0, 4)




![output_12_1.png](https://qiita-image-store.s3.amazonaws.com/0/211162/a5277dff-7762-3ce6-905a-23f553785003.png)


# 予測を難しくするため、不要な特徴量（ノイズ）を加える


```python
# 予測を難しくするため、不要な特徴量（ノイズ）を加える
m = 96
np.random.seed(0)
data = np.c_[data, np.random.randn(n_samples, m)]
feature_names = iris.feature_names
for i in range(96):
    feature_names.append(i)
```

# データの前半を用いて学習する


```python
# データの前半を用いて学習する
classifier.fit(data[:half],target[:half])
```




    RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini',
                max_depth=None, max_features='auto', max_leaf_nodes=None,
                min_samples_leaf=1, min_samples_split=2,
                min_weight_fraction_leaf=0.0, n_estimators=10, n_jobs=1,
                oob_score=False, random_state=None, verbose=0,
                warm_start=False)


# データの後半を予測する


```python
# データの後半を予測する
pred = classifier.predict(data[half:])
pred
```




    array([1, 0, 2, 0, 1, 2, 1, 1, 1, 2, 2, 0, 0, 2, 1, 0, 0, 1, 1, 0, 1, 1, 2,
           0, 0, 2, 1, 1, 2, 1, 1, 1, 1, 2, 0, 1, 0, 0, 1, 0, 2, 2, 1, 2, 1, 0,
           0, 2, 2, 2, 0, 2, 0, 2, 0, 0, 2, 1, 0, 2, 1, 1, 1, 0, 1, 0, 2, 1, 0,
           1, 1, 0, 0, 2, 2])




# 正解はこちら

```python
# 正解はこちら
target_test = target[half:]
target_test
```




    array([1, 0, 2, 0, 2, 2, 1, 1, 1, 2, 2, 0, 0, 1, 1, 0, 0, 2, 1, 0, 1, 1, 2,
           0, 0, 1, 1, 1, 2, 2, 2, 2, 1, 1, 0, 2, 0, 0, 2, 0, 2, 2, 2, 2, 1, 0,
           0, 2, 1, 2, 0, 2, 0, 2, 0, 0, 2, 1, 0, 2, 1, 2, 1, 0, 1, 0, 2, 2, 0,
           1, 1, 0, 0, 2, 1])


# 予測と正解の比較。第一引数が行、第二引数が列を表す。


```python
# 予測と正解の比較。第一引数が行、第二引数が列を表す。
#pd.DataFrame(confusion_matrix([0, 0, 0],[1,1,1])) #縦横が分からなくなったらこれを実行する
pd.DataFrame(confusion_matrix(pred, target_test))
```




<div>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>0</th>
      <th>1</th>
      <th>2</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>25</td>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <th>1</th>
      <td>0</td>
      <td>18</td>
      <td>10</td>
    </tr>
    <tr>
      <th>2</th>
      <td>0</td>
      <td>5</td>
      <td>17</td>
    </tr>
  </tbody>
</table>
</div>


# cv=5 で５分割クロスバリデーションし精度を計算。さっきよりは下がったはず


```python
# cv=5 で５分割クロスバリデーションし精度を計算。さっきよりは下がったはず
score=cv.cross_val_score(classifier,data,target,cv=5,n_jobs=-1)
print("Accuracy: {0:04.4f} (+/- {1:04.4f})".format(score.mean(),score.std()))
```

    Accuracy: 0.8733 (+/- 0.0389)

#どのレコードがどのラベルっぽいか予測された数字。


```python
#どのレコードがどのラベルっぽいか予測された数字。
pd.DataFrame(classifier.predict_proba(data[half:])).T
```




<div>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>0</th>
      <th>1</th>
      <th>2</th>
      <th>3</th>
      <th>4</th>
      <th>5</th>
      <th>6</th>
      <th>7</th>
      <th>8</th>
      <th>9</th>
      <th>...</th>
      <th>65</th>
      <th>66</th>
      <th>67</th>
      <th>68</th>
      <th>69</th>
      <th>70</th>
      <th>71</th>
      <th>72</th>
      <th>73</th>
      <th>74</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>0.1</td>
      <td>0.9</td>
      <td>0.1</td>
      <td>0.9</td>
      <td>0.1</td>
      <td>0.1</td>
      <td>0.0</td>
      <td>0.0</td>
      <td>0.1</td>
      <td>0.0</td>
      <td>...</td>
      <td>0.9</td>
      <td>0.2</td>
      <td>0.1</td>
      <td>0.8</td>
      <td>0.1</td>
      <td>0.0</td>
      <td>0.9</td>
      <td>0.5</td>
      <td>0.2</td>
      <td>0.2</td>
    </tr>
    <tr>
      <th>1</th>
      <td>0.7</td>
      <td>0.1</td>
      <td>0.4</td>
      <td>0.0</td>
      <td>0.5</td>
      <td>0.3</td>
      <td>0.5</td>
      <td>0.5</td>
      <td>0.6</td>
      <td>0.4</td>
      <td>...</td>
      <td>0.1</td>
      <td>0.3</td>
      <td>0.8</td>
      <td>0.2</td>
      <td>0.6</td>
      <td>0.5</td>
      <td>0.1</td>
      <td>0.4</td>
      <td>0.3</td>
      <td>0.3</td>
    </tr>
    <tr>
      <th>2</th>
      <td>0.2</td>
      <td>0.0</td>
      <td>0.5</td>
      <td>0.1</td>
      <td>0.4</td>
      <td>0.6</td>
      <td>0.5</td>
      <td>0.5</td>
      <td>0.3</td>
      <td>0.6</td>
      <td>...</td>
      <td>0.0</td>
      <td>0.5</td>
      <td>0.1</td>
      <td>0.0</td>
      <td>0.3</td>
      <td>0.5</td>
      <td>0.0</td>
      <td>0.1</td>
      <td>0.5</td>
      <td>0.5</td>
    </tr>
  </tbody>
</table>
<p>3 rows × 75 columns</p>
</div>


# どの変数の寄与度が大きいか。（加えたノイズは寄与度が低くなるはず）


```python
# どの変数の寄与度が大きいか。（加えたノイズは寄与度が低くなるはず）
ranking = np.argsort(classifier.feature_importances_)[::-1]
important_features = classifier.feature_importances_[ranking]
plt.figure(figsize=(20, 10))
ax = plt.subplot(111)
plt.bar(np.arange(len(important_features)),
       important_features, width=1, lw=2)
ax.set_xticks(np.arange(len(important_features))+.5)
ax.set_xticklabels([iris.feature_names[n] for n in ranking], rotation='vertical')
plt.xlim(0, len(important_features))
```




    (0, 100)




![output_20_1.png](https://qiita-image-store.s3.amazonaws.com/0/211162/1c00bd0f-d689-b3f7-d544-5af3c4f67ed9.png)


# ベストなパラメーターを探し当てるためのグリッドサーチ


```python
# ベストなパラメーターを探し当てるためのグリッドサーチ
parameters = {
        'n_estimators'      : [50, 100], # The number of trees in the forest.
        #'max_features'      : [3, 5, 10, 15, 20], # The number of features to consider when looking for the best split:
        # 'random_state'      : [0],
        'n_jobs'            : [-1],
        'min_samples_split' : [10, 30],
        'max_depth'         : [10, 30],
        'criterion' : ['gini', 'entropy']
}
clf = grid_search.GridSearchCV(classifier, parameters)
clf.fit(data, target)
 
print(clf.best_estimator_)
```

    RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini',
                max_depth=30, max_features='auto', max_leaf_nodes=None,
                min_samples_leaf=1, min_samples_split=10,
                min_weight_fraction_leaf=0.0, n_estimators=100, n_jobs=-1,
                oob_score=False, random_state=None, verbose=0,
                warm_start=False)



```python

```


```python

```