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.
- Se o rótulo tiver apenas duas classes, o algoritmo de aprendizagem é um Classificador Binário.
- 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:
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: 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.
É 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.
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 após 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.
O 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 quadrados:
- 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.
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.
à Taxa de juros
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.
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
- relacionamento
- 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
A seguir, você importa os dados do arquivo 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 Python código 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
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.
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]
Observação 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 essa complexidade e torná-la 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.
Observação que se você alterar o hiperparâmetro, será necessário excluir a pasta em andamento/train4 caso contrário o modelo iniciará 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:
- Colunas de recursos. Se contínuo: tf.feature_column.numeric_column(). Você pode preencher uma lista com compreensão de lista python
- O estimador: tf.estimator.LinearClassifier(feature_columns, model_dir, n_classes = 2)
- 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