- [Otto Group Product Classification](#Otto-Group-Product-Classification)
    - [Contexto](#Contexto)
    - [Dados](#Dados)
- [Benchmark](#Benchmark)
- [Cross Validation](#Cross-Validation)
- [Tratamento](#Tratamento)
    - [Correlação](#Correlação)
    - [Filtrando colunas](#Filtrando-colunas)
    - [Resultado](#Resultado)
- [Train/Test split](#Train/Test-split)
    - [Feature Scaling](#Feature-Scaling)
    - [Confusion Matrix](#Confusion-Matrix)
- [Modelo Dummy Classifier](#Modelo-Dummy-Classifier)
- [Boosting](#Boosting)
- [Gradient Descent](#Gradient-Descent)
- [XGBoost](#XGBoost)
    - [Model](#Model)
        - [Objective Function:](#Objective-Function:)
        - [CART](#CART)
    - [Training](#Training)
        - [Additive](#Additive)
- [GridSearchCV](#GridSearchCV)
    - [Aplicando GridSearchCV ao XGBClassifier:](#Aplicando-GridSearchCV-ao-XGBClassifier:)
    - [Aplicando GridSearchCV ao Decision Tree Classifier:](#Aplicando-GridSearchCV-ao-Decision-Tree-Classifier:)
- [Trees](#Trees)
    - [Decision Tree](#Decision-Tree)
    - [Distribuição dos dados](#Distribuição-dos-dados)
        - [Filtrar dados](#Filtrar-dados)
        - [Verificando resultado](#Verificando-resultado)
- [Random Forest](#Random-Forest)
    - [Utilizando o algoritmo](#Utilizando-o-algoritmo)
    - [Verificando com Cross Validation](#Verificando-com-Cross-Validation)
    - [Importancia das features para a RF](#Importancia-das-features-para-a-RF)
        - [Gini](#Gini)
            - [O indice](#O-indice)
            - [Para Decisions Trees](#Para-Decisions-Trees)
            - [Decrease Mean Importance](#Decrease-Mean-Importance)
    - [ExtraTrees](#ExtraTrees)
- [Neurônio Artificial](#Neurônio-Artificial)
    - [Entrada](#Entrada)
    - [Função agregadora](#Função-agregadora)
    - [Neurônio](#Neurônio)
    - [Formula](#Formula)
    - [MLP Classifier](#MLP-Classifier)
- [Conclusão](#Conclusão)
- [Referências Bibliográficas](#Referências-Bibliográficas)

# Otto Group Product Classification

Este notebook é uma proposta de solução utilizando técnicas de data-mining e machine learn para o problema de classificação de produtos da companhia Otto disponíveis em: [Kaggle (challenge): Otto group product classification](https://www.kaggle.com/c/otto-group-product-
classification-challenge)

## Contexto

Retirado da descrição do problema, temos que o grupo Otto é uma das maiores companhias de *e-commerce* do mundo, e possui s filiais em mais de 20 paises. Vendem milhões de produtos ao redor do mundo todos os dias com centezas de produtos sendo adicionados constantemente.

A análise de consistência da performance dos produtos deles é crucial, entretando, com a infraestrutura de escala global que possuem, produtos identicos são classifidados de maneira diferenciada. Entretanto a análise da qualidade dos produtos depende fortemente da acurácia na habilidade de agrupar produtos semelhantes. Quanto melhor for a classificação, mais intuitivamente eles ter um maior alcance com seus produtos.

## Dados

Foram disponibilizados 2 bases de dados separadas. A primeira delas contém 61878 registros com rótulo da classificação do produto e 144368 de registros sem o rótulo.

São um total de 93 características na qual não há a descrição do que significa cada uma delas.  Sendo que não há dados faltando. O range dos dados vão de 0 a 352.

```python
# Configure to show multiples outputs from a single cell
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
import zipfile
import pandas as pd
import matplotlib.pyplot as plt
from pandas.plotting import scatter_matrix
import numpy as np
import math
from sklearn.metrics import classification_report, confusion_matrix
from sklearn.neural_network import MLPClassifier

```

```python
with zipfile.ZipFile('Datasets.zip') as ziped_file:
    with ziped_file.open('Datasets/train.csv') as train_file:
        df_train = pd.read_csv(train_file, header=0).set_index('id')
    with ziped_file.open('Datasets/test.csv') as test_file:
        df_test = pd.read_csv(test_file, header=0).set_index('id')
df_target = pd.DataFrame(df_train.pop('target')) # Get the target
df_target.target = pd.Categorical(df_target.target) # Transform target in Categorical type
df_target['categories'] = df_target.target.cat.codes # Add the codes in a columns
df_target.head() # Show target classes
df_train.head() # The train dataset
df_test.head() # It hasn't target
```

      target
      categories

      id

      1
      Class_1
      0

      2
      Class_1
      0

      3
      Class_1
      0

      4
      Class_1
      0

      5
      Class_1
      0

      feat_1
      feat_2
      feat_3
      feat_4
      feat_5
      feat_6
      feat_7
      feat_8
      feat_9
      feat_10
      ...
      feat_84
      feat_85
      feat_86
      feat_87
      feat_88
      feat_89
      feat_90
      feat_91
      feat_92
      feat_93

      id

      1
      1
      0
      0
      0
      0
      0
      0
      0
      0
      0
      ...
      0
      1
      0
      0
      0
      0
      0
      0
      0
      0

      2
      0
      0
      0
      0
      0
      0
      0
      1
      0
      0
      ...
      0
      0
      0
      0
      0
      0
      0
      0
      0
      0

      3
      0
      0
      0
      0
      0
      0
      0
      1
      0
      0
      ...
      0
      0
      0
      0
      0
      0
      0
      0
      0
      0

      4
      1
      0
      0
      1
      6
      1
      5
      0
      0
      1
      ...
      22
      0
      1
      2
      0
      0
      0
      0
      0
      0

      5
      0
      0
      0
      0
      0
      0
      0
      0
      0
      0
      ...
      0
      1
      0
      0
      0
      0
      1
      0
      0
      0

5 rows × 93 columns

      feat_1
      feat_2
      feat_3
      feat_4
      feat_5
      feat_6
      feat_7
      feat_8
      feat_9
      feat_10
      ...
      feat_84
      feat_85
      feat_86
      feat_87
      feat_88
      feat_89
      feat_90
      feat_91
      feat_92
      feat_93

      id

      1
      0
      0
      0
      0
      0
      0
      0
      0
      0
      3
      ...
      0
      0
      11
      1
      20
      0
      0
      0
      0
      0

      2
      2
      2
      14
      16
      0
      0
      0
      0
      0
      0
      ...
      0
      0
      0
      0
      0
      4
      0
      0
      2
      0

      3
      0
      1
      12
      1
      0
      0
      0
      0
      0
      0
      ...
      0
      0
      0
      0
      2
      0
      0
      0
      0
      1

      4
      0
      0
      0
      1
      0
      0
      0
      0
      0
      0
      ...
      0
      3
      1
      0
      0
      0
      0
      0
      0
      0

      5
      1
      0
      0
      1
      0
      0
      1
      2
      0
      3
      ...
      0
      0
      0
      0
      0
      0
      0
      9
      0
      0

5 rows × 93 columns

# Benchmark

A variável results é um acumulador para salvar os resultados na base de treino e teste de cada um dos modelos e compará-los ao final.

Segue a estrutura:

`
 'modelo':
     'teste': value
     'treino': value
`

```python
from sklearn.model_selection import train_test_split

results = {}
def add_results(model, train, test):
    results[model] = {
        'train': train*100,
        'test': test*100,
    }
```

# Cross Validation

A abordagem para a Validação Cruzada é a utilização do método de k-partições. Neste método, o conjunto de dados é dividido em k partições [(WITTEN e FRANK, 2000)](ftp://ftp.ingv.it/pub/manuela.sbarra/Data%20Mining%20Practical%20Machine%20Learning%20Tools%20and%20Techniques%20-%20WEKA.pdf), testes extensivos em diversas bases de dados, utilizando diversos algoritmos, identificaram o valor de k para identificar a melhor margem de erro como sendo 10, também de forma randômica. Então, o conjunto de dados de treinamento é criado com k – 1 partições, e apenas uma partição é utilizada para testes. São realizadas k iterações, aonde cada partição é utilizada uma vez para testes enquanto as outras são utilizadas para treinamento. Após todas as partições terem sido utilizadas para teste, a margem de erro de cada iteração é somada e a média das k iterações se torna a margem de erro do modelo.

Representação do método Cross Validation com k = 10.
**Fonte**: BABATUNDE et al., 2015.

# Tratamento

Será realizada as etapas de feature selection e feature engineering.  Correlação entre features Será realizada uma análise da correlação entre as features. Visto que há um total de 93 colunas que não foi disponibilizada nenhuma informação sobre o que são elas e o que representam e portanto, esta análize ajudará a identificar as relações entre as features.

## Correlação

A correlação entre duas variáveis é quando existe algum laço matemático que envolve o valor de duas variáveis de alguma forma [ESTATÍSTICA II - CORRELAÇÃO E REGRESSÃO](http://www.ctec.ufal.br/professor/mgn/05CorrelacaoERegressao.pdf).

Uma das maneiras mais simples de se identificar a correlação entre duas variáveis é plotando-as em um gráfico, para tentar identificar alguma relação entre elas, entretanto, como são um total de 93 features, dificulta visualizar a correlação em forma gráfica.

A correlação de [Pearson](https://pt.wikipedia.org/wiki/Coeficiente_de_correla%C3%A7%C3%A3o_de%0A_Pearson) mede o grau da correlação (e a direcção dessa correlação - se positiva ou negativa) entre duas variáveis de escala métrica (intervalar ou de rácio/razão).

Já a correlação de [Spearman](https://pt.wikipedia.org/wiki/Coeficiente_de_correla%C3%A7%C3%A3o_de_postos_de_Spearman) entre duas variáveis é igual à correlação de Pearson entre os valores de postos daquelas duas variáveis. Enquanto a correlação de Pearson avalia relações lineares, a correlação de Spearman avalia relações monótonas, sejam elas lineares ou não.

Visto ambos os tipos de correlação, utilizaremos a de Pearson para avaliar se há alguma correlação linear crescente ou decrescente entre as variáveis, pois esta relação nos possibilita remover uma delas sem prejuizos aos modelos de machine learn.

```python
shape = (df_train.shape[1], df_train.shape[1])
upper_matrix = np.tril(np.ones(shape)).astype(np.bool)
np.fill_diagonal(upper_matrix, False)
correlation = df_train.corr('pearson').abs().where(upper_matrix)
correlation
```

      feat_1
      feat_2
      feat_3
      feat_4
      feat_5
      feat_6
      feat_7
      feat_8
      feat_9
      feat_10
      ...
      feat_84
      feat_85
      feat_86
      feat_87
      feat_88
      feat_89
      feat_90
      feat_91
      feat_92
      feat_93

      feat_1
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_2
      0.031332
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_3
      0.027807
      0.082573
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_4
      0.027529
      0.134987
      0.583523
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_5
      0.042973
      0.020926
      0.010880
      1.729026e-02
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_6
      0.043603
      0.041343
      0.004288
      1.405895e-02
      0.145355
      NaN
      NaN
      NaN
      NaN
      NaN
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_7
      0.298952
      0.222386
      0.001294
      1.448981e-02
      0.075047
      0.088014
      NaN
      NaN
      NaN
      NaN
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_8
      0.056321
      0.019815
      0.053462
      4.618407e-02
      0.035861
      0.012867
      0.038121
      NaN
      NaN
      NaN
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_9
      0.032285
      0.025630
      0.063551
      4.624977e-02
      0.024708
      0.009373
      0.027146
      0.039281
      NaN
      NaN
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_10
      0.097776
      0.051925
      0.036944
      5.951396e-02
      0.091324
      0.041940
      0.194258
      0.000023
      0.024323
      NaN
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_11
      0.042928
      0.118534
      0.596243
      3.894092e-01
      0.004882
      0.014504
      0.012418
      0.065923
      0.075820
      0.006010
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_12
      0.056934
      0.090153
      0.050037
      5.743356e-02
      0.036668
      0.028588
      0.056230
      0.091424
      0.021885
      0.048969
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_13
      0.139254
      0.157467
      0.013870
      2.897317e-02
      0.059081
      0.036293
      0.199142
      0.095365
      0.040164
      0.086682
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_14
      0.063517
      0.070057
      0.111105
      9.921490e-02
      0.037607
      0.027350
      0.044671
      0.061799
      0.110188
      0.029598
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_15
      0.045738
      0.048798
      0.065285
      5.122155e-02
      0.007000
      0.018328
      0.035721
      0.056960
      0.009858
      0.021700
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_16
      0.027086
      0.108046
      0.221426
      2.110780e-01
      0.062877
      0.021934
      0.043957
      0.004659
      0.082664
      0.063997
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_17
      0.053004
      0.074902
      0.023093
      7.553867e-03
      0.062197
      0.015488
      0.127245
      0.173912
      0.028709
      0.092959
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_18
      0.084856
      0.242716
      0.115655
      2.148952e-01
      0.052186
      0.048710
      0.098972
      0.087777
      0.043642
      0.071635
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_19
      0.002302
      0.176655
      0.012228
      3.519107e-07
      0.008556
      0.038493
      0.058071
      0.019387
      0.000167
      0.009015
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_20
      0.070511
      0.449160
      0.011069
      4.465657e-02
      0.046200
      0.057813
      0.364972
      0.062595
      0.023397
      0.176373
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_21
      0.027026
      0.014113
      0.354925
      2.329227e-01
      0.003288
      0.008046
      0.022908
      0.041095
      0.028409
      0.005134
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_22
      0.063283
      0.215106
      0.251082
      2.477378e-01
      0.075161
      0.038939
      0.162620
      0.029032
      0.062348
      0.141405
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_23
      0.048686
      0.162065
      0.002427
      3.062225e-02
      0.017281
      0.043651
      0.186462
      0.012774
      0.006940
      0.096666
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_24
      0.067255
      0.253684
      0.031596
      3.727726e-03
      0.075222
      0.082124
      0.244813
      0.161848
      0.073618
      0.081684
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_25
      0.187237
      0.096366
      0.157459
      1.342306e-01
      0.003610
      0.023319
      0.048820
      0.036939
      0.025279
      0.009792
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_26
      0.022813
      0.064856
      0.268112
      3.657567e-01
      0.025116
      0.004680
      0.008782
      0.041599
      0.066414
      0.003721
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_27
      0.038826
      0.037841
      0.508370
      3.086287e-01
      0.002098
      0.001943
      0.015429
      0.050272
      0.042531
      0.001551
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_28
      0.030257
      0.072494
      0.551398
      4.864171e-01
      0.047688
      0.017132
      0.000998
      0.036668
      0.055545
      0.022349
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_29
      0.069266
      0.025689
      0.004141
      1.427066e-02
      0.065957
      0.002389
      0.046231
      0.104985
      0.021328
      0.068243
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_30
      0.033108
      0.026896
      0.007667
      8.733991e-04
      0.318117
      0.196493
      0.050535
      0.009574
      0.015830
      0.012623
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      ...
      ...
      ...
      ...
      ...
      ...
      ...
      ...
      ...
      ...
      ...
      ...
      ...
      ...
      ...
      ...
      ...
      ...
      ...
      ...
      ...
      ...

      feat_64
      0.010499
      0.005354
      0.065105
      4.728813e-02
      0.021017
      0.002764
      0.011165
      0.003194
      0.702951
      0.022536
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_65
      0.110041
      0.078801
      0.065492
      6.228472e-02
      0.228349
      0.066867
      0.202346
      0.025544
      0.038163
      0.182756
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_66
      0.053010
      0.175620
      0.088017
      1.296545e-01
      0.048364
      0.033285
      0.122660
      0.115175
      0.001778
      0.100722
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_67
      0.154301
      0.068667
      0.110081
      8.045694e-02
      0.061964
      0.038289
      0.148598
      0.320949
      0.176921
      0.043117
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_68
      0.014674
      0.012802
      0.030992
      2.009191e-02
      0.107405
      0.021619
      0.040309
      0.075384
      0.012192
      0.001693
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_69
      0.007544
      0.307406
      0.032748
      1.446082e-02
      0.003294
      0.074836
      0.131430
      0.046258
      0.029335
      0.077354
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_70
      0.165442
      0.112968
      0.018774
      2.079779e-02
      0.118510
      0.052401
      0.237907
      0.023089
      0.056205
      0.322857
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_71
      0.013712
      0.002336
      0.053020
      4.241268e-02
      0.056428
      0.011901
      0.115813
      0.081664
      0.043286
      0.104834
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_72
      0.029983
      0.023267
      0.045339
      2.979578e-02
      0.005177
      0.011090
      0.014921
      0.029868
      0.058147
      0.004225
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_73
      0.140815
      0.039192
      0.013972
      1.128547e-02
      0.001609
      0.025023
      0.022819
      0.028999
      0.022679
      0.000240
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_74
      0.051365
      0.070724
      0.041559
      4.909735e-02
      0.017265
      0.043160
      0.053059
      0.000431
      0.007594
      0.008912
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_75
      0.011596
      0.093689
      0.044724
      3.145389e-02
      0.015279
      0.006951
      0.039865
      0.031466
      0.027313
      0.003828
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_76
      0.153808
      0.259360
      0.028670
      1.379188e-02
      0.035570
      0.073867
      0.375114
      0.081682
      0.027424
      0.106752
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_77
      0.123752
      0.014911
      0.001584
      1.531773e-02
      0.030462
      0.006501
      0.005769
      0.027486
      0.020185
      0.019069
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_78
      0.279202
      0.094256
      0.021979
      1.449856e-02
      0.070709
      0.061250
      0.567084
      0.079623
      0.015922
      0.091760
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_79
      0.228912
      0.033668
      0.020566
      1.083473e-02
      0.055115
      0.009942
      0.066753
      0.083714
      0.036116
      0.113659
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_80
      0.013303
      0.155768
      0.442036
      4.057725e-01
      0.026223
      0.017648
      0.028860
      0.038382
      0.046721
      0.019042
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_81
      0.032427
      0.052101
      0.013089
      2.828377e-02
      0.129333
      0.044136
      0.144308
      0.035102
      0.005847
      0.135928
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_82
      0.026085
      0.119109
      0.438458
      4.365413e-01
      0.057400
      0.014907
      0.022059
      0.034409
      0.039806
      0.029741
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_83
      0.059165
      0.371691
      0.019914
      1.051874e-03
      0.008006
      0.035145
      0.282069
      0.033479
      0.032875
      0.052025
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_84
      0.049634
      0.009845
      0.011159
      5.684499e-03
      0.467329
      0.177777
      0.062634
      0.005064
      0.013569
      0.017939
      ...
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_85
      0.008739
      0.006764
      0.048626
      3.315343e-02
      0.034062
      0.004290
      0.037874
      0.003416
      0.031462
      0.086758
      ...
      0.010210
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_86
      0.107947
      0.039090
      0.096093
      7.102916e-02
      0.013879
      0.010455
      0.009169
      0.029395
      0.019144
      0.159447
      ...
      0.003459
      0.109643
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_87
      0.089374
      0.047451
      0.009838
      5.054728e-03
      0.013999
      0.015256
      0.089574
      0.059929
      0.016925
      0.077421
      ...
      0.013631
      0.049250
      0.073685
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_88
      0.020830
      0.047035
      0.082336
      6.748367e-02
      0.019201
      0.015437
      0.033646
      0.050931
      0.001160
      0.054635
      ...
      0.017903
      0.027886
      0.426972
      0.023053
      NaN
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_89
      0.096851
      0.105527
      0.174781
      1.837145e-01
      0.119951
      0.035042
      0.063511
      0.007974
      0.019147
      0.061498
      ...
      0.103643
      0.053582
      0.011822
      0.066008
      0.022552
      NaN
      NaN
      NaN
      NaN
      NaN

      feat_90
      0.010310
      0.515022
      0.015068
      9.454061e-03
      0.004842
      0.054034
      0.129578
      0.026807
      0.020698
      0.049908
      ...
      0.006013
      0.003931
      0.019803
      0.014696
      0.031679
      0.027764
      NaN
      NaN
      NaN
      NaN

      feat_91
      0.037264
      0.026383
      0.012417
      1.031241e-02
      0.012012
      0.012465
      0.068506
      0.095990
      0.014742
      0.024025
      ...
      0.003444
      0.023091
      0.024005
      0.028850
      0.033653
      0.015917
      0.014812
      NaN
      NaN
      NaN

      feat_92
      0.054777
      0.008219
      0.066921
      8.763105e-02
      0.065331
      0.015479
      0.032261
      0.013608
      0.069707
      0.006869
      ...
      0.048431
      0.043484
      0.049393
      0.001424
      0.070120
      0.129622
      0.035311
      0.104226
      NaN
      NaN

      feat_93
      0.081783
      0.054593
      0.006814
      1.574563e-02
      0.002038
      0.008521
      0.034912
      0.005131
      0.006038
      0.041316
      ...
      0.003723
      0.023390
      0.029035
      0.499990
      0.008631
      0.030650
      0.039864
      0.000045
      0.003653
      NaN

93 rows × 93 columns

## Filtrando colunas

A partir da matriz de correlação assima, buscamos agora identificar quais das colunas possuem uma forte correlação de acordo com a tabela a seguir.

Como sugerido por [Makuka,2012](https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3576830/)

 Interpretação do resultado de correlação

|Valor absoluto|Significado|
|---|---|
|0.9 < v | Muito forte |
|0.7 < v <= 0.9 | Forte |
|0.5 < v <= 0.7 | Moderada |
|0.3 < v <= 0.5 | Fraca |
|0.0 < v <= 0.3 | Desprezível |

```python
strong_correlation = correlation.where(correlation > 0.8)
strong_correlation = strong_correlation.dropna(how='all', axis=(0,1))
corr_features = strong_correlation[strong_correlation.notnull()].stack().index
corr_features_size = len(corr_features)
if corr_features_size:
    col = math.floor(math.log2(corr_features_size)) or 1
    row = math.ceil(corr_features_size/col)
    figure, axis = plt.subplots(row, col, figsize=[15,2*row])
    figure.tight_layout()
    for idx, (feature1, feature2) in enumerate(corr_features):
        if row == 1: # Has a single element
            plot = axis.scatter(df_train[feature1],df_train[feature2])
            plot = axis.set_xlabel(feature1)
            plot = axis.set_ylabel(feature2)
            plot = axis.annotate(strong_correlation[feature2][feature1],xy=(0,0))
        elif col == 1: # Has multiples elements, but is a array
            plot = axis[idx].scatter(df_train[feature1], df_train[feature2])
            plot = axis[idx].set_xlabel(feature1)
            plot = axis[idx].set_ylabel(feature2)
            plot = axis[idx].annotate(strong_correlation[feature2][feature1],xy=(0,0))
        else: # Multitle elements and is a matrix
            plot = axis[int(idx/col), idx%col].scatter(df_train[feature1], df_train[feature2])
            plot = axis[int(idx/col), idx%col].set_xlabel(feature1)
            plot = axis[int(idx/col), idx%col].set_ylabel(feature2)
            plot = axis[int(idx/col), idx%col].annotate(strong_correlation[feature2][feature1],xy=(0,0))
    plt.show()
```

## Resultado

A correlação mostra que não há uma fortíssima correlação entre as features, entretanto, há 10 colunas que estão fortemente correlacionadas. Porem buscamos uma correlação fortíssima para não remover features com comportamentos diferentes.

# Train/Test split

Utilizaremos 80% da base de treino para efetivamente treinar o modelo e 20% para averiguar a performance do modelo.

```python
from sklearn.model_selection import cross_val_score
from sklearn.metrics import confusion_matrix
from sklearn.preprocessing import StandardScaler

X = df_train
y = df_target.categories
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
```

## Feature Scaling

Trata-se do processo de transformar todos os dados da amostra para uma unidade padrão, neste problema utilizaremos a técnica de padronização que consiste em remover a média dos dados e colocar todos na escala do desvio padrão [Wikipedia](https://en.wikipedia.org/wiki/Feature_scaling). Em que $\bar{x}$ é a média e $\sigma$ é o desvio padrão.

\begin{equation}
    x' = \frac{x - \bar{x}}{\sigma}
\end{equation}

```python
sc_X = StandardScaler()
sc_X_train = sc_X.fit_transform(X_train)
sc_X_test = sc_X.transform(X_test)
```

Feature scaling foi aplicado nos dataframes de **features** e utilizado nos modelos, mas o resultado não apresentou mudança. Os modelos continuaram com exatamente as mesmas performances.

## Confusion Matrix

A matriz de confução é uma métrica para algorítmos supervisionados em que é possível estabelecer uma relação entre os acertos e erros durante a classificação do conjunto de amostras. Basicamente elabora-se uma matriz em que nas colunas e linhas são as possíveis classes. Cada célula traz a contagem de amostras que eram da Label X (coluna) e foram classificadas na Label Y (linha). Dessa forma, na matriz, a diagonal principal trará os acertos do classificador [Microsoft](https://docs.microsoft.com/pt-br/sql/analysis-services/data- mining/classification-matrix-analysis-services-data-mining).

 Veja o exemplo a seguir:

|Classificador\Real|Label 1|Label 2|Label 3|
|---|-------|-------|-------|
|**Label 1**|10|10|0|
|**Label 2**|1|10|1|
|**Label 3**|0|0|3|

Plot para matriz de confusão encontrado em [Scikit](http://scikit- learn.org/stable/auto_examples/model_selection/plot_confusion_matrix.html#sphx- glr-auto-examples-model-selection-plot-confusion-matrix-py) e adaptado para o problema

```python
import itertools
import numpy as np
import matplotlib.pyplot as plt

from sklearn.metrics import confusion_matrix

def plot_confusion_matrix(cm, classes,
                          normalize=False,
                          title='Confusion matrix',
                          cmap=plt.cm.Blues):
    """
    This function prints and plots the confusion matrix.
    Normalization can be applied by setting `normalize=True`.
    """
    if normalize:
        cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]
        print("Normalized confusion matrix")
    else:
        print('Confusion matrix, without normalization')

    plt.figure(figsize=(11, 7))
    plt.imshow(cm, interpolation='nearest', cmap=cmap)
    plt.title(title)
    plt.colorbar()

    fmt = '.2f' if normalize else 'd'
    thresh = cm.max() / 2.
    for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
        plt.text(j, i, format(cm[i, j], fmt),
                 horizontalalignment="center",
                 color="white" if cm[i, j] > thresh else "black")

    plt.tight_layout()
    plt.ylabel('True label')
    plt.xlabel('Predicted label')
    plt.show()
```

## Modelo Dummy Classifier

Dummy Classifier é um modelo que faz predições usando regras simples.

O dummy é importante para termos como parâmetro de comparação com outros modelos.Não pode ser utilizado em problemas reais porque ele é apenas para realizar comparações e trabalha com aleatoriedade e frequencia de repetições para realizar as predições.

Usamos dois tipos de estratégia:

* **Stratified**: realiza predições baseadas na distribuição das classes da base de treino. (Ex.: 10% A, 20% B, 50% C, 20% D)
* **Most Frequent**: sempre prediz com a classe mais frequente na base de treino

```python
from sklearn.dummy import DummyClassifier

def dummies(X_train, y_train, X_test, y_test):
    models = ['most_frequent', 'stratified']

    for model in models:
        clf = DummyClassifier(strategy=model)
        clf.fit(X_train, y_train)
        score = clf.score(X_train, y_train)
        y_pred = clf.predict(X_test)
        cm = confusion_matrix(y_test, y_pred)

        plot_confusion_matrix(cm, classes=model)
        # Cross validation
        accuracies = cross_val_score(estimator=clf, X=X_train, y=y_train, cv=10)

        add_results(model, clf.score(X_train, y_train), clf.score(X_test, y_test))
        print(model, 'train dataset score: %.2f' % score)
        print('Média: %.2f' % accuracies.mean())
        print('Desvio padrão: %.4f' % accuracies.std())

dummies(X_train, y_train, X_test, y_test)
```

## Boosting

A definição de boosting é que até mesmo algorítmos fracos de machine larning podem se tornar potentes [(KEARNS, 1988)](https://www.cis.upenn.edu/~mkearns/papers/boostnote.pdf).

Um algorítmo fraco de aprendizagem pode ser definido como modelos ou regras que não possuem boa acurácia ou aparentam ser ineficientes, tais como modelos *dummy*: mais frequente, estratificado, randômico. Já algorítmos de aprendizagem forte, são aqueles que apresentam uma boa taxa de acertos [(FREUND e SCHAPIRE)](http://citeseerx.ist.psu.edu/viewdoc/download;jsessionid=4BF3325D8222B3234BB95971FCAD8759?doi=10.1.1.56.9855&rep=rep1&type=pdf).

**Exemplo - Corrida de cavalos**[(FREUND e SCHAPIRE)](http://citeseerx.ist.psu.edu/viewdoc/download;jsessionid=4BF3325D8222B3234BB95971FCAD8759?doi=10.1.1.56.9855&rep=rep1&type=pdf):

    Como determinar em qual cavalor apostar, considerando um conjunto de dados disponíveis tais como informações do cavalo, do dono, das corridas anteriores e etc. Ao perguntar para especialistas cada um deles irá falar coisas distintas e ainda assim muito imprecisas (modelos fracos)! Mas seria possível utilizar as regras de aposta de cada especialista e gerar uma única regra que seja capaz de predizer o cavalor vencedor da corrida utilizando boost

## Gradient Descent

Um algorítmo de gradient descendent é uma forma de minimizar o valor de uma função interativamente, na qual são dados um conjunto de parametros e ela busca a partir daí o menor valor[(TOUSSAINT, 2012)](https://ipvs.informatik.uni- stuttgart.de/mlr/marc/notes/gradientDescent.pdf). De forma que:

\begin{equation}
    y_{min} = F(x_1) > F(x_2) > F(x_3) > ... > F(x_n),\ onde:\ F(x_n) < precisão
\end{equation}

Um pseudo algorítmo que pode ser proposto para um problema de gradient é:

    x = inital_value
    step = 0.01
    repita
        xprev=x
        x = xperv - step * F(xprev)
    enquanto abs(x - xprev) > precisao

# XGBoost

XGBoost é um algoritmo que implementa *gradient boosting* de Decision Trees de forma rápida e com alta performance.  **Gradient Boosting** é uma técnica de *machine learning* para problemas de regressão e classificação que produz um modelo de predição na forma de *ensemble* de modelos de predições fracas, normalmente árvores de decisões.  Boosting é um processo sequencial, mas como o `XGBoost` consegue implementá-lo de forma paralela?  Sabemos que cada árvore pode ser produzida apenas depois que produzida a árvore anterior, mas o processo de criar as árvores pode ser paralelizado utilizando todos os núcleos a disposição.

## Model

### Objective Function:

\begin{equation}
    \text{obj}(\theta) = L(\theta) + \Omega(\theta)
\end{equation}

**L- Training Loss function**: Mede predição do modelo na base de treino.  (Métrica: *Mean Squared Error*(MSE))
**Omega- Regularization function **: Controla a complexidade do modelo (Ajuda a evitar o *Overfitting*)

nota: As *objective functions* devem sempre possuir *training loss* e *regularization*

### CART

Uso de *CARTs* (Classification And Regression Trees) no ensemble das árvores

Modelo de ensemble de árvores IGUAL ao modelo Random Forest, mas onde está então a diferença?

## Training

### Additive

Training:

Precisamos agora melhorar os paramêtros da função de **Regularization**, mas como fazer isso? Fazer isso aqui é muito mais difícil do que em problemas de otimização tradicionais, onde você pode usar o gradiente para isso. Não é fácil treinar todas as árvores ao mesmo tempo. Em vez disso, usamos uma **estratégia aditiva**: consertamos o que aprendemos e adicionamos uma nova árvore de cada vez.

\begin{split}\hat{y}_i^{(0)} &= 0\\
    \hat{y}_i^{(1)} &= f_1(x_i) = \hat{y}_i^{(0)} + f_1(x_i)\\
    \hat{y}_i^{(2)} &= f_1(x_i) + f_2(x_i)= \hat{y}_i^{(1)} + f_2(x_i)\\
    &\dots\\
    \hat{y}_i^{(t)} &= \sum_{k=1}^t f_k(x_i)= \hat{y}_i^{(t-1)} + f_t(x_i)
\end{split}

```python
%%time
from xgboost import XGBClassifier

def xgboost(X_train, y_train, X_test, y_test):
    xgbclf = XGBClassifier(
        learning_rate=0.01,
        n_estimators=140,
        max_depth=6,
        min_child_weight=6,
        gamma=0,
        subsample=0.8,
        colsample_bytree=0.8,
        nthread=8,
        scale_pos_weight=1
        )
    print('XGBoost fit')
    xgbclf.fit(X_train, y_train)
    print('XGBoost train score')
    train_score = xgbclf.score(X_train, y_train)
    print('XGBoost test score')
    y_pred = xgbclf.predict(X_test)

    print('XGBoost confusion matrix')
    cm = confusion_matrix(y_test, y_pred)

    print('XGBoost cross validation')
    accuracies = cross_val_score(estimator=xgbclf, X=X_train, y=y_train, cv=10)

    print('XGBoost results')
    add_results('xgboost', xgbclf.score(X_train, y_train), xgbclf.score(X_test, y_test))

    plot_confusion_matrix(cm, classes=xgbclf)
    print('Resultado na base de treino %.2f' % train_score)
    print('Resultado Médio na base de teste: %.2f' % accuracies.mean())
    print('Desvio padrão: %.4f' % accuracies.std())

xgboost(X_train, y_train, X_test, y_test)
```

# GridSearchCV

A ferramenta GridSearch disponibilizada pelo Scikit, gera de forma exaustiva candidatos a partir de um grid de  parâmetros especificados com o atributo param_grid.

```python
dt_params = [{
    'max_depth': [40, 50, 60, 80, 100, 120],
    'max_features': [70, 80, 90, 92],
    'min_samples_leaf': [2, 5, 10, 20, 30, 40]
}]

xgb_params = [{
    'max_depth': [4, 5, 6],
    'min_child_weight': [4, 5, 6]
}]
```

```python
%%time
from sklearn.model_selection import GridSearchCV
from sklearn.tree import DecisionTreeClassifier

def search_params(classifier, params):
    clf = classifier()
    grid_search = GridSearchCV(estimator=clf,
                              param_grid=params,
                              cv = 10,
                              n_jobs=-1)

    grid_search = grid_search.fit(X_train, y_train)
    print(grid_search.best_score_, grid_search.best_params_)
    return grid_search.best_score_
```

    CPU times: user 20 ms, sys: 10 ms, total: 30 ms
    Wall time: 371 ms

## Aplicando GridSearchCV ao XGBClassifier:

```python
%%time
from xgboost import XGBClassifier

# Takes long time to run
search_params(XGBClassifier, xgb_params)
```

    0.797705143227 {'max_depth': 6, 'min_child_weight': 6}
    CPU times: user 2min 44s, sys: 667 ms, total: 2min 45s
    Wall time: 1h 30min 54s

## Aplicando GridSearchCV ao Decision Tree Classifier:

```python
search_params(DecisionTreeClassifier, dt_params)
```

    0.724374772736 {'max_depth': 50, 'max_features': 70, 'min_samples_leaf': 10}

    0.72437477273645512

# Trees

## Decision Tree

Os dados são separados recursivamente formando uma árvore de decisão baseada nas features.Pode-se definir uma árvore de decisão, conforme diz (MITCHELL, 1997), como um método para aproximar valores discretos em funções, onde a função de aprendizagem é representada por uma árvore de decisão. Tais árvores aprendidas podem ser representadas - a nível de código fonte - como conjuntos de estruturas condicionais "se-então" para melhorar a leitura e entendimento humano, de acordo com (MITCHELL, 1997).

Estes algoritmos são muito utilizados, segundo (MITCHELL, 1997), na área de algoritmos de inferência indutiva, e dentre as aplicações de tais algoritmos, tem-se máquinas que aprenderam a diagnosticar casos da medicina, ou ainda, para avaliar o risco de inadimplência dos requerentes de créditos em bancos.

Para visualizar de forma mais fácil a representação de uma árvore, a figura 3, representada abaixo, caracteriza uma árvore de decisão em que a máquina deve decidir com base nas variáveis do tempo (ensolarado, nublado ou chuvoso), se pode ou não ocorrer uma partida de tênis. Além das variáveis de tempo, tem-se outras variáveis que podem ser levadas em conta dependendo da condição climática local, como umidade (alta ou normal) e o vento (forte ou fraco).

O algoritmo de árvores de decisão classifica instâncias ou dados, ordenando-os apartir da raiz da árvore, para os nós de suas folhas. Cada nó da árvore exemplifica uma pergunta (teste) de alguns - atributos - de instância, e cada ramo descendente de um nó corresponde para um dos possíveis valores de tal atributo (MITCHELL, 1997). Vale a pena citar: O algoritmo ID3 (QUINLAN, 1986) aprende sobre árvores de decisão construindo-as de cima para baixo (nó raiz para as ramificações) tentando buscar respostas para a pergunta "Qual atributo devemos testar na raiz da árvore?", sendo assim, cada atributo instanciado é calculado por meio de testes estatísticos, para determinar o quão bem (ótimo) tal atributo, isolado dos demais, classifica os exemplos de treinamento.

Quando o melhor atributo é selecionado e utilizado como teste no nó principal da árvore, cria-se um descendente para cada valor admissível deste atributo e os exemplos de treinamento são sorteados para o nó filho mais apropriado. O processo inteiro é então repetido utilizando treinamentos associados a cada descendente para selecionar o melhor atributo para testar na árvore. Quando realizado dessa forma, o algoritmo tenta de forma “gulosa“3.4. O modelo 49 Figura 3 – Exemplo de árvore de decisão, sobre condições para realização de um jogo de tênis.

```python
from sklearn.model_selection import cross_val_score

def fit_tree(X_train, y_train, X_test, y_test, tree_description='decision_tree'):
    tree_clf = DecisionTreeClassifier(max_features=70, min_samples_leaf=10, max_depth=40)
    tree_clf.fit(X_train, y_train)

    inner_score = tree_clf.score(X_train, y_train)
    tree_fit = cross_val_score(tree_clf, X_train, y_train)

    add_results(tree_description, tree_clf.score(X_train, y_train), tree_clf.score(X_test, y_test))

    return inner_score, tree_fit.mean(), tree_fit.std()

"inner: {:.2f} cross: {:.2f} +/- {:.2f}".format(*fit_tree(X_train, y_train, X_test, y_test))
```

    'inner: 0.81 cross: 0.71 +/- 0.01'

## Distribuição dos dados

Um dos modelos a ser utilizado será o decision tree no método de montagem random forest. Este modelo de predição possui um problema de viés quando uma das classes na base de treino é mais predominante do que outra, ou seja, a distribuição das classes na base de treino devem ser semelhantes para evitar problemas de [overfiting](http://docs.aws.amazon.com/machine-learning/latest/dg/model-fit-underfitting-vs-overfitting.html).

Para tanto, precisa-se descobrir qual a contagem de cada classe disponível na base de treino, montaremos um histograma para verificar a diferença entre elas.

```python
counts = [0] *len(df_target.target.cat.categories)

def reduce(target):
    counts[target.categories] += 1
    return counts[target.categories]

df_target['increase_count'] = df_target.apply(reduce, axis=1)
df_target.groupby('target').count()
df_target.groupby('target')['increase_count'].max().sum() == df_target.target.count()
```

      categories
      increase_count

      target

      Class_1
      1929
      1929

      Class_2
      16122
      16122

      Class_3
      8004
      8004

      Class_4
      2691
      2691

      Class_5
      2739
      2739

      Class_6
      14135
      14135

      Class_7
      2839
      2839

      Class_8
      8464
      8464

      Class_9
      4955
      4955

    True

### Filtrar dados

Agora, iremos filtrar os dados deixando apenas os primeiros registros. O critério de filtrar os dados será pegar a classe que possue o menor número e utilizar ele como base para remover os demais, considerando um tamanho máximo de até 2x o da menor classe

```python
distance_percent = 2
minimum_value = df_target.groupby('target')['increase_count'].max().min()
df_rtarget = df_target[ df_target.increase_count < minimum_value*distance_percent ]
df_rtarget.groupby('target').count()
df_rtrain = df_train.drop( df_target[df_target.increase_count >= minimum_value * distance_percent].index )
df_rtrain.shape[0] == df_rtarget.shape[0]
```

      categories
      increase_count

      target

      Class_1
      1929
      1929

      Class_2
      3857
      3857

      Class_3
      3857
      3857

      Class_4
      2691
      2691

      Class_5
      2739
      2739

      Class_6
      3857
      3857

      Class_7
      2839
      2839

      Class_8
      3857
      3857

      Class_9
      3857
      3857

    True

### Verificando resultado

Após aplicar uma melhor distribuição nos dados, rodou-se novamene o algorítmo da decision tree e percebeu-se que a acurácia do modelo diminuiu, e portanto, não será utilizado.

```python
X_tr, X_te, y_tr, y_te = train_test_split(df_rtrain, df_rtarget.target, test_size=0.2)
"inner: {:.2f} cross: {:.2f} +/- {:.2f}".format(*fit_tree(X_tr, y_tr, X_te, y_te))
```

    'inner: 0.77 cross: 0.65 +/- 0.00'

# Random Forest

Breiman breiman, 2001, descreve Random Forests como uma evolução das decisions trees, onde várias ávores são formadas para criar um modelo com maior precisão.  Isto é feito a partir da separação dos Dados em conjutos de dados menores e aleatórios. Cada árvore é contruida a partir de um pedaço aleatório dos dados. Quando um novo dado chega, a predição é feita por todas as Árvores e ao fim é feita uma votação por maioria, ou seja, a categoria com mais votos ganha e o resultado é dado.

De acordo com breiman, 2001, as RFs corrigem a maior parte dos problemas de Overfitting que as Árvores de decisão apresentam. Tudo depende do quanto as DT contidas dentro da Random Forest. Isto é, o quanto elas representam os dados.

## Utilizando o algoritmo

```python
from sklearn.ensemble import RandomForestClassifier

def test_random(params, X_train, y_train, X_test, y_test, name='random_forest'):
    rfclf = RandomForestClassifier(**params)
    rfclf = rfclf.fit(X_train, y_train)

    train_score = rfclf.score(X_train, y_train)
    test_score = rfclf.score(X_test, y_test)

    add_results(name, train_score, test_score)
    return name, train_score, test_score
params = {'n_estimators': 10, 'max_features': 70, 'min_samples_leaf': 10, 'max_depth': 40}
test_random({}, X_train, y_train, X_test, y_test)
test_random(params, X_train, y_train, X_test, y_test, 'random_forest_otimized')
```

    ('random_forest', 0.9920003232192639, 0.77957336780866193)

    ('random_forest_otimized', 0.84002666558926908, 0.7690691661279897)

## Verificando com Cross Validation

Cross validation irá predizer um pedaço do dataset utilizando o modelo treinado com o resto dos dados que não fazem parte deste dataset.

```python
rfclf = RandomForestClassifier(**params)
rfclf.fit(X_train, y_train)
rfscores = cross_val_score(rfclf, X_train, y_train)
print ("{} de precisão".format(rfscores.mean() * 100))

```

    RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini',
                max_depth=40, max_features=70, max_leaf_nodes=None,
                min_impurity_decrease=0.0, min_impurity_split=None,
                min_samples_leaf=10, 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)

    76.09793654862037 de precisão

## Importancia das features para a RF

A seguir vemos quais as influências de cada uma das features para o uso no random forest. Quanto maior no gráfico, maior é a importância da feature.

### Gini

O método utilizado para gerar a importância das features no modelo é a Decrease Mean Importance, que utiliza em seus cálculos um indicador de impureza no sistema. No caso do random forest implementado [(LOUPPE et al.,2013)](https://pdfs.semanticscholar.org/2635/19c5a43fbf981da5ba873062219c50fdf56d.pdf), este indicador é o Gini Impurity que pode ser entendido como uma redução da probabilidade de errar a classificação de uma categoria dentro de um algorítmo de árvore [(Sebastian Raschaka)](https://sebastianraschka.com/faq/docs/decision-tree-binary.html).

#### O indice

O indice de Gini pode ser calculado utilizando a seguinte fórmula[(TEKIMONO,2009)](http://people.revoledu.com/kardi/tutorial/DecisionTree/how-
to-measure-impurity.htm):

\begin{equation}
    Gini = 1- \sum_{i=1} p_i^2
\end{equation}

Em que $p_i$ é a probabilidade da ocorrência de uma determinada classe, desconsiderando os atributos. Ou seja $N_i$ é o número de ocorrências da classe i e N é o total de elementos das classes:

\begin{equation}
    p_i = \frac{N_i}{N}
\end{equation}

#### Para Decisions Trees

Para Classification and Regression Trees (CART), utiliza-se o indice de Gini modificado, isto é, calcula-se ainda as probabilidades em $p_i$, mas agora utiliza-se do indice de Gini nos filhos da esquerda $t_l$ e direita $t_r$. Recalcula-se as probabilidades para ambos os nós também em $p_l$ e $p_r$ utilizando como base as possíveis classes reduzidas a $N_t$ [(LOUPPE et al.,2013)](https://pdfs.semanticscholar.org/2635/19c5a43fbf981da5ba873062219c50fdf56d.pdf).

\begin{equation}
    i(s, t) = Gini(t) - p_l Gini(t_l) - p_r Gini(t_r) \\
    p(t) = \frac{N_{l|r}}{N_t}
\end{equation}

#### Decrease Mean Importance

Para calcular a importância de uma feature X ao tentar predizer uma label Y, utiliza- se os indices de impureza com a proporção de $N_f$ amostras em relação ao total $N$.  $N_T$ é o total de árvores na floresta. Assim, para uma Random Forest a conta é:

\begin{equation}
    I(X_m) = \frac{1}{N_T} \sum_{T} \sum_{t \epsilon T:v(s)=X_m} pf(t)i(s,t) \\
    pf(f) = \frac{N_f}{N}
\end{equation}

```python
fig, axis = plt.subplots(figsize=(15, 5))
plot = axis.bar(df_train.columns, rfclf.feature_importances_)
plot = axis.set_xticklabels(df_train.columns.values, rotation='vertical')
plot = axis.set_xlabel('feature')
plot = axis.set_ylabel('importance')
plt.show()
```

## ExtraTrees

O [Scikit Learn](http://scikit- learn.org/stable/modules/generated/sklearn.ensemble.ExtraTreesClassifier.html) nos apresenta um tipo diferente de random forest que pode apresentar resultados melhores que o [RandomForestClassifier](http://scikit- learn.org/stable/modules/generated/sklearn.ensemble.RandomForestClassifier.html).  Assim como afirma que as extra tree devem ser utilizadas apenas em algorítmos de montagem Como o Extra Trees Classifier e Regressor.

O que diferencia uma extra tree de uma decision tree é a forma que é feita a construção da árvore. Enquanto uma decision tree utiliza cópia dos dados e sub amostras para realizar as divisões de cada nó. Uma extra tree utiliza um ponto de divisão randomico e utiliza toda a base de treino para crescer a árvore [(GEURTS, ERNST e WEHENKEL, 2005)](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.65.7485&rep=rep1&type=pdf).

```python
from sklearn.ensemble import ExtraTreesClassifier

etc = ExtraTreesClassifier()
etscores = cross_val_score(etc, X_train, y_train)
print ("{} de precisão".format((etscores.mean() * 100)))

etc = etc.fit(X_train, y_train)
add_results('extra_trees', etc.score(X_train, y_train), etc.score(X_test, y_test))
print("Inner score", etc.score(X_train, y_train))
```

    76.8898405821295 de precisão
    Inner score 1.0

## Neurônio Artificial

#### Entrada

- Sinais de entrada {x1,x2,...,xn}.
- Cada sinal de entrada e ponderado por 1 peso.{w1,w2,...,wn}.
- O peso é adquirido a partir do treino.

#### Função agregadora

- Recebe todos os sinais e realiza a soma dos produtos dos sinais.

#### Neurônio

- Tem a função de deixar, passar ou inibir um sinal de saida de acordo com a entrada.
- Teta é a limiar de ativacao(ponderado),'u' é o potencial de ativação que é passado para a função (g(u)), que é a função de ativação que é responsavel pela saida que permite o sinal passar ou não ou até mesmo modificalo.

#### Formula

- Potencial de ativação

### MLP Classifier

Esse algoritmo é um classificador Perceptron de Multicamadas usado para fazer o treinamento de modelos, e é uma biblioteca do Scikit-Learn.

```python
%%time

from sklearn.neural_network import MLPClassifier

mlp = MLPClassifier(solver='adam',activation='relu',max_iter=250)
mlp.fit(X_train, y_train)
saidas = mlp.predict(X_test)
scoreTreino =  mlp.score(X_train, y_train)
scoreTeste =  mlp.score(X_test, y_test)

print('Score treino: ', scoreTreino)
print('Score teste: ', scoreTeste)

mlpscores = cross_val_score(mlp, X_train, y_train)

print('Score: {} +/- {}'.format(mlpscores.mean(), mlpscores.std()))

add_results('multi_layer_perceptron', scoreTreino, scoreTeste)
```

    Score treino:  0.87135873298
    Score teste:  0.785956690368
    Score: 0.7825550109810641 +/- 0.007188504494548886
    CPU times: user 4min 13s, sys: 4min 39s, total: 8min 52s
    Wall time: 2min 17s

```python
from sklearn.neural_network import MLPClassifier

mp = confusion_matrix(y_test,saidas);
plot_confusion_matrix(mp, classes=mlp)
```

## Preprocessamento de dados

A rede neural pode ter dificuldade em convergir antes de atingir o número máximo
de iterações permitido se os dados não forem normalizados. Multi-layer
Perceptron é sensível ao dimensionamento de features, portanto, é altamente
recomendável dimensionar seus dados. Usaremos o StandardScaler incorporado para
padronização.

```python
%%time
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
# Fit only to the training data
scaler.fit(X_train)

# Now apply the transformations to the data:
X_train = scaler.transform(X_train)
X_test = scaler.transform(X_test)
```

    CPU times: user 107 ms, sys: 3.33 ms, total: 110 ms
    Wall time: 109 ms

```python
%%time

mlp = MLPClassifier(hidden_layer_sizes=(30,30,30))
mlp.fit(X_train,y_train)
predictions = mlp.predict(X_test)
```

    CPU times: user 1min 21s, sys: 2min 14s, total: 3min 35s
    Wall time: 57.6 s

```python
from sklearn.metrics import classification_report,confusion_matrix
print(classification_report(y_test,predictions))
mp = confusion_matrix(y_test,predictions)
plot_confusion_matrix(mp, classes=mlp)
add_results('MultiLayerPerceptron parametrized', X_train, y_train, X_test, y_test)
```

coefs\_ é uma lista de matrizes de peso, onde a matriz de peso no índice i
representa os pesos entre a camada i e a camada i + 1.

intercepts\_ é uma lista de vetores de polarização, onde o vetor no índice i
representa os valores de polarização adicionados à camada i + 1.

```python
print(len(mlp.coefs_), len(mlp.coefs_[0]), len(mlp.intercepts_[0]))
```

    4 93 30

# Conclusão

Como conclusão, tivemos a utilização do modelo Random Forest e Extreme Gradient Boosting otimizados. Mas o gráfico a seguir irá mostrar os resultados com a base de treino e base de teste.

```python
columns = [x.replace('_',' ') for x in results.keys()]
train = []
test = []
width=0.4
base = np.arange(len(columns))
for key in results:
    train.append(results[key]['train'])
    test.append(results[key]['test'])
fig, ax=plt.subplots(figsize=[10,10])
fig = ax.bar(base, train, width)
fig = ax.bar(base+width, test, width)
fig = ax.set_xticks(base+width/2)
fig = ax.set_xticklabels(columns, rotation='45')
fig = ax.legend(['Base de treino', 'Base de teste'])
plt.show()
```

# Referências Bibliográficas

http://scikit- learn.org/stable/modules/generated/sklearn.dummy.DummyClassifier.html#sklearn.dummy.DummyClassifier

https://www.analyticsvidhya.com/blog/2016/03/complete-guide-parameter-tuning- xgboost-with-codes-python/

http://scikit- learn.org/stable/modules/generated/sklearn.neural_network.MLPClassifier.html

ftp://ftp.sas.com/pub/neural/FAQ3.html#A_hu

[MITCHELL](https://dl.acm.org/citation.cfm?id=505283), Tom M. Machine learning.  1997. Burr Ridge, IL: McGraw Hill, v. 45, n. 37, p. 870-877, 1997.
[QUINLAN](http://hunch.net/~coms-4771/quinlan.pdf), J.. Ross . Induction of decision trees. Machine learning, v. 1, n. 1, p. 81-106, 1986.
[BREIMAN](https://www.stat.berkeley.edu/users/breiman/randomforest2001.pdf), Leo. Random forests. Machine learning, v. 45, n. 1, p. 5-32, 2001.

BABATUNDE, Oluleye, ARMSTRONG, Leisa, DIEPEVEEN, Dean e LENG, J. Comparative analysis of Genetic Algorithm and Particle Swam Optimization: An application in precision agriculture. 2015. **Asian Journal of Computer and Information Systems**. 3.  1-12.


最初に必要なライブラリを読み込みます。

```python
from sympy import *
from sympy.physics.quantum import *
from sympy.physics.quantum.qubit import Qubit, QubitBra, measure_all, measure_all_oneshot
from sympy.physics.quantum.gate import H,X,Y,Z,S,T,CPHASE,CNOT,SWAP,UGate,CGateS,gate_simp
from sympy.physics.quantum.gate import IdentityGate as _I
from sympy.physics.quantum.qft import *

from sympy.printing.dot import dotprint
init_printing()

%matplotlib inline
import matplotlib.pyplot as plt
from sympy.physics.quantum.circuitplot import CircuitPlot,labeller, Mz,CreateOneQubitGate

```

## （狭義の）量子プログラミングの手順

1. 計算に必要な量子ビット（量子レジスタ）を準備して、その値を初期化する

2. 量子計算をユニタリ行列（ゲート演算子）で記述する

3. ユニタリ行列を量子ビットに作用する

4. 測定する

#### （１の例）計算に必要な量子ビット（量子レジスタ）を準備して、その値を初期化する

```python
# 全て 0 の３量子ビットを準備
Qubit('000')
```

#### （２の例）量子計算をユニタリ行列（ゲート演算子）で記述する

```python
# 基本的なユニタリ演算子
pprint(represent(X(0),nqubits=1))
pprint(represent(Y(0),nqubits=1))
pprint(represent(Z(0),nqubits=1))
pprint(represent(H(0),nqubits=1))
pprint(represent(S(0),nqubits=1))
pprint(represent(S(0)**(-1),nqubits=1))
pprint(represent(T(0),nqubits=1))
pprint(represent(T(0)**(-1),nqubits=1))
pprint(represent(CNOT(1,0),nqubits=2))
```

    ⎡0  1⎤
    ⎢    ⎥
    ⎣1  0⎦
    ⎡0  -ⅈ⎤
    ⎢     ⎥
    ⎣ⅈ  0 ⎦
    ⎡1  0 ⎤
    ⎢     ⎥
    ⎣0  -1⎦
    ⎡1    1  ⎤
    ⎢──   ── ⎥
    ⎢√2   √2 ⎥
    ⎢        ⎥
    ⎢1   -√2 ⎥
    ⎢──  ────⎥
    ⎣√2   2  ⎦
    ⎡1  0⎤
    ⎢    ⎥
    ⎣0  ⅈ⎦
    ⎡1  0 ⎤
    ⎢     ⎥
    ⎣0  -ⅈ⎦
    ⎡1   0  ⎤
    ⎢       ⎥
    ⎢    ⅈ⋅π⎥
    ⎢    ───⎥
    ⎢     4 ⎥
    ⎣0  ℯ   ⎦
    ⎡1    0   ⎤
    ⎢         ⎥
    ⎢    -ⅈ⋅π ⎥
    ⎢    ─────⎥
    ⎢      4  ⎥
    ⎣0  ℯ     ⎦
    ⎡1  0  0  0⎤
    ⎢          ⎥
    ⎢0  1  0  0⎥
    ⎢          ⎥
    ⎢0  0  0  1⎥
    ⎢          ⎥
    ⎣0  0  1  0⎦

#### （３の例）ユニタリ行列を量子ビットに作用する

```python
# ユニタリ行列を量子ビットに作用するには、qapply() を使います。
hadamard3 = H(2)*H(1)*H(0)
qapply(hadamard3*Qubit('000'))
```

#### （４の例）測定する

```python
# 測定は、qapply() した量子状態に対して、measure_all_oneshot() で確率的な結果を得ます。
for i in range(10):
    pprint(measure_all_oneshot(qapply(hadamard3*Qubit('000'))))
```

    ❘011⟩
    ❘000⟩
    ❘000⟩
    ❘100⟩
    ❘100⟩
    ❘100⟩
    ❘011⟩
    ❘001⟩
    ❘100⟩
    ❘000⟩

```python
# SymPyの量子シミュレーターでは、内部で量子状態を厳密に計算して、すべての状態を保持しています。
# そのため。measure_all() では、全ての量子状態の確率を得ることができます。
measure_all(qapply(hadamard3*Qubit('000')))
```

## 【練習問題】いつもの説明資料の量子回路をプログラミング手順にそって計算しましょう。

```python
### 1. 計算に必要な量子ビット（量子レジスタ）を準備して、その値を初期化する
## ２量子ビットを 0 で初期化してください。
Qubit('00')
```

```python
### 2. 量子計算をユニタリ行列（ゲート演算子）で記述する
## Hadamard のテンソル積 の行列表現を表示してください。

represent(H(1)*H(0),nqubits=2)
```

```python
## CNOT を Hadamard で挟んだゲート操作 の行列表現を表示してください。

represent(H(0)*CNOT(1,0)*H(0),nqubits=2)
```

```python
### 3. ユニタリ行列を量子ビットに作用する
## Hadamard のテンソル積 を `Qubit('00')` に作用してください。

qapply(H(1)*H(0)*Qubit('00'))
```

```python
## 次に、CNOT を Hadamard で挟んだゲート操作 を 前の状態に作用してください。

qapply(H(0)*CNOT(1,0)*H(0)*H(1)*H(0)*Qubit('00'))
```

```python
### 4. 測定する
## measure_all() を使って、それぞれの状態が測定される確率を表示してください。

measure_all(qapply(H(0)*CNOT(1,0)*H(0)*H(1)*H(0)*Qubit('00')))
```

## 【課題１】グローバーのアルゴリズム

問１）
１. 次の「問１の初期状態」 quest_state を入力として、この量子状態に $\lvert 111 \rangle $ が含まれるか
　グローバーのアルゴリズムを使って調べてください。

２. 上の条件で、この量子状態に $\lvert 101 \rangle $ が含まれるかをグローバーのアルゴリズムを
　使って調べる考察をします。（うまくいかない例を見ます）

　・プログラムを作り、実際は、$\lvert 101 \rangle $ が高確率で検出されることを調べてください。
　・なぜ、初期状態に含まれていない状態が検出されるか理由を考えましょう。（解答は口頭でよい）

問２）
１. 下の「問２の初期状態」quest2_state を入力として、問１と同様、
　$\lvert 111 \rangle $ と $\lvert 101 \rangle $ の状態にの検知について  グローバーのアルゴリズムを適用して、
　その状況を考察してください。

**以降、【課題１】問１−１）の回答欄：**

```python
# 問１の初期状態
quest_state = CNOT(1,0)*CNOT(2,1)*H(2)*H(0)*Qubit('000')
CircuitPlot(quest_state,nqubits=3)
```

```python
# 計算した初期状態を init_state とする
init_state = qapply(quest_state)
init_state
```

```python
# 以降で役立ちそうな関数を定義します。
def CCX(c1,c2,t):  return CGateS((c1,c2),X(t))
def hadamard(s,n):
    h = H(s)
    for i in range(s+1,n+s):
       h = H(i)*h
    return h
def CCZ(c1,c2,t): return (H(t)*CCX(c1,c2,t)*H(t)) # ＣＣＺ演算子を定義します。
def DOp(n): return (Qubit('0'*n)*QubitBra('0'*n)*2-_I(0))     # ゲート操作で計算するには、上記コメントのような演算になります。
h_3 = hadamard(0,3)
d_3 = h_3 * DOp(3) * h_3    # 平均値周りの反転操作
# represent(d_3,nqubits=3)
```

```python
# | 111 > の検索する量子回路を作成する。

mark_7 = CCZ(1,2,0)
grover_7 = gate_simp(d_3*mark_7*d_3*mark_7)
state1_7 = qapply(d_3*mark_7*init_state)
pprint(state1_7)
qapply(d_3*mark_7*state1_7)
```

```python
# 上で作った量子回路を初期状態と作用させて measure_all_oneshot() で何回か試行して、結果をみる。

for i in range(10):
    pprint(measure_all_oneshot(qapply(grover_7*init_state)))
```

    ❘011⟩
    ❘111⟩
    ❘100⟩
    ❘111⟩
    ❘111⟩
    ❘010⟩
    ❘001⟩
    ❘100⟩
    ❘100⟩
    ❘100⟩

**以降、【課題１】問１−２）の回答欄：**

```python
# | 101 > の検索する量子回路を作成する。

mark_5 = X(1)*CCZ(1,2,0)*X(1)
grover_5 = gate_simp(d_3*mark_5*d_3*mark_5)
state1_5 = qapply(d_3*mark_5*init_state)
pprint(state1_5)
qapply(d_3*mark_5*state1_5)
```

```python
# 上で作った量子回路を初期状態と作用させて measure_all() でかく状態の確率をみて、考察する。

measure_all(qapply(grover_5*init_state))
```

**以降、【課題１】問２−１）の回答欄：**

```python
# 問２の初期状態
quest2_state = CNOT(2,1)*H(2)*X(2)*CNOT(2,1)*CNOT(2,0)*H(2)*X(2)*Qubit('000')
CircuitPlot(quest2_state,nqubits=3)
```

```python
# 問２の回答欄（１）

init2_state = qapply(quest2_state)
init2_state
```

```python
# 問２の回答欄（２）

for i in range(10):
    pprint(measure_all_oneshot(qapply(grover_7*init2_state)))
```

    ❘101⟩
    ❘110⟩
    ❘111⟩
    ❘101⟩
    ❘001⟩
    ❘111⟩
    ❘110⟩
    ❘101⟩
    ❘101⟩
    ❘000⟩

```python
# 問２の回答欄（３）

measure_all(qapply(grover_5*init2_state))
```

## 【課題２】量子フーリエ変換

問１）
１. ３量子ビットを対象にした、量子フーリエ変換を行います。
　|000>, |001>, ..., |110>, |111> の全ての状態のそれぞれの QFT の結果を出してください。

　　　ヒント）sympy.physics.quantum.qft の QFT 関数を使います。

２. QFT(0,3) の量子回路図を CircuitPlot() で作図してください。

問２）
１. ３量子ビットを対象にした、量子フーリエ変換を基本的な量子ゲートだけで表してください。
　  $\sqrt{T}$ゲートである Rk(n,4) は利用してもよい。

　・演算をテンソル積で表してください。
　・（この場合の量子回路図は、うまく描けません。）

**以降、【課題２】問１−１）の回答欄：**

```python
## QFT(0,3) の行列表現を表示してください。

qft3=QFT(0,3)
represent(qft3,nqubits=3)
```

```python
# |000> を量子フーリエ変換してください。

qapply(qft3*Qubit('000'))
```

```python
# |001> を量子フーリエ変換してください。

qapply(qft3*Qubit('001'))
```

```python
# |010> を量子フーリエ変換してください。

qapply(qft3*Qubit('010'))
```

```python
# |011> を量子フーリエ変換してください。

qapply(qft3*Qubit('011'))
```

```python
# |100> を量子フーリエ変換してください。

qapply(qft3*Qubit('100'))
```

```python
# |101> を量子フーリエ変換してください。

qapply(qft3*Qubit('101'))
```

```python
# |110> を量子フーリエ変換してください。

qapply(qft3*Qubit('110'))
```

```python
# |111> を量子フーリエ変換してください。

qapply(qft3*Qubit('111'))
```

**以降、【課題２】問１−２）の回答欄：**

```python
### QFT(0,3) は、SymPy ではひと塊りのまとまったオペレータとして定義されています。
### 基本ゲートを知るためには、decompose() を使います。
QFT(0,3).decompose()
```

```python
# QFT(0,3) の量子回路図を CircuitPlot() で作図してください。

CircuitPlot(QFT(0,3).decompose(), nqubits=3)
```

```python
# decompose() した上記の回路を改めて、定義しなおします。
qft3_decomp = SWAP(0,2)*H(0)*CGateS((0,),S(1))*H(1)*CGateS((0,),T(2))*CGateS((1,),S(2))*H(2)
qft3_decomp
```

```python
# 上記で定義しなおした QFT の量子回路図を CircuitPlot() で作図します。
# QFT(0,3).decompose() の量子回路図と比較してください。
CircuitPlot(qft3_decomp,nqubits=3)
```

**以降、【課題２】問２−１）の解答欄：**
（ヒント）$c_{g}$ をグローバル位相として、Z軸回転
$ R_{z\theta} = c_{g} X \cdot R_{z\theta/2}^{\dagger} \cdot X \cdot R_{z\theta/2} $
と表せることを使います。

```python
# S = c・X・T†・X・T であることを示します。
pprint(represent(S(0),nqubits=1))
represent(exp(I*pi/4)*X(0)*T(0)**(-1)*X(0)*T(0),nqubits=1)
```

```python
# T = c・X・sqrt(T)†・X・sqrt(T) であることを示します。
pprint(represent(T(0),nqubits=1))
represent(exp(I*pi/8)*X(0)*Rk(0,4)**(-1)*X(0)*Rk(0,4),nqubits=1)
```

```python
# qft3_decomp = SWAP(0,2)*H(0)*CGateS((0,),S(1))*H(1)*CGateS((0,),T(2))*CGateS((1,),S(2))*H(2)
# qft3_decomp を見ながら、制御Ｓゲートを置き換えて、qft3_decomp2 へ代入します。

qft3_decomp2 = SWAP(0,2)*H(0)*CNOT(0,1)*T(1)**(-1)*CNOT(0,1)*T(1)*H(1)*CGateS((0,),T(2))*CNOT(1,2)*T(2)**(-1)*CNOT(1,2)*T(2)*H(2)
qft3_decomp2
```

```python
# qft3_decomp2 = SWAP(0,2)*H(0)*CNOT(0,1)*T(1)**(-1)*CNOT(0,1)*T(1)*H(1)*CGateS((0,),T(2))*CNOT(1,2)*T(2)**(-1)*CNOT(1,2)*T(2)*H(2)
# qft3_decomp を見ながら、制御Ｔゲートを置き換えて、qft3_decomp3 へ代入します。

qft3_decomp3 = SWAP(0,2)*H(0)*CNOT(0,1)*T(1)**(-1)*CNOT(0,1)*T(1)*H(1)*CNOT(0,2)*Rk(2,4)**(-1)*CNOT(0,2)*Rk(2,4)*CNOT(1,2)*T(2)**(-1)*CNOT(1,2)*T(2)*H(2)
qft3_decomp3
```

```python
# |000> の量子フーリエ変換の結果をみます。
### ゲート操作が少し複雑になるため、SymPyがうまく判断できません。
### represent()で計算します。解答例では、結果が縦ベクトルで行数が長くなるのを嫌い、transpose()します。

# （解答例）transpose(represent(qft3_decomp2*Qubit('000'), nqubits=3))

transpose(represent(qft3_decomp2*Qubit('000'), nqubits=3))
```

```python
# |001> の量子フーリエ変換の結果をみます。
### グローバル位相 exp(I*pi/4) をかけると同じになります。

exp(I*pi/4)*transpose(represent(qft3_decomp2*Qubit('001'), nqubits=3))
```

```python
# |010> の量子フーリエ変換の結果をみます。
### グローバル位相 exp(I*pi/4) をかけると同じになります。

exp(I*pi/4)*transpose(represent(qft3_decomp2*Qubit('010'), nqubits=3))
```

```python
# |011> の量子フーリエ変換の結果をみます。
### グローバル位相 exp(I*pi/2) をかけると同じになります。

exp(I*pi/2)*transpose(represent(qft3_decomp2*Qubit('011'), nqubits=3))
```

```python
# |100> の量子フーリエ変換の結果をみます。

transpose(represent(qft3_decomp2*Qubit('100'), nqubits=3))
```

```python
# |101> の量子フーリエ変換の結果をみます。
### グローバル位相 exp(I*pi/4) をかけると同じになります。

exp(I*pi/4)*transpose(represent(qft3_decomp2*Qubit('101'), nqubits=3))
```

```python
# |110> の量子フーリエ変換の結果をみます。
### グローバル位相 exp(I*pi/4) をかけると同じになります。

exp(I*pi/4)*transpose(represent(qft3_decomp2*Qubit('110'), nqubits=3))
```

```python
# |111> の量子フーリエ変換の結果をみます。
### グローバル位相 exp(I*pi/2) をかけると同じになります。

exp(I*pi/2)*transpose(represent(qft3_decomp2*Qubit('111'), nqubits=3))
```

```python

```