Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
tensorflow
GitHub Repository: tensorflow/docs-l10n
Path: blob/master/site/pt-br/tutorials/keras/regression.ipynb
25118 views
Kernel: Python 3
#@title Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License.
#@title MIT License # # Copyright (c) 2017 François Chollet # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE.

Regressão básica: previsão da eficiência de combustível

Em um problema de regressão, o objetivo é prever a saída de um valor contínuo, como um preço ou uma probabilidade. Compare com um problema de classificação, em que o objetivo é selecionar uma classe em uma lista de classes (por exemplo, quando uma imagem contém uma maçã ou uma laranja, reconhecer qual fruta está presente na imagem).

Este tutorial usa o dataset clássico Auto MPG e demonstra como criar modelos para prever a eficiência de combustível dos automóveis do fim da década de 1970 e início da década de 1980. Para fazer isso, você fornecerá aos modelos uma descrição de diversos automóveis desse período. A descrição incluir vários atributos, como cilindros, cilindradas, cavalos e peso.

Este exemplo usa a API do Keras. Para saber mais, confira os tutoriais e guias do Keras.

# Use seaborn for pairplot. !pip install -q seaborn
import matplotlib.pyplot as plt import numpy as np import pandas as pd import seaborn as sns # Make NumPy printouts easier to read. np.set_printoptions(precision=3, suppress=True)
import tensorflow as tf from tensorflow import keras from tensorflow.keras import layers print(tf.__version__)

Dataset Auto MPG

O dataset está disponível no Repositório de Aprendizado de Máquina da UCI.

Obter os dados

Primeiro, baixe e importe o dataset usando o pandas:

url = 'http://archive.ics.uci.edu/ml/machine-learning-databases/auto-mpg/auto-mpg.data' column_names = ['MPG', 'Cylinders', 'Displacement', 'Horsepower', 'Weight', 'Acceleration', 'Model Year', 'Origin'] raw_dataset = pd.read_csv(url, names=column_names, na_values='?', comment='\t', sep=' ', skipinitialspace=True)
dataset = raw_dataset.copy() dataset.tail()

Limpar os dados

O dataset contém alguns valores desconhecidos:

dataset.isna().sum()

Elimine essas linhas para simplificar este tutorial inicial:

dataset = dataset.dropna()

A coluna "Origin" (origem) armazena uma categoria, não um número. Portanto, a próxima etapa é fazer a codificação one-hot dos valores na coluna com pd.get_dummies.

Observação: você pode configurar tf.keras.Model para fazer esse tipo de transformação, mas isso foge do escopo deste tutorial. Confira exemplos nos tutoriais Classificar dados estruturados usando camadas de pré-processamento do Keras ou Carregar dados em CSV.

dataset['Origin'] = dataset['Origin'].map({1: 'USA', 2: 'Europe', 3: 'Japan'})
dataset = pd.get_dummies(dataset, columns=['Origin'], prefix='', prefix_sep='') dataset.tail()

Dividir os dados em datasets de treinamento e teste

Agora, divida o dataset em um conjunto de treinamento e outro de teste. Você usará o conjunto de teste na avaliação final dos modelos.

train_dataset = dataset.sample(frac=0.8, random_state=0) test_dataset = dataset.drop(train_dataset.index)

Avaliar os dados

Confira a distribuição conjunta de alguns pares de colunas do conjunto de treinamento.

A linha superior indica que a eficiência de combustível (MPG, na sigla em inglês) é uma função de todos os outros parâmetros. As outras linhas indicam que são funções uma da outra.

sns.pairplot(train_dataset[['MPG', 'Cylinders', 'Displacement', 'Weight']], diag_kind='kde')

Confira também as estatísticas gerais. Observe como cada característica abrange um intervalo bem diferente:

train_dataset.describe().transpose()

Separar as características dos rótulos

Separa o valor alvo, o "rótulo", das características. Você treinará o modelo para prever esse rótulo.

train_features = train_dataset.copy() test_features = test_dataset.copy() train_labels = train_features.pop('MPG') test_labels = test_features.pop('MPG')

Normalização

Na tabela de estatísticas, é fácil ver como os intervalos de cada característica são diferentes:

train_dataset.describe().transpose()[['mean', 'std']]

É uma boa prática normalizar os recursos que usem escalas e intervalos diferentes.

Um motivos dessa importância é porque as características são multiplicadas pelos pesos do modelo. Portanto, a escala das saídas e a escala dos gradientes são afetadas pela escala das entradas.

Embora um modelo talvez possa convergir sem a normalização de características, ela deixa o treinamento muito mais estável.

Observação: não há vantagens em normalizar as características one-hot. Isso é feito aqui por questões de simplicidade. Confira mais detalhes de como usar as camadas de pré-processamento no guia Trabalhando com camadas de pré-processamento e no tutorial Classificar dados estruturados usando camadas de pré-processamento do Keras.

Camada de normalização

tf.keras.layers.Normalization é uma forma simples e elegante de acrescentar a normalização de características ao seu modelo.

O primeiro passo é criar a camada:

normalizer = tf.keras.layers.Normalization(axis=-1)

Em seguida, faça a adequação do estado da camada de pré-processamento aos dados chamando Normalization.adapt:

normalizer.adapt(np.array(train_features))

Calcule a média e a variância., depois armazene-as na camada:

print(normalizer.mean.numpy())

Quando a camada é chamada, retorna os dados de entrada, com cada característica normalizada de forma independente:

first = np.array(train_features[:1]) with np.printoptions(precision=2, suppress=True): print('First example:', first) print() print('Normalized:', normalizer(first).numpy())

Regressão linear

Antes de criar um modelo de rede neural profunda, comece com a regressão linear, usando uma ou várias variáveis.

Regressão linear com uma variável

Comece com uma regressão linear com uma única variável para prever 'MPG' (milhas por galão) a partir de 'Horsepower' (cavalos).

Geralmente, fazer o treinamento de um modelo tf.keras começa pela definição da arquitetura do modelo. Use um modelo tf.keras.Sequential que representa uma sequência de passos.

Há dois passos no modelo de regressão linear com uma única variável:

  • Normalize as características de entrada 'Horsepower' (cavalos) usando a camada de pré-processamento tf.keras.layers.Normalization.

  • Aplique uma transformação linear (y=mx+by = mx+b) para gerar 1 saída usando uma camada linear (tf.keras.layers.Dense).

O número de entradas pode ser definido pelo argumento input_shape ou automaticamente quando o modelo é executado pela primeira vez.

Primeiro, crie uma array NumPy composto pelas características 'Horsepower' (cavalos). Em seguida, instancie tf.keras.layers.Normalization e faça a adequação de seu estado aos dados de horsepower:

horsepower = np.array(train_features['Horsepower']) horsepower_normalizer = layers.Normalization(input_shape=[1,], axis=None) horsepower_normalizer.adapt(horsepower)

Crie o modelo Sequential do Keras:

horsepower_model = tf.keras.Sequential([ horsepower_normalizer, layers.Dense(units=1) ]) horsepower_model.summary()

Esse modelo preverá 'MPG' a partir de 'Horsepower'.

Execute o modelo não treinado para os primeiros 10 valores de 'Horsepower'. A saída não será boa, mas observe que tem o formato esperado – (10, 1):

horsepower_model.predict(horsepower[:10])

Após criar o modelo, configure o procedimento de treinamento usando o método Model.compile do Keras. Os argumentos mais importantes a serem compilados são loss (perda) e optimizer (otimizador), já que definem o que será otimizado (mean_absolute_error) e como (usando tf.keras.optimizers.Adam).

horsepower_model.compile( optimizer=tf.keras.optimizers.Adam(learning_rate=0.1), loss='mean_absolute_error')

Use Model.fit do Keras para executar o treinamento com 100 épocas:

%%time history = horsepower_model.fit( train_features['Horsepower'], train_labels, epochs=100, # Suppress logging. verbose=0, # Calculate validation results on 20% of the training data. validation_split = 0.2)

Visualize o progresso de treinamento do modelo usando as estatísticas armazenadas no objeto history (histórico):

hist = pd.DataFrame(history.history) hist['epoch'] = history.epoch hist.tail()
def plot_loss(history): plt.plot(history.history['loss'], label='loss') plt.plot(history.history['val_loss'], label='val_loss') plt.ylim([0, 10]) plt.xlabel('Epoch') plt.ylabel('Error [MPG]') plt.legend() plt.grid(True)
plot_loss(history)

Colete os resultados para o conjunto de teste para uso posterior:

test_results = {} test_results['horsepower_model'] = horsepower_model.evaluate( test_features['Horsepower'], test_labels, verbose=0)

Como é uma regressão com uma única variável, é fácil ver as previsões do modelo como uma função da entrada:

x = tf.linspace(0.0, 250, 251) y = horsepower_model.predict(x)
def plot_horsepower(x, y): plt.scatter(train_features['Horsepower'], train_labels, label='Data') plt.plot(x, y, color='k', label='Predictions') plt.xlabel('Horsepower') plt.ylabel('MPG') plt.legend()
plot_horsepower(x, y)

Regressão linear com várias entradas

Você pode usar uma configuração quase idêntica para fazer previsões com base em diversas entradas. Esse modelo ainda faz a mesma transformação linear y=mx+by = mx+b, mas mm é uma matriz, e xx é um vetor.

Crie novamente um modelo Sequential do Keras com dois passos, sendo que a primeira camada é o normalizer (normalizador), (tf.keras.layers.Normalization(axis=-1)) que você definiu anteriormente e adaptou para todo o dataset:

linear_model = tf.keras.Sequential([ normalizer, layers.Dense(units=1) ])

Quando você faz uma chamada a Model.predict para um lote de entradas, são produzidas saídasunits=1 para cada exemplo:

linear_model.predict(train_features[:10])

Quando você faz uma chamada ao modelo, suas matrizes de peso são construídas. Verifique se os pesos de kernel (o mm em y=mx+by=mx+b) têm um formato igual a (9, 1):

linear_model.layers[1].kernel

Configure o modelo com Model.compile do Keras e faça o treinamento com Model.fit com 100 épocas:

linear_model.compile( optimizer=tf.keras.optimizers.Adam(learning_rate=0.1), loss='mean_absolute_error')
%%time history = linear_model.fit( train_features, train_labels, epochs=100, # Suppress logging. verbose=0, # Calculate validation results on 20% of the training data. validation_split = 0.2)

Ao usar todas as entradas nesse modelo de regressão, conseguimos um erro de treinamento e validação bem menor do que horsepower_model, que tinha uma entrada:

plot_loss(history)

Colete os resultados para o conjunto de teste para uso posterior:

test_results['linear_model'] = linear_model.evaluate( test_features, test_labels, verbose=0)

Regressão com uma rede neural profunda (DNN)

Na seção anterior, você implementou dois modelos lineares para entrada única ou diversas entradas.

Agora, você implementará modelos de DNN com uma entrada ou diversas entradas.

O código é basicamente o mesmo, exceto que o modelo é expandido, com a inclusão de algumas camadas não lineares "ocultas". O termo "ocultas" significa apenas que elas não estão ligadas diretamente às entradas ou às saídas.

Esses modelos conterão algumas camadas a mais do que o modelo linear:

  • A camada de normalização, da mesma forma que anteriormente (com horsepower_normalizer para um modelo com uma entrada e normalizer para um modelo com várias entradas).

  • Duas camadas Dense não lineares e ocultas, com a função de ativação ReLU (relu) não linear.

  • Uma camada Dense com uma única saída.

Os dois modelos usarão o mesmo procedimento de treinamento, então o método compile é incluído na função build_and_compile_model abaixo.

def build_and_compile_model(norm): model = keras.Sequential([ norm, layers.Dense(64, activation='relu'), layers.Dense(64, activation='relu'), layers.Dense(1) ]) model.compile(loss='mean_absolute_error', optimizer=tf.keras.optimizers.Adam(0.001)) return model

Regressão usando uma DNN e uma única entrada

Crie um modelo de DNN com apenas 'Horsepower' (cavalos) como entrada e horsepower_normalizer (definido anteriormente) como a camada de normalização:

dnn_horsepower_model = build_and_compile_model(horsepower_normalizer)

Esse modelo tem bem mais parâmetros que podem ser treinados do que os modelos lineares:

dnn_horsepower_model.summary()

Treine o modelo com Model.fit do Keras:

%%time history = dnn_horsepower_model.fit( train_features['Horsepower'], train_labels, validation_split=0.2, verbose=0, epochs=100)

Esse modelo tem um desempenho um pouco melhor do que o modelo horsepower_model linear com uma única entrada:

plot_loss(history)

Se você plotar as previsões como função de 'Horsepower' (cavalos), notará como esse modelo tem vantagens sobre a não linearidade fornecida pelas camadas ocultas:

x = tf.linspace(0.0, 250, 251) y = dnn_horsepower_model.predict(x)
plot_horsepower(x, y)

Colete os resultados para o conjunto de teste para uso posterior:

test_results['dnn_horsepower_model'] = dnn_horsepower_model.evaluate( test_features['Horsepower'], test_labels, verbose=0)

Regressão usando uma DNN e várias entradas

Repita o processo anterior usando todas as entradas. O desempenho do modelo aumenta um pouco para o dataset de validação.

dnn_model = build_and_compile_model(normalizer) dnn_model.summary()
%%time history = dnn_model.fit( train_features, train_labels, validation_split=0.2, verbose=0, epochs=100)
plot_loss(history)

Colete os resultados para o conjunto de teste:

test_results['dnn_model'] = dnn_model.evaluate(test_features, test_labels, verbose=0)

Desempenho

Como todos os modelos foram treinados, você pode conferir o desempenho de seus conjuntos de teste:

pd.DataFrame(test_results, index=['Mean absolute error [MPG]']).T

Esses resultados batem com o erro de validação observado durante o treinamento.

Fazer previsões

Agora, você pode fazer previsões com dnn_model para o conjunto de testes usando Model.predict do Keras e conferindo a perda:

test_predictions = dnn_model.predict(test_features).flatten() a = plt.axes(aspect='equal') plt.scatter(test_labels, test_predictions) plt.xlabel('True Values [MPG]') plt.ylabel('Predictions [MPG]') lims = [0, 50] plt.xlim(lims) plt.ylim(lims) _ = plt.plot(lims, lims)

Parece que o modelo faz previsões razoavelmente boas.

Agora, confira a distribuição do erro:

error = test_predictions - test_labels plt.hist(error, bins=25) plt.xlabel('Prediction Error [MPG]') _ = plt.ylabel('Count')

Se você estiver contente com o modelo, salve-o para uso posterior com Model.save:

dnn_model.save('dnn_model.keras')

Se você recarregar o modelo, ele gerará uma saída idêntica:

reloaded = tf.keras.models.load_model('dnn_model.keras') test_results['reloaded'] = reloaded.evaluate( test_features, test_labels, verbose=0)
pd.DataFrame(test_results, index=['Mean absolute error [MPG]']).T

Conclusão

Este notebook apresentou algumas técnicas para lidar com um problema de regressão. Confira mais algumas dicas que podem ajudar:

  • Erro Quadrático Médio (EQM) (tf.keras.losses.MeanSquaredError) e Erro Absoluto Médio (EMA) (tf.keras.losses.MeanAbsoluteError) são funções de perda comuns usadas para problemas de regressão. O EMA é menos sensível aos pontos fora da curva. Funções de perda diferentes são usadas para problemas de classificação.

  • De maneira similar, as métricas de avaliação usadas para regressão diferem das usadas para classificação.

  • Quando características de dados de entrada numérica têm valores com intervalos diferentes, cada característica deve ter sua escala alterada de forma independente para o mesmo intervalo.

  • O overfitting é um problema comum para modelos de DNN, embora não tenha sido um problema neste tutorial. Consulte mais informações sobre esse tema no tutorial Overfitting e underfitting.