Classificação binária do TensorFlow: exemplo de classificador linear

Os dois mais comuns aprendizagem supervisionada as tarefas são regressão linear e classificador linear. A regressão linear prevê um valor enquanto o classificador linear prevê uma classe. Este tutorial é focado em Classificadores Lineares.

O que é classificador linear?

A Classificador Linear em Machine Learning é um método para encontrar a classe de um objeto com base em suas características para classificação estatística. Toma decisões de classificação com base no valor de uma combinação linear de características de um objeto. O classificador linear é usado em problemas práticos como classificação de documentos e problemas com muitas variáveis.

Os problemas de classificação representam cerca de 80% da tarefa de aprendizado de máquina. A classificação visa prever a probabilidade de cada classe dado um conjunto de entradas. O rótulo (ou seja, a variável dependente) é um valor discreto, denominado classe.

  1. Se o rótulo tiver apenas duas classes, o algoritmo de aprendizagem é um Classificador Binário.
  2. O classificador multiclasse aborda rótulos com mais de duas classes.

Por exemplo, um problema típico de classificação binária é prever a probabilidade de um cliente fazer uma segunda compra. Prever o tipo de animal exibido em uma imagem é um problema de classificação multiclasse, uma vez que existem mais de duas variedades de animais.

A parte teórica deste tutorial coloca o foco principal na classe binária. Você aprenderá mais sobre a função de saída multiclasse em um tutorial futuro.

Como funciona o classificador binário?

Você aprendeu no tutorial anterior que uma função é composta por dois tipos de variáveis, uma variável dependente e um conjunto de recursos (variáveis ​​independentes). Na regressão linear, uma variável dependente é um número real sem intervalo. O objetivo principal é prever seu valor minimizando o erro quadrático médio.

Para o classificador binário do TensorFlow, o rótulo pode ter dois valores inteiros possíveis. Na maioria dos casos, é [0,1] ou [1,2]. Por exemplo, o objetivo é prever se um cliente comprará um produto ou não. O rótulo é definido da seguinte forma:

  • Y = 1 (o cliente comprou o produto)
  • Y = 0 (o cliente não compra o produto)

O modelo utiliza as características X para classificar cada cliente na classe mais provável a que ele pertence, ou seja, potencial comprador ou não.

A probabilidade de sucesso é calculada com regressão logística. O algoritmo calculará uma probabilidade com base no recurso X e prevê um sucesso quando essa probabilidade estiver acima de 50 por cento. Mais formalmente, a probabilidade é calculada conforme mostrado no exemplo de classificação binária do TensorFlow abaixo:

Exemplo de classificação binária

onde 0 é o conjunto de pesos, os recursos eb o viés.

A função pode ser decomposta em duas partes:

  • O modelo linear
  • A função logística

Modelo linear

Você já está familiarizado com a forma como os pesos são calculados. Os pesos são calculados usando um produto escalar:Produto Dot Y é uma função linear de todos os recursos xi. Se o modelo não possuir características, a previsão é igual ao viés, b.

Os pesos indicam a direção da correlação entre os recursos xi e o rótulo y. Uma correlação positiva aumenta a probabilidade da classe positiva, enquanto uma correlação negativa aproxima a probabilidade de 0 (ou seja, classe negativa).

O modelo linear retorna apenas números reais, o que é inconsistente com a medida de probabilidade do intervalo [0,1]. A função logística é necessária para converter a saída do modelo linear em uma probabilidade,

Função logística

A função logística, ou função sigmóide, tem formato de S e a saída desta função está sempre entre 0 e 1.

Exemplo de função logística

Exemplo de função logística
Exemplo de função logística

É fácil substituir a saída da regressão linear na função sigmóide. Isso resulta em um novo número com probabilidade entre 0 e 1.

O classificador pode transformar a probabilidade em uma classe

  • Valores entre 0 e 0.49 passam a ser classe 0
  • Valores entre 0.5 e 1 passam a ser classe 1

Como medir o desempenho do classificador linear?

Precisão

O desempenho geral de um classificador é medido com a métrica de precisão. A precisão coleta todos os valores corretos divididos pelo número total de observações. Por exemplo, um valor de precisão de 80% significa que o modelo está correto em 80% dos casos.

Métrica de Precisão
Meça o desempenho do Classificador Linear usando a métrica de Precisão

Você pode notar uma deficiência nessa métrica, especialmente para a classe de desequilíbrio. Um conjunto de dados de desequilíbrio ocorre quando o número de observações por grupo não é igual. Digamos; você tenta classificar um evento raro com uma função logística. Imagine que o classificador tente estimar a morte de um paciente seguindowing uma doença. Nos dados, 5% dos pacientes falecem. Você pode treinar um classificador para prever o número de mortes e usar a métrica de precisão para avaliar o desempenho. Se o classificador prever 0 morte para todo o conjunto de dados, estará correto em 95% dos casos.

Matriz de confusão

A melhor maneira de avaliar o desempenho de um classificador é observar a matriz de confusão.

Matriz de Confusão
Meça o desempenho do Classificador Linear usando a matriz de confusão

A matriz de confusão visualiza a precisão de um classificador comparando as classes reais e previstas, conforme mostrado no exemplo do Classificador Linear acima. A matriz de confusão binária é composta por squares:

  • TP: Verdadeiro Positivo: Valores previstos corretamente como positivos reais
  • FP: Os valores previstos previram incorretamente um positivo real. ou seja, valores negativos previstos como positivos
  • FN: Falso Negativo: Valores positivos previstos como negativos
  • TN: Verdadeiro Negativo: Valores previstos corretamente como negativos reais

A partir da matriz de confusão, é fácil comparar a classe real e a classe prevista.

Precisão e Sensibilidade

A matriz de confusão fornece uma boa visão do verdadeiro positivo e do falso positivo. Em alguns casos, é preferível ter uma métrica mais concisa.

Precisão

A métrica de precisão mostra a precisão da classe positiva. Ele mede a probabilidade de a previsão da classe positiva estar correta.

Precisão

A pontuação máxima é 1 quando o classificador classifica perfeitamente todos os valores positivos. A precisão por si só não é muito útil porque ignora a classe negativa. A métrica geralmente é combinada com a métrica Recall. A recuperação também é chamada de sensibilidade ou taxa de verdadeiro positivo.

Sensibilidade

A sensibilidade calcula a proporção de classes positivas detectadas corretamente. Essa métrica mostra o quão bom o modelo é para reconhecer uma classe positiva.

Sensibilidade

Classificador Linear com TensorFlow

Para este tutorial, usaremos o conjunto de dados do censo. O objetivo é usar as variáveis ​​do conjunto de dados do censo para prever o nível de renda. Observe que a renda é uma variável binária

  • com valor 1 se a renda > 50k
  • 0 se renda < 50k.

Esta variável é o seu rótulo

Este conjunto de dados inclui oito variáveis ​​categóricas:

  • local de trabalho
  • educação
  • marital
  • ocupação
  • relação
  • raça
  • sexo
  • país nativo

além disso, seis variáveis ​​contínuas:

  • idade
  • fnlwgt
  • número_educação
  • Ganho de capital
  • perda_capital
  • horas_semana

Por meio deste exemplo de classificação do TensorFlow, você entenderá como treinar classificadores lineares do TensorFlow com o estimador do TensorFlow e como melhorar a métrica de precisão.

Procederemos da seguinte forma:

  • Etapa 1) Importe os dados
  • Etapa 2) Conversão de dados
  • Etapa 3) Treine o classificador
  • Etapa 4) Melhorar o modelo
  • Etapa 5) Hiperparâmetro: Lasso e Ridge

Etapa 1) Importe os dados

Primeiro você importa as bibliotecas usadas durante o tutorial.

import tensorflow as tf
import pandas as pd

Em seguida, você importa os dados do archicinco da UCI e define os nomes das colunas. Você usará COLUMNS para nomear as colunas em um quadro de dados do pandas.

Observe que você treinará o classificador usando um dataframe do Pandas.

## Define path data
COLUMNS = ['age','workclass', 'fnlwgt', 'education', 'education_num', 'marital',
           'occupation', 'relationship', 'race', 'sex', 'capital_gain', 'capital_loss',
           'hours_week', 'native_country', 'label']
PATH = "https://archive.ics.uci.edu/ml/machine-learning-databases/adult/adult.data"
PATH_test = "https://archive.ics.uci.edu/ml/machine-learning-databases/adult/adult.test"

Os dados armazenados online já estão divididos entre um conjunto de treinamento e um conjunto de teste.

df_train = pd.read_csv(PATH, skipinitialspace=True, names = COLUMNS, index_col=False)
df_test = pd.read_csv(PATH_test,skiprows = 1, skipinitialspace=True, names = COLUMNS, index_col=False)

O conjunto de trem contém 32,561 observações e o conjunto de teste 16,281

print(df_train.shape, df_test.shape)
print(df_train.dtypes)
(32561, 15) (16281, 15)
age                int64
workclass         object
fnlwgt             int64
education         object
education_num      int64
marital           object
occupation        object
relationship      object
race              object
sex               object
capital_gain       int64
capital_loss       int64
hours_week         int64
native_country    object
label             object
dtype: object

O Tensorflow requer um valor booleano para treinar o classificador. Você precisa converter os valores de string para inteiro. O rótulo é armazenado como um objeto, porém é necessário convertê-lo em um valor numérico. O código abaixo cria um dicionário com os valores a serem convertidos e percorre o item da coluna. Observe que você executa esta operação duas vezes, uma para o teste de trem, uma para o conjunto de testes

label = {'<=50K': 0,'>50K': 1}
df_train.label = [label[item] for item in df_train.label]
label_t = {'<=50K.': 0,'>50K.': 1}
df_test.label = [label_t[item] for item in df_test.label]

Nos dados do trem, há 24,720 rendimentos inferiores a 50 mil e 7841 acima. A proporção é quase a mesma para o conjunto de teste. Consulte este tutorial em Facetas para obter mais informações.

print(df_train["label"].value_counts())
### The model will be correct in atleast 70% of the case
print(df_test["label"].value_counts())
## Unbalanced label
print(df_train.dtypes)
0    24720
1     7841
Name: label, dtype: int64
0    12435
1     3846
Name: label, dtype: int64
age                int64
workclass         object
fnlwgt             int64
education         object
education_num      int64
marital           object
occupation        object
relationship      object
race              object
sex               object
capital_gain       int64
capital_loss       int64
hours_week         int64
native_country    object
label              int64
dtype: object

Etapa 2) Conversão de dados

Algumas etapas são necessárias antes de treinar um classificador linear com Tensorflow. Você precisa preparar os recursos a serem incluídos no modelo. Na regressão de benchmark, você usará os dados originais sem aplicar nenhuma transformação.

O estimador precisa ter uma lista de recursos para treinar o modelo. Conseqüentemente, os dados da coluna precisam ser convertidos em um tensor.

Uma boa prática é definir duas listas de recursos com base em seu tipo e depois passá-las em feature_columns do estimador.

Você começará convertendo recursos contínuos e, em seguida, definirá um intervalo com os dados categóricos.

Os recursos do conjunto de dados têm dois formatos:

  • Número inteiro
  • objeto

Cada recurso é listado nas próximas duas variáveis ​​de acordo com seus tipos.

## Add features to the bucket: 
### Define continuous list
CONTI_FEATURES  = ['age', 'fnlwgt','capital_gain', 'education_num', 'capital_loss', 'hours_week']
### Define the categorical list
CATE_FEATURES = ['workclass', 'education', 'marital', 'occupation', 'relationship', 'race', 'sex', 'native_country']

O feature_column é equipado com um objeto numeric_column para auxiliar na transformação das variáveis ​​​​contínuas em tensor. No código abaixo, você converte todas as variáveis ​​​​de CONTI_FEATURES em um tensor com valor numérico. Isso é obrigatório para construir o modelo. Todas as variáveis ​​independentes precisam ser convertidas no tipo adequado de tensor.

Abaixo, escrevemos um código para permitir que você veja o que está acontecendo por trás de feature_column.numeric_column. Imprimiremos o valor convertido para idade. É para fins explicativos, portanto não há necessidade de entender o código python. Você pode consultar a documentação oficial para entender os códigos.

def print_transformation(feature = "age", continuous = True, size = 2): 
    #X = fc.numeric_column(feature)
    ## Create feature name
    feature_names = [
    feature]

    ## Create dict with the data
    d = dict(zip(feature_names, [df_train[feature]]))

    ## Convert age
    if continuous == True:
        c = tf.feature_column.numeric_column(feature)
        feature_columns = [c]
    else: 
        c = tf.feature_column.categorical_column_with_hash_bucket(feature, hash_bucket_size=size) 
        c_indicator = tf.feature_column.indicator_column(c)
        feature_columns = [c_indicator]
    
## Use input_layer to print the value
    input_layer = tf.feature_column.input_layer(
        features=d,
        feature_columns=feature_columns
        )
    ## Create lookup table
    zero = tf.constant(0, dtype=tf.float32)
    where = tf.not_equal(input_layer, zero)
    ## Return lookup tble
    indices = tf.where(where)
    values = tf.gather_nd(input_layer, indices)
    ## Initiate graph
    sess = tf.Session()
    ## Print value
    print(sess.run(input_layer))
print_transformation(feature = "age", continuous = True) 
[[39.]
 [50.]
 [38.]
 ...
 [58.]
 [22.]
 [52.]]

Os valores são exatamente iguais aos de df_train

continuous_features = [tf.feature_column.numeric_column(k) for k in CONTI_FEATURES]

De acordo com a documentação do TensorFlow, existem diferentes maneiras de converter dados categóricos. Se a lista de vocabulário de um recurso for conhecida e não possuir muitos valores, é possível criar a coluna categórica com categorical_column_with_vocabulary_list. Ele atribuirá um ID a todas as listas de vocabulário exclusivas.

Por exemplo, se um status de variável tiver três valores distintos:

  • Marido
  • Esposa
  • Individual

Então três ID serão atribuídos. Por exemplo, o Marido terá o ID 1, a Esposa o ID 2 e assim por diante.

Para fins ilustrativos, você pode usar este código para converter uma variável de objeto em uma coluna categórica no TensorFlow.

O traço sexo só pode ter dois valores: masculino ou feminino. Quando convertermos o recurso sex, o Tensorflow criará 2 novas colunas, uma para masculino e outra para feminino. Se o sexo for igual a masculino, então a nova coluna masculino será igual a 1 e feminino a 0. Este exemplo é apresentado na tabela abaixo:

linhas sexo depois da transformação masculina feminina
1 masculina => 1 0
2 masculina => 1 0
3 feminina => 0 1

No fluxo tensor:

print_transformation(feature = "sex", continuous = False, size = 2)
[[1. 0.]
 [1. 0.]
 [1. 0.]
 ...
 [0. 1.]
 [1. 0.]
 [0. 1.]]

relationship = tf.feature_column.categorical_column_with_vocabulary_list(
    'relationship', [
        'Husband', 'Not-in-family', 'Wife', 'Own-child', 'Unmarried',
        'Other-relative'])

Abaixo, adicionamos o código Python para imprimir a codificação. Novamente, você não precisa entender o código, o objetivo é ver a transformação

Porém, uma maneira mais rápida de transformar os dados é usar o método categorical_column_with_hash_bucket. Alterar variáveis ​​de string em uma matriz esparsa será útil. Uma matriz esparsa é uma matriz com quase zero. O método cuida de tudo. Você só precisa especificar o número de buckets e a coluna-chave. O número de buckets é a quantidade máxima de grupos que o Tensorflow pode criar. A coluna chave é simplesmente o nome da coluna a ser convertida.

No código abaixo, você cria um loop sobre todos os recursos categóricos.

categorical_features = [tf.feature_column.categorical_column_with_hash_bucket(k, hash_bucket_size=1000) for k in CATE_FEATURES]

Etapa 3) Treine o Classificador

Atualmente, o TensorFlow fornece um estimador para regressão linear e classificação linear.

  • Regressão linear: LinearRegressor
  • Classificação linear: LinearClassifier

A sintaxe do classificador linear é a mesma do tutorial em regressão linear exceto por um argumento, n_class. Você precisa definir a coluna de recursos, o diretório do modelo e comparar com o regressor linear; você tem que definir o número da aula. Para uma regressão logit, o número de turmas é igual a 2.

O modelo calculará os pesos das colunas contidas em Continuous_features e categorical_features.

model = tf.estimator.LinearClassifier(
    n_classes = 2,
    model_dir="ongoing/train", 
    feature_columns=categorical_features+ continuous_features)

saída

INFO:tensorflow:Using default config.
INFO:tensorflow:Using config: {'_model_dir': 'ongoing/train', '_tf_random_seed': None, '_save_summary_steps': 100, '_save_checkpoints_steps': None, '_save_checkpoints_secs': 600, '_session_config': None, '_keep_checkpoint_max': 5, '_keep_checkpoint_every_n_hours': 10000, '_log_step_count_steps': 100, '_train_distribute': None, '_service': None, '_cluster_spec': 
<tensorflow.python.training.server_lib.ClusterSpec object at 0x181f24c898>, '_task_type': 'worker', '_task_id': 0, '_global_id_in_cluster': 0, '_master': '', '_evaluation_master': '', '_is_chief': True, '_num_ps_replicas': 0, '_num_worker_replicas': 1}

Agora que o classificador está definido, você pode criar a função de entrada. O método é o mesmo do tutorial do regressor linear. Aqui, você usa um tamanho de lote de 128 e embaralha os dados.

FEATURES = ['age','workclass', 'fnlwgt', 'education', 'education_num', 'marital', 'occupation', 'relationship', 'race', 'sex', 'capital_gain', 'capital_loss', 'hours_week', 'native_country']
LABEL= 'label'
def get_input_fn(data_set, num_epochs=None, n_batch = 128, shuffle=True):
    return tf.estimator.inputs.pandas_input_fn(
       x=pd.DataFrame({k: data_set[k].values for k in FEATURES}),
       y = pd.Series(data_set[LABEL].values),
       batch_size=n_batch,   
       num_epochs=num_epochs,
       shuffle=shuffle)

Você cria uma função com os argumentos exigidos pelo estimador linear, ou seja, número de épocas, número de lotes e embaralha o conjunto de dados ou nota. Já que você usa o Pandas método para passar os dados para o modelo, você precisa definir as variáveis ​​X como um quadro de dados do pandas. Observe que você percorre todos os dados armazenados em FEATURES.

Vamos treinar o modelo com o objeto model.train. Você usa a função definida anteriormente para alimentar o modelo com os valores apropriados. Observe que você definiu o tamanho do lote como 128 e o número de épocas como Nenhum. O modelo será treinado em mil etapas.

model.train(input_fn=get_input_fn(df_train, 
                                      num_epochs=None,
                                      n_batch = 128,
                                      shuffle=False),
                                      steps=1000)
									 
INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Create CheckpointSaverHook.
INFO:tensorflow: Graph was finalized.
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Saving checkpoints for 1 into ongoing/train/model.ckpt.
INFO:tensorflow:loss = 88.722855, step = 1
INFO:tensorflow:global_step/sec: 65.8282
INFO:tensorflow:loss = 52583.64, step = 101 (1.528 sec)
INFO:tensorflow:global_step/sec: 118.386
INFO:tensorflow:loss = 25203.816, step = 201 (0.837 sec)
INFO:tensorflow:global_step/sec: 110.542
INFO:tensorflow:loss = 54924.312, step = 301 (0.905 sec)
INFO:tensorflow:global_step/sec: 199.03
INFO:tensorflow:loss = 68509.31, step = 401 (0.502 sec)
INFO:tensorflow:global_step/sec: 167.488
INFO:tensorflow:loss = 9151.754, step = 501 (0.599 sec)
INFO:tensorflow:global_step/sec: 220.155
INFO:tensorflow:loss = 34576.06, step = 601 (0.453 sec)
INFO:tensorflow:global_step/sec: 199.016
INFO:tensorflow:loss = 36047.117, step = 701 (0.503 sec)
INFO:tensorflow:global_step/sec: 197.531
INFO:tensorflow:loss = 22608.148, step = 801 (0.505 sec)
INFO:tensorflow:global_step/sec: 208.479
INFO:tensorflow:loss = 22201.918, step = 901 (0.479 sec)
INFO:tensorflow:Saving checkpoints for 1000 into ongoing/train/model.ckpt.
INFO:tensorflow:Loss for final step: 5444.363.

<tensorflow.python.estimator.canned.linear.LinearClassifier at 0x181f223630>

Observe que a perda diminuiu posteriormente durante as últimas 100 etapas, ou seja, de 901 para 1000.

A perda final após mil iterações é 5444. Você pode estimar seu modelo no conjunto de testes e ver o desempenho. Para avaliar o desempenho do seu modelo, você precisa usar o objetoavaliar. Você alimenta o modelo com o conjunto de testes e define o número de épocas como 1, ou seja, os dados irão para o modelo apenas uma vez.

model.evaluate(input_fn=get_input_fn(df_test, 
                                      num_epochs=1,
                                      n_batch = 128,
                                      shuffle=False),
                                      steps=1000)
									  
INFO:tensorflow:Calling model_fn.
WARNING:tensorflow:Trapezoidal rule is known to produce incorrect PR-AUCs; please switch to "careful_interpolation" instead.
WARNING:tensorflow:Trapezoidal rule is known to produce incorrect PR-AUCs; please switch to "careful_interpolation" instead.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Starting evaluation at 2018-06-02-08:28:22
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Restoring parameters from ongoing/train/model.ckpt-1000
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Evaluation [100/1000]
INFO:tensorflow:Finished evaluation at 2018-06-02-08:28:23
INFO:tensorflow:Saving dict for global step 1000: accuracy = 0.7615626, accuracy_baseline = 0.76377374, auc = 0.63300294, auc_precision_recall = 0.50891197, average_loss = 47.12155, global_step = 1000, label/mean = 0.23622628, loss = 5993.6406, precision = 0.49401596, prediction/mean = 0.18454961, recall = 0.38637546

{'accuracy': 0.7615626,
 'accuracy_baseline': 0.76377374,
 'auc': 0.63300294,
 'auc_precision_recall': 0.50891197,
 'average_loss': 47.12155,
 'global_step': 1000,
 'label/mean': 0.23622628,
 'loss': 5993.6406,
 'precision': 0.49401596,
 'prediction/mean': 0.18454961,
 'recall': 0.38637546}

O TensorFlow retorna todas as métricas que você aprendeu na parte teórica. Sem surpresa, a precisão é grande devido ao rótulo desequilibrado. Na verdade, o modelo tem um desempenho ligeiramente melhor do que uma estimativa aleatória. Imagine que o modelo preveja todas as famílias com renda inferior a 50 mil, então o modelo tem uma precisão de 70%. Em uma análise mais detalhada, você pode ver que a previsão e o recall são bastante baixos.

Etapa 4) Melhorar o modelo

Agora que você tem um modelo de benchmark, pode tentar melhorá-lo, ou seja, aumentar a precisão. No tutorial anterior, você aprendeu como melhorar o poder de predição com um termo de interação. Neste tutorial, você revisitará essa ideia adicionando um termo polinomial à regressão.

A regressão polinomial é fundamental quando há não linearidade nos dados. Existem duas maneiras de capturar a não linearidade nos dados.

  • Adicionar termo polinomial
  • Divida a variável contínua em uma variável categórica

Termo polinomial

Na imagem abaixo você pode ver o que é uma regressão polinomial. É uma equação com variáveis ​​X com potências diferentes. Uma regressão polinomial de segundo grau tem duas variáveis, X e X ao quadrado. Terceiro grau tem três variáveis, X, X2e X3

Regressão Polinomial
O que é regressão polinomial

Abaixo, construímos um gráfico com duas variáveis, X e Y. É óbvio que a relação não é linear. Se adicionarmos uma regressão linear, podemos ver que o modelo não consegue capturar o padrão (imagem à esquerda).

Agora, olhe para a imagem à esquerda da imagem abaixo, adicionamos cinco termos à regressão (ou seja, y=x+x2+x3+x4+x5. O modelo agora captura muito melhor o padrão. Este é o poder da regressão polinomial.

Regressão Polinomial

Voltemos ao nosso exemplo. A idade não está numa relação linear com a renda. A idade precoce pode ter um rendimento fixo próximo de zero porque as crianças ou os jovens não trabalham. Depois aumenta na idade activa e diminui durante a reforma. Normalmente é uma forma de U invertido. Uma maneira de capturar esse padrão é adicionar uma potência dois à regressão.

Vamos ver se isso aumenta a precisão.

Você precisa adicionar este novo recurso ao conjunto de dados e na lista de recursos contínuos.

Você adiciona a nova variável no conjunto de dados de treinamento e teste, por isso é mais conveniente escrever uma função.

def square_var(df_t, df_te, var_name = 'age'):
    df_t['new'] = df_t[var_name].pow(2) 
    df_te['new'] = df_te[var_name].pow(2) 
    return df_t, df_te

A função tem 3 argumentos:

  • df_t: define o conjunto de treinamento
  • df_te: define o conjunto de testes
  • var_name = 'age': Defina a variável a ser transformada

Você pode usar o objeto pow(2) para elevar ao quadrado a variável idade. Observe que a nova variável é chamada de 'new'

Agora que a função square_var foi escrita, você pode criar os novos conjuntos de dados.

df_train_new, df_test_new = square_var(df_train, df_test, var_name = 'age')

Como você pode ver, o novo conjunto de dados possui mais um recurso.

print(df_train_new.shape, df_test_new.shape)			
(32561, 16) (16281, 16)

A variável quadrada é chamada de nova no conjunto de dados. Você precisa adicioná-lo à lista de recursos contínuos.

CONTI_FEATURES_NEW  = ['age', 'fnlwgt','capital_gain', 'education_num', 'capital_loss', 'hours_week', 'new']
continuous_features_new = [tf.feature_column.numeric_column(k) for k in CONTI_FEATURES_NEW]

Note que você alterou o diretório do Gráfico. Você não pode treinar modelos diferentes no mesmo diretório. Isso significa que você precisa alterar o caminho do argumento model_dir. Caso contrário, o TensorFlow gerará um erro.

model_1 = tf.estimator.LinearClassifier(
    model_dir="ongoing/train1", 
    feature_columns=categorical_features+ continuous_features_new)
INFO:tensorflow:Using default config.
INFO:tensorflow:Using config: {'_model_dir': 'ongoing/train1', '_tf_random_seed': None, '_save_summary_steps': 100, '_save_checkpoints_steps': None, '_save_checkpoints_secs': 600, '_session_config': None, '_keep_checkpoint_max': 5, '_keep_checkpoint_every_n_hours': 10000, '_log_step_count_steps': 100, '_train_distribute': None, '_service': None, '_cluster_spec': 
<tensorflow.python.training.server_lib.ClusterSpec object at 0x1820f04b70>, '_task_type': 'worker', '_task_id': 0, '_global_id_in_cluster': 0, '_master': '', '_evaluation_master': '', '_is_chief': True, '_num_ps_replicas': 0, '_num_worker_replicas': 1}
FEATURES_NEW = ['age','workclass', 'fnlwgt', 'education', 'education_num', 'marital', 'occupation', 'relationship', 'race', 'sex', 'capital_gain', 'capital_loss', 'hours_week', 'native_country', 'new']
def get_input_fn(data_set, num_epochs=None, n_batch = 128, shuffle=True):
    return tf.estimator.inputs.pandas_input_fn(
       x=pd.DataFrame({k: data_set[k].values for k in FEATURES_NEW}),
       y = pd.Series(data_set[LABEL].values),
       batch_size=n_batch,   
       num_epochs=num_epochs,
       shuffle=shuffle)

Agora que o classificador foi projetado com o novo conjunto de dados, você pode treinar e avaliar o modelo.

model_1.train(input_fn=get_input_fn(df_train, 
                                      num_epochs=None,
                                      n_batch = 128,
                                      shuffle=False),
                                      steps=1000)
INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Create CheckpointSaverHook.
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Saving checkpoints for 1 into ongoing/train1/model.ckpt.
INFO:tensorflow:loss = 88.722855, step = 1
INFO:tensorflow:global_step/sec: 81.487
INFO:tensorflow:loss = 70077.66, step = 101 (1.228 sec)
INFO:tensorflow:global_step/sec: 111.169
INFO:tensorflow:loss = 49522.082, step = 201 (0.899 sec)
INFO:tensorflow:global_step/sec: 128.91
INFO:tensorflow:loss = 107120.57, step = 301 (0.776 sec)
INFO:tensorflow:global_step/sec: 132.546
INFO:tensorflow:loss = 12814.152, step = 401 (0.755 sec)
INFO:tensorflow:global_step/sec: 162.194
INFO:tensorflow:loss = 19573.898, step = 501 (0.617 sec)
INFO:tensorflow:global_step/sec: 204.852
INFO:tensorflow:loss = 26381.986, step = 601 (0.488 sec)
INFO:tensorflow:global_step/sec: 188.923
INFO:tensorflow:loss = 23417.719, step = 701 (0.529 sec)
INFO:tensorflow:global_step/sec: 192.041
INFO:tensorflow:loss = 23946.049, step = 801 (0.521 sec)
INFO:tensorflow:global_step/sec: 197.025
INFO:tensorflow:loss = 3309.5786, step = 901 (0.507 sec)
INFO:tensorflow:Saving checkpoints for 1000 into ongoing/train1/model.ckpt.
INFO:tensorflow:Loss for final step: 28861.898.

<tensorflow.python.estimator.canned.linear.LinearClassifier at 0x1820f04c88>
model_1.evaluate(input_fn=get_input_fn(df_test_new, 
                                      num_epochs=1,
                                      n_batch = 128,
                                      shuffle=False),
                                      steps=1000)
INFO:tensorflow:Calling model_fn.
WARNING:tensorflow:Trapezoidal rule is known to produce incorrect PR-AUCs; please switch to "careful_interpolation" instead.
WARNING:tensorflow:Trapezoidal rule is known to produce incorrect PR-AUCs; please switch to "careful_interpolation" instead.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Starting evaluation at 2018-06-02-08:28:37
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Restoring parameters from ongoing/train1/model.ckpt-1000
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Evaluation [100/1000]
INFO:tensorflow:Finished evaluation at 2018-06-02-08:28:39
INFO:tensorflow:Saving dict for global step 1000: accuracy = 0.7944229, accuracy_baseline = 0.76377374, auc = 0.6093755, auc_precision_recall = 0.54885805, average_loss = 111.0046, global_step = 1000, label/mean = 0.23622628, loss = 14119.265, precision = 0.6682401, prediction/mean = 0.09116262, recall = 0.2576703

{'accuracy': 0.7944229,
 'accuracy_baseline': 0.76377374,
 'auc': 0.6093755,
 'auc_precision_recall': 0.54885805,
 'average_loss': 111.0046,
 'global_step': 1000,
 'label/mean': 0.23622628,
 'loss': 14119.265,
 'precision': 0.6682401,
 'prediction/mean': 0.09116262,
 'recall': 0.2576703}

A variável quadrada melhorou a precisão de 0.76 para 0.79. Vamos ver se você consegue fazer melhor combinando bucketização e termo de interação.

Bucketização e interação

Como você viu antes, um classificador linear é incapaz de capturar corretamente o padrão idade-renda. Isso ocorre porque ele aprende um único peso para cada recurso. Para tornar mais fácil para o classificador, uma coisa que você pode fazer é agrupar o recurso. O agrupamento transforma um recurso numérico em vários determinados com base no intervalo em que ele se enquadra, e cada um desses novos recursos indica se a idade de uma pessoa está dentro desse intervalo.

Com esses novos recursos, o modelo linear pode capturar o relacionamento aprendendo pesos diferentes para cada intervalo.

No TensorFlow, isso é feito com bucketized_column. Você precisa adicionar o intervalo de valores nos limites.

age = tf.feature_column.numeric_column('age')
age_buckets = tf.feature_column.bucketized_column(
    age, boundaries=[18, 25, 30, 35, 40, 45, 50, 55, 60, 65])

Você já sabe que a idade não é linear com a renda. Outra forma de melhorar o modelo é por meio da interação. Nas palavras do TensorFlow, é cruzamento de recursos. O cruzamento de recursos é uma forma de criar novos recursos que são combinações de recursos existentes, o que pode ser útil para um classificador linear que não consegue modelar interações entre recursos.

Você pode dividir a idade com outro recurso, como a educação. Ou seja, alguns grupos provavelmente terão renda alta e outros baixa (pense no estudante de doutorado).

education_x_occupation = [tf.feature_column.crossed_column(
    ['education', 'occupation'], hash_bucket_size=1000)]
age_buckets_x_education_x_occupation = [tf.feature_column.crossed_column(
    [age_buckets, 'education', 'occupation'], hash_bucket_size=1000)]

Para criar uma coluna de características cruzadas, você usa cross_column com as variáveis ​​a serem cruzadas entre colchetes. O hash_bucket_size indica as possibilidades máximas de cruzamento. Para criar interação entre variáveis ​​(pelo menos uma variável precisa ser categórica), você pode usar tf.feature_column.crossed_column. Para usar este objeto, você precisa adicionar entre colchetes a variável para interagir e um segundo argumento, o tamanho do balde. O tamanho do bucket é o número máximo de grupos possível dentro de uma variável. Aqui você define como 1000 porque não sabe o número exato de grupos

age_buckets precisa ser elevado ao quadrado antes de adicioná-lo às colunas de recursos. Você também adiciona os novos recursos às colunas de recursos e prepara o estimador

base_columns = [
    age_buckets,
]

model_imp = tf.estimator.LinearClassifier(
    model_dir="ongoing/train3", 
    feature_columns=categorical_features+base_columns+education_x_occupation+age_buckets_x_education_x_occupation)

saída

INFO:tensorflow:Using default config.
INFO:tensorflow:Using config: {'_model_dir': 'ongoing/train3', '_tf_random_seed': None, '_save_summary_steps': 100, '_save_checkpoints_steps': None, '_save_checkpoints_secs': 600, '_session_config': None, '_keep_checkpoint_max': 5, '_keep_checkpoint_every_n_hours': 10000, '_log_step_count_steps': 100, '_train_distribute': None, '_service': None, '_cluster_spec': <tensorflow.python.training.server_lib.ClusterSpec object at 0x1823021be0>, '_task_type': 'worker', '_task_id': 0, '_global_id_in_cluster': 0, '_master': '', '_evaluation_master': '', '_is_chief': True, '_num_ps_replicas': 0, '_num_worker_replicas': 1}
FEATURES_imp = ['age','workclass', 'education', 'education_num', 'marital',
                'occupation', 'relationship', 'race', 'sex', 'native_country', 'new']

def get_input_fn(data_set, num_epochs=None, n_batch = 128, shuffle=True):
    return tf.estimator.inputs.pandas_input_fn(
       x=pd.DataFrame({k: data_set[k].values for k in FEATURES_imp}),
       y = pd.Series(data_set[LABEL].values),
       batch_size=n_batch,   
       num_epochs=num_epochs,
       shuffle=shuffle)

Você está pronto para estimar o novo modelo e ver se ele melhora a precisão.

model_imp.train(input_fn=get_input_fn(df_train_new, 
                                      num_epochs=None,
                                      n_batch = 128,
                                      shuffle=False),
                                      steps=1000)
									  
INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Create CheckpointSaverHook.
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Saving checkpoints for 1 into ongoing/train3/model.ckpt.
INFO:tensorflow:loss = 88.722855, step = 1
INFO:tensorflow:global_step/sec: 94.969
INFO:tensorflow:loss = 50.334488, step = 101 (1.054 sec)
INFO:tensorflow:global_step/sec: 242.342
INFO:tensorflow:loss = 56.153225, step = 201 (0.414 sec)
INFO:tensorflow:global_step/sec: 213.686
INFO:tensorflow:loss = 45.792007, step = 301 (0.470 sec)
INFO:tensorflow:global_step/sec: 174.084
INFO:tensorflow:loss = 37.485672, step = 401 (0.572 sec)
INFO:tensorflow:global_step/sec: 191.78
INFO:tensorflow:loss = 56.48449, step = 501 (0.524 sec)
INFO:tensorflow:global_step/sec: 163.436
INFO:tensorflow:loss = 32.528934, step = 601 (0.612 sec)
INFO:tensorflow:global_step/sec: 164.347
INFO:tensorflow:loss = 37.438057, step = 701 (0.607 sec)
INFO:tensorflow:global_step/sec: 154.274
INFO:tensorflow:loss = 61.1075, step = 801 (0.647 sec)
INFO:tensorflow:global_step/sec: 189.14
INFO:tensorflow:loss = 44.69645, step = 901 (0.531 sec)
INFO:tensorflow:Saving checkpoints for 1000 into ongoing/train3/model.ckpt.
INFO:tensorflow:Loss for final step: 44.18133.

<tensorflow.python.estimator.canned.linear.LinearClassifier at 0x1823021cf8>
model_imp.evaluate(input_fn=get_input_fn(df_test_new, 
                                      num_epochs=1,
                                      n_batch = 128,
                                      shuffle=False),
                                      steps=1000)
									  
INFO:tensorflow:Calling model_fn.
WARNING:tensorflow:Trapezoidal rule is known to produce incorrect PR-AUCs; please switch to "careful_interpolation" instead.
WARNING:tensorflow:Trapezoidal rule is known to produce incorrect PR-AUCs; please switch to "careful_interpolation" instead.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Starting evaluation at 2018-06-02-08:28:52
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Restoring parameters from ongoing/train3/model.ckpt-1000
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Evaluation [100/1000]
INFO:tensorflow:Finished evaluation at 2018-06-02-08:28:54
INFO:tensorflow:Saving dict for global step 1000: accuracy = 0.8358209, accuracy_baseline = 0.76377374, auc = 0.88401634, auc_precision_recall = 0.69599575, average_loss = 0.35122654, global_step = 1000, label/mean = 0.23622628, loss = 44.67437, precision = 0.68986726, prediction/mean = 0.23320661, recall = 0.55408216


{'accuracy': 0.8358209,
 'accuracy_baseline': 0.76377374,
 'auc': 0.88401634,
 'auc_precision_recall': 0.69599575,
 'average_loss': 0.35122654,
 'global_step': 1000,
 'label/mean': 0.23622628,
 'loss': 44.67437,
 'precision': 0.68986726,
 'prediction/mean': 0.23320661,
 'recall': 0.55408216}

O novo nível de precisão é de 83.58%. É quatro por cento maior que o modelo anterior.

Finalmente, você pode adicionar um termo de regularização para evitar overfitting.

Etapa 5) Hiperparâmetro: Lasso e Ridge

Seu modelo pode sofrer sobreajuste or insuficiente.

  • Overfitting: o modelo é incapaz de generalizar a previsão para novos dados
  • Underfitting: O modelo não consegue capturar o padrão dos dados. ou seja, regressão linear quando os dados são não lineares

Quando um modelo tem muitos parâmetros e uma quantidade relativamente baixa de dados, isso leva a previsões ruins. Imagine, um grupo tem apenas três observações; o modelo calculará um peso para este grupo. O peso é usado para fazer uma previsão; se as observações do conjunto de teste para este grupo específico forem totalmente diferentes do conjunto de treinamento, então o modelo fará uma previsão errada. Durante a avaliação com o conjunto de treinamento, a precisão é boa, mas não boa com o conjunto de teste porque os pesos calculados não são os verdadeiros para generalizar o padrão. Neste caso, não faz uma previsão razoável sobre dados não vistos.

Para evitar overfitting, a regularização oferece a possibilidade de controlar tais comunicações.plexe torná-lo mais generalizável. Existem duas técnicas de regularização:

  • L1: Laço
  • L2: Cume

No TensorFlow, você pode adicionar esses dois hiperparâmetros no otimizador. Por exemplo, quanto maior o hiperparâmetro L2, o peso tende a ser muito baixo e próximo de zero. A linha ajustada será muito plana, enquanto um L2 próximo de zero implica que os pesos estão próximos da regressão linear regular.

Você pode tentar sozinho os diferentes valores dos hiperparâmetros e ver se consegue aumentar o nível de precisão.

Note que se você alterar o hiperparâmetro, precisará excluir a pasta em andamento/train4 otherwise o modelo começará com o modelo previamente treinado.

Vamos ver como está a precisão com o hype

model_regu = tf.estimator.LinearClassifier(
    model_dir="ongoing/train4", feature_columns=categorical_features+base_columns+education_x_occupation+age_buckets_x_education_x_occupation,
    optimizer=tf.train.FtrlOptimizer(
        learning_rate=0.1,
        l1_regularization_strength=0.9,
        l2_regularization_strength=5))

SAÍDA

INFO:tensorflow:Using default config.
INFO:tensorflow:Using config: {'_model_dir': 'ongoing/train4', '_tf_random_seed': None, '_save_summary_steps': 100, '_save_checkpoints_steps': None, '_save_checkpoints_secs': 600, '_session_config': None, '_keep_checkpoint_max': 5, '_keep_checkpoint_every_n_hours': 10000, '_log_step_count_steps': 100, '_train_distribute': None, '_service': None, '_cluster_spec': <tensorflow.python.training.server_lib.ClusterSpec object at 0x1820d9c128>, '_task_type': 'worker', '_task_id': 0, '_global_id_in_cluster': 0, '_master': '', '_evaluation_master': '', '_is_chief': True, '_num_ps_replicas': 0, '_num_worker_replicas': 1}
model_regu.train(input_fn=get_input_fn(df_train_new, 
                                      num_epochs=None,
                                      n_batch = 128,
                                      shuffle=False),
                                      steps=1000)

SAÍDA

INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Create CheckpointSaverHook.
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Saving checkpoints for 1 into ongoing/train4/model.ckpt.
INFO:tensorflow:loss = 88.722855, step = 1
INFO:tensorflow:global_step/sec: 77.4165
INFO:tensorflow:loss = 50.38778, step = 101 (1.294 sec)
INFO:tensorflow:global_step/sec: 187.889
INFO:tensorflow:loss = 55.38014, step = 201 (0.535 sec)
INFO:tensorflow:global_step/sec: 201.895
INFO:tensorflow:loss = 46.806694, step = 301 (0.491 sec)
INFO:tensorflow:global_step/sec: 217.992
INFO:tensorflow:loss = 38.68271, step = 401 (0.460 sec)
INFO:tensorflow:global_step/sec: 193.676
INFO:tensorflow:loss = 56.99398, step = 501 (0.516 sec)
INFO:tensorflow:global_step/sec: 202.195
INFO:tensorflow:loss = 33.263622, step = 601 (0.497 sec)
INFO:tensorflow:global_step/sec: 216.756
INFO:tensorflow:loss = 37.7902, step = 701 (0.459 sec)
INFO:tensorflow:global_step/sec: 240.215
INFO:tensorflow:loss = 61.732605, step = 801 (0.416 sec)
INFO:tensorflow:global_step/sec: 220.336
INFO:tensorflow:loss = 46.938225, step = 901 (0.456 sec)
INFO:tensorflow:Saving checkpoints for 1000 into ongoing/train4/model.ckpt.
INFO:tensorflow:Loss for final step: 43.4942.


<tensorflow.python.estimator.canned.linear.LinearClassifier at 0x181ff39e48>
model_regu.evaluate(input_fn=get_input_fn(df_test_new, 
                                      num_epochs=1,
                                      n_batch = 128,
                                      shuffle=False),
                                      steps=1000)

saída

INFO:tensorflow:Calling model_fn.
WARNING:tensorflow:Trapezoidal rule is known to produce incorrect PR-AUCs; please switch to "careful_interpolation" instead.
WARNING:tensorflow:Trapezoidal rule is known to produce incorrect PR-AUCs; please switch to "careful_interpolation" instead.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Starting evaluation at 2018-06-02-08:29:07
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Restoring parameters from ongoing/train4/model.ckpt-1000
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Evaluation [100/1000]
INFO:tensorflow:Finished evaluation at 2018-06-02-08:29:09
INFO:tensorflow:Saving dict for global step 1000: accuracy = 0.83833915, accuracy_baseline = 0.76377374, auc = 0.8869794, auc_precision_recall = 0.7014905, average_loss = 0.34691378, global_step = 1000, label/mean = 0.23622628, loss = 44.12581, precision = 0.69720596, prediction/mean = 0.23662092, recall = 0.5579823





{'accuracy': 0.83833915,
 'accuracy_baseline': 0.76377374,
 'auc': 0.8869794,
 'auc_precision_recall': 0.7014905,
 'average_loss': 0.34691378,
 'global_step': 1000,
 'label/mean': 0.23622628,
 'loss': 44.12581,
 'precision': 0.69720596,
 'prediction/mean': 0.23662092,
 'recall': 0.5579823}

Com este hiperparâmetro, você aumenta ligeiramente as métricas de precisão. No próximo tutorial, você aprenderá como melhorar um classificador linear usando um método kernel.

Resumo

Para treinar um modelo, você precisa:

  • Defina os recursos: Variáveis ​​independentes: X
  • Defina o rótulo: Variável dependente: y
  • Construa um conjunto de treinamento/teste
  • Defina o peso inicial
  • Defina a função de perda: MSE
  • Otimize o modelo: gradiente descendente
  • Definir:
    • Taxa de Aprendizagem
    • Número de época
    • Tamanho do batch
    • Número da aula

Neste tutorial, você aprendeu como usar a API de alto nível para um classificador de regressão linear. Você precisa definir:

  1. Colunas de recursos. Se contínuo: tf.feature_column.numeric_column(). Você pode preencher uma lista com compreensão de lista python
  2. O estimador: tf.estimator.LinearClassifier(feature_columns, model_dir, n_classes = 2)
  3. Uma função para importar os dados, o tamanho do lote e a época: input_fn()

Depois disso, você está pronto para treinar, avaliar e fazer uma previsão com train(), avaliar() e prever()

Para melhorar o desempenho do modelo, você pode:

  • Usar regressão polinomial
  • Termo de interação: tf.feature_column.crossed_column
  • Adicionar parâmetro de regularização