Na programação tradicional, o foco está no código. Em projetos de machine learning, o foco muda para representação. Ou seja, uma maneira de os desenvolvedores aprimorarem um modelo é adicionando e melhorando os recursos dele.
Como mapear dados brutos para atributos
O lado esquerdo da Figura 1 ilustra dados brutos de uma fonte de dados de entrada. O lado direito ilustra um vetor de atributos, que é o conjunto de valores de ponto flutuante que compõem os exemplos do seu conjunto de dados. Engenharia de atributos significa transformar dados brutos em um vetor de atributos. Espere passar um tempo significativo fazendo engenharia de atributos.
Muitos modelos de machine learning precisam representar os atributos como vetores de número real, já que os valores dos atributos precisam ser multiplicados pelos pesos do modelo.
Figura 1. A engenharia de atributos mapeia dados brutos para atributos de ML.
Como mapear valores numéricos
Dados inteiros e de ponto flutuante não precisam de codificação especial, porque podem ser multiplicados por um peso numérico. Como sugerido na Figura 2, a conversão do valor inteiro bruto 6 para o valor do recurso 6.0 é trivial:
Figura 2. Mapeando valores inteiros para valores de ponto flutuante.
Mapear valores categóricos
Os atributos categóricos têm um conjunto distinto de valores possíveis.
Por exemplo, pode
ter um recurso chamado street_name
com opções que incluem:
{'Charleston Road', 'North Shoreline Boulevard', 'Shorebird Way', 'Rengstorff Avenue'}
Como os modelos não podem multiplicar strings pelos pesos aprendidos, usamos engenharia de atributos para converter strings em valores numéricos.
Isso pode ser feito definindo um mapeamento com base nos valores do atributo, que vamos chamar de vocabulário de valores possíveis para números inteiros. Como nem todas as ruas do mundo aparecerão no nosso conjunto de dados, podemos agrupar todas as outras ruas em uma categoria completa, conhecida como bucket OOV (fora do vocabulário).
Usando essa abordagem, veja como podemos mapear nossos nomes de ruas para números:
- mapear a Rua Charleston para 0
- mapear o North Shoreline Boulevard para 1
- mapa Shorebird Way para 2
- mapear Rengstorff Avenue para 3
- mapear todo o restante (OOV) para 4
No entanto, se incorporarmos esses números de índice diretamente ao nosso modelo, ele imporá algumas restrições que podem ser problemáticas:
Vamos aprender um único peso que se aplica a todas as ruas. Por exemplo, se aprendermos um peso de 6 para
street_name
, vamos multiplicá-lo por 0 para a Charleston Road, para 1 para a North Shoreline Boulevard, 2 para Shorebird Way e assim por diante. Considere um modelo que prevê preços de imóveis usandostreet_name
como atributo. É improvável que haja um ajuste de preço linear com base no nome da rua. Além disso, isso pressupõe que você fez o pedido das ruas com base no preço médio da casa. Nosso modelo precisa da flexibilidade de aprender diferentes pesos para cada rua que serão adicionados ao preço estimado usando os outros atributos.Não estamos considerando casos em que
street_name
pode ter vários valores. Por exemplo, muitas casas estão localizadas na esquina de duas ruas, e não há como codificar essas informações no valor destreet_name
se elas contiverem um único índice.
Para remover essas duas restrições, podemos criar um vetor binário para cada atributo categórico em nosso modelo que representa os valores da seguinte maneira:
- Para valores que se aplicam ao exemplo, defina os elementos vetoriais correspondentes como
1
. - Defina todos os outros elementos como
0
.
A duração do vetor é igual ao número de elementos no vocabulário. Essa representação é chamada de codificação one-hot quando um único valor é 1, e uma codificação multi-hot quando vários valores são 1.
A Figura 3 ilustra uma codificação one-hot de uma rua específica: Shorebird Way.
O elemento no vetor binário da maneira Shorebird tem um valor de 1
, enquanto os
elementos de todas as outras ruas têm valores de 0
.
Figura 3. mapear o endereço em codificação one-hot.
Essa abordagem cria efetivamente uma variável booleana para cada valor do recurso (por exemplo, nome da rua). Aqui, se uma casa está na Shorebird Way, o valor binário é 1 apenas para Shorebird Way. Assim, o modelo usa apenas o peso para o caminho Shorebird.
Da mesma forma, se uma casa estiver no canto de duas ruas, dois valores binários serão definidos como 1, e o modelo usará os respectivos pesos.
Representação esparsa
Suponha que você tenha 1.000.000 de nomes de rua diferentes no conjunto de dados que queira incluir como valores para street_name
. Criar explicitamente um vetor binário de 1.000.000 elementos em que apenas um ou dois elementos são verdadeiros é uma representação muito ineficiente em termos de tempo de armazenamento e computação ao processar esses vetores. Nessa situação, uma abordagem comum é usar uma
representação esparsa em que apenas valores diferentes de zero são armazenados. Nas representações esparsas, um peso de modelo independente ainda é aprendido para cada valor de atributo, conforme descrito acima.