|
1 | 1 | import pandas as pd
|
2 |
| - |
| 2 | +import numpy as np |
3 | 3 |
|
4 | 4 | """
|
5 | 5 | Até agora, temos trabalhado apenas com valores numéricos. No entanto, não é incomum
|
|
19 | 19 | para uma tarefa de aprendizado supervisionada) são armazenados na última coluna. Os
|
20 | 20 | algoritmos de aprendizado para classificação que discutimos neste livro não usam
|
21 | 21 | informações ordinais em rótulos de classes.
|
| 22 | +""" |
| 23 | + |
| 24 | +df = pd.DataFrame([['green', 'M', 10.1, 'class1'],['red', 'L', 13.5, 'class2'],['blue', 'XL', 15.3, 'class1']]) |
| 25 | +df.columns = ['color', 'size', 'price', 'classlabel'] |
| 26 | + |
| 27 | +print(df) |
| 28 | + |
| 29 | +""" |
| 30 | +Mapeando atributos ordinais |
| 31 | +""" |
22 | 32 |
|
| 33 | +""" |
23 | 34 | Para certificar-se de que o algoritmo de aprendizado interpreta os recursos ordinais
|
24 | 35 | corretamente, precisamos converter os valores das cadeias categóricas em inteiros.
|
25 | 36 | Infelizmente, não há nenhuma função conveniente que possa derivar automaticamente a ordem
|
26 | 37 | correta das etiquetas do nosso recurso de tamanho. Assim, temos que definir o mapeamento
|
27 | 38 | manualmente. No exemplo simples a seguir, vamos supor que sabemos a diferença entre
|
28 | 39 | os recursos, por exemplo, XL = L + 1 = M + 2.
|
| 40 | +""" |
29 | 41 |
|
| 42 | +size_mapping = {'XL': 3, 'L': 2, 'M': 1} |
| 43 | +df['size'] = df['size'].map(size_mapping) |
| 44 | + |
| 45 | +print(df) |
| 46 | + |
| 47 | +""" |
| 48 | +Se quisermos transformar os valores inteiros de volta para a representação de string |
| 49 | +original em um estágio posterior, podemos simplesmente definir um dicionário de |
| 50 | +mapeamento inverso inv_size_mapping = {v: k for k, v in size_mapping.items()} |
| 51 | +que pode ser usado por meio de o método de mapa dos pandas na coluna de recurso |
| 52 | +transformado semelhante ao dicionário size_mapping que usamos anteriormente. |
30 | 53 | """
|
31 | 54 |
|
32 |
| -df = pd.DataFrame([['green', 'M', 10.1, 'class1'],['red', 'L', 13.5, 'class2'],['blue', 'XL', 15.3, 'class1']]) |
33 |
| -df.columns = ['color', 'size', 'price', 'classlabel'] |
| 55 | + |
| 56 | +""" |
| 57 | +Codificando rótulos de classes |
| 58 | +""" |
| 59 | + |
| 60 | +""" |
| 61 | +Muitas bibliotecas de aprendizado de máquina exigem que os rótulos de classe sejam |
| 62 | +codificados como valores inteiros. Embora a maioria dos estimadores para classificação |
| 63 | +em scikit-learn converta rótulos de classe para inteiros internamente, considera-se |
| 64 | +boa prática fornecer rótulos de classe como matrizes inteiras para evitar falhas |
| 65 | +técnicas. Para codificar os rótulos de classe, podemos usar uma abordagem semelhante |
| 66 | +ao mapeamento dos recursos ordinais discutidos anteriormente. Precisamos lembrar que |
| 67 | +os rótulos de classe não são ordinais e não importa qual número inteiro atribuímos a |
| 68 | +um determinado rótulo de sequência. Assim, podemos simplesmente enumerar os rótulos |
| 69 | +de classe começando em 0 |
| 70 | +""" |
| 71 | + |
| 72 | + |
| 73 | +class_mapping = {label:idx for idx,label in enumerate(np.unique(df['classlabel']))} |
| 74 | +print(class_mapping) |
| 75 | +df['classlabel'] = df['classlabel'].map(class_mapping) |
34 | 76 |
|
35 | 77 | print(df)
|
36 | 78 |
|
37 |
| -size_mapping = {'XL': 3, 'L': 2, 'M': 1} |
38 |
| -df['size'] = df['size'].map(size_mapping) |
| 79 | + |
| 80 | +""" |
| 81 | +Podemos inverter os pares de valor-chave no dicionário de mapeamento da seguinte |
| 82 | +forma para mapear os rótulos de classe convertidos de volta para a representação |
| 83 | +de sequência original: |
| 84 | +""" |
| 85 | + |
| 86 | +inv_class_mapping = {v: k for k, v in class_mapping.items()} |
| 87 | +df['classlabel'] = df['classlabel'].map(inv_class_mapping) |
39 | 88 |
|
40 | 89 | print(df)
|
41 | 90 |
|
| 91 | +""" |
| 92 | +Alternativamente, há uma classe LabelEncoder conveniente implementada diretamente |
| 93 | +no scikit-learn para obter o mesmo: |
| 94 | +""" |
| 95 | + |
| 96 | +from sklearn.preprocessing import LabelEncoder |
| 97 | +class_le = LabelEncoder() |
| 98 | +y = class_le.fit_transform(df['classlabel'].values) |
| 99 | +print(y) |
| 100 | + |
| 101 | + |
| 102 | +""" |
| 103 | +Note que o método fit_transform é apenas um atalho para chamar fit e transform |
| 104 | +separadamente, e podemos usar o método inverse_transform para transformar os |
| 105 | +rótulos de classes inteiras de volta em sua representação de string original: |
| 106 | +""" |
| 107 | +y = class_le.inverse_transform(y) |
| 108 | +print(y) |
| 109 | + |
| 110 | + |
| 111 | +""" |
| 112 | +Executando one-hot enconding em atributos nominais |
| 113 | +""" |
| 114 | + |
| 115 | +""" |
| 116 | +Como os estimadores do scikit-learn tratam os rótulos de classe sem qualquer |
| 117 | +ordem, usamos a conveniente classe LabelEncoder para codificar os rótulos de |
| 118 | +string em inteiros. Pode parecer que poderíamos usar uma abordagem semelhante |
| 119 | +para transformar a coluna de cor nominal do nosso conjunto de dados, da seguinte forma: |
| 120 | +""" |
| 121 | + |
| 122 | +X = df[['color', 'size', 'price']].values |
| 123 | +color_le = LabelEncoder() |
| 124 | +X[:, 0] = color_le.fit_transform(X[:, 0]) |
| 125 | + |
| 126 | +print(X) |
| 127 | + |
| 128 | +""" |
| 129 | +Se pararmos nesse ponto e alimentarmos o array para nosso classificador, faremos |
| 130 | +um dos erros mais comuns ao lidar com dados categóricos. Você pode identificar o |
| 131 | +problema? Embora os valores das cores não estejam em nenhuma ordem específica, |
| 132 | +um algoritmo de aprendizado agora assumirá que verde é maior que azul e vermelho |
| 133 | +é maior que verde. Embora essa suposição esteja incorreta, o algoritmo ainda |
| 134 | +pode produzir resultados úteis. No entanto, esses resultados não seriam ótimos. |
| 135 | +
|
| 136 | +Uma solução comum para esse problema é usar uma técnica chamada codificação |
| 137 | +simples (one-hot encoding). A ideia por trás dessa abordagem é criar |
| 138 | +um novo atributo fictício (dummy feature) para cada valor exclusivo na coluna |
| 139 | +de recurso nominal. Aqui, converteríamos o atributo |
| 140 | +de cores em três novos recursos: azul, verde e vermelho. Valores binários podem então |
| 141 | +ser usados para indicar a cor particular de uma amostra; por exemplo, uma amostra |
| 142 | +azul pode ser codificada como azul = 1, verde = 0, vermelho = 0. Para realizar |
| 143 | +essa transformação, podemos usar o OneHotEncoder implementado no módulo |
| 144 | +scikit-learn.preprocessing: |
| 145 | +
|
| 146 | +Quando inicializamos o OneHotEncoder, definimos a posição da coluna da variável |
| 147 | +que queremos transformar por meio do parâmetro categorical_features (observe que |
| 148 | +a cor é a primeira coluna na matriz de recursos X). Por padrão, o OneHotEncoder |
| 149 | +retorna uma matriz esparsa quando usamos o método transform e convertemos a |
| 150 | +representação de matriz esparsa em uma matriz NumPy regular (densa) para fins |
| 151 | +de visualização por meio do método toarray. As matrizes esparsas são simplesmente |
| 152 | +uma maneira mais eficiente de armazenar grandes conjuntos de dados e uma que é |
| 153 | +suportada por muitas funções scikit-learn, o que é especialmente útil se contiver |
| 154 | +muitos zeros. Para omitir a etapa toarray, poderíamos inicializar o codificador |
| 155 | +como OneHotEncoder (..., sparse = False) para retornar uma matriz NumPy regular. |
| 156 | +""" |
| 157 | + |
| 158 | +from sklearn.preprocessing import OneHotEncoder |
| 159 | +ohe = OneHotEncoder(categorical_features=[0]) |
| 160 | +ohe.fit_transform(X).toarray() |
| 161 | + |
| 162 | + |
| 163 | +""" |
| 164 | +Uma maneira ainda mais conveniente de criar esses recursos fictícios por meio |
| 165 | +de uma codificação simples é usar o método get_dummies implementado em pandas. |
| 166 | +Aplicado em um DataFrame, o método get_dummies só converterá colunas de string |
| 167 | +e deixará todas as outras colunas inalteradas: |
| 168 | +""" |
| 169 | +pd.get_dummies(df[['price', 'color', 'size']]) |
| 170 | + |
0 commit comments