#@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.

"""
Explanation: Copyright 2019 The TensorFlow Authors.
End of explanation
"""


try:
  # %tensorflow_version only exists in Colab.
  %tensorflow_version 2.x
except Exception:
  pass


from __future__ import absolute_import, division, print_function, unicode_literals
import functools

import numpy as np
import tensorflow as tf

TRAIN_DATA_URL = "https://storage.googleapis.com/tf-datasets/titanic/train.csv"
TEST_DATA_URL = "https://storage.googleapis.com/tf-datasets/titanic/eval.csv"

train_file_path = tf.keras.utils.get_file("train.csv", TRAIN_DATA_URL)
test_file_path = tf.keras.utils.get_file("eval.csv", TEST_DATA_URL)

# Facilitar a leitura de valores numpy.
np.set_printoptions(precision=3, suppress=True)

"""
Explanation: Carregar dados CSV
<table class="tfo-notebook-buttons" align="left">
  <td>
    <a target="_blank" href="https://www.tensorflow.org/tutorials/load_data/csv"><img src="https://www.tensorflow.org/images/tf_logo_32px.png" />Ver em TensorFlow.org</a>
  </td>
  <td>
    <a target="_blank" href="https://colab.research.google.com/github/tensorflow/docs-l10n/blob/master/site/pt-br/tutorials/load_data/csv.ipynb"><img src="https://www.tensorflow.org/images/colab_logo_32px.png" />Executar em Google Colab</a>
  </td>
  <td>
    <a target="_blank" href="https://github.com/tensorflow/docs-l10n/blob/master/site/pt-br/tutorials/load_data/csv.ipynb"><img src="https://www.tensorflow.org/images/GitHub-Mark-32px.png" />Ver código fonte no GitHub</a>
  </td>
  <td>
    <a href="https://storage.googleapis.com/tensorflow_docs/docs-l10n/site/pt-br/tutorials/load_data/csv.ipynb"><img src="https://www.tensorflow.org/images/download_logo_32px.png" />Baixar notebook</a>
  </td>
</table>

Este tutorial fornece um exemplo de como carregar dados CSV de um arquivo em um tf.data.Dataset.
Os dados usados neste tutorial foram retirados da lista de passageiros do Titanic. O modelo preverá a probabilidade de sobrevivência de um passageiro com base em características como idade, sexo, classe de passagem e se a pessoa estava viajando sozinha.
Setup
End of explanation
"""


!head {train_file_path}

"""
Explanation: Carregar dados
Para começar, vejamos a parte superior do arquivo CSV para ver como ele está formatado.
End of explanation
"""


LABEL_COLUMN = 'survived'
LABELS = [0, 1]

"""
Explanation: Você pode [carregar isso usando pandas] (pandas.ipynb) e passar as matrizes NumPy para o TensorFlow. Se você precisar escalar até um grande conjunto de arquivos ou precisar de um carregador que se integre ao [TensorFlow e tf.data] (../../guide/data.ipynb), use o tf.data.experimental. função make_csv_dataset:
A única coluna que você precisa identificar explicitamente é aquela com o valor que o modelo pretende prever.
End of explanation
"""


def get_dataset(file_path, **kwargs):
  dataset = tf.data.experimental.make_csv_dataset(
      file_path,
      batch_size=5, # Artificialmente pequeno para facilitar a exibição de exemplos
      label_name=LABEL_COLUMN,
      na_value="?",
      num_epochs=1,
      ignore_errors=True, 
      **kwargs)
  return dataset

raw_train_data = get_dataset(train_file_path)
raw_test_data = get_dataset(test_file_path)

def show_batch(dataset):
  for batch, label in dataset.take(1):
    for key, value in batch.items():
      print("{:20s}: {}".format(key,value.numpy()))

"""
Explanation: Now read the CSV data from the file and create a dataset. 
(For the full documentation, see tf.data.experimental.make_csv_dataset)
End of explanation
"""


show_batch(raw_train_data)

"""
Explanation: Cada item do conjunto de dados é um lote, representado como uma tupla de ( muitos exemplos , * muitos rótulos *). Os dados dos exemplos são organizados em tensores baseados em colunas (em vez de tensores baseados em linhas), cada um com tantos elementos quanto o tamanho do lote (5 neste caso).
Pode ajudar a ver isso por si mesmo.
End of explanation
"""


CSV_COLUMNS = ['survived', 'sex', 'age', 'n_siblings_spouses', 'parch', 'fare', 'class', 'deck', 'embark_town', 'alone']

temp_dataset = get_dataset(train_file_path, column_names=CSV_COLUMNS)

show_batch(temp_dataset)

"""
Explanation: Como você pode ver, as colunas no CSV são nomeadas. O construtor do conjunto de dados selecionará esses nomes automaticamente. Se o arquivo com o qual você está trabalhando não contém os nomes das colunas na primeira linha, passe-os em uma lista de strings para o argumento column_names na função make_csv_dataset.
End of explanation
"""


SELECT_COLUMNS = ['survived', 'age', 'n_siblings_spouses', 'class', 'deck', 'alone']

temp_dataset = get_dataset(train_file_path, select_columns=SELECT_COLUMNS)

show_batch(temp_dataset)

"""
Explanation: Este exemplo vai usar todas as colunas disponíveis. Se você precisar omitir algumas colunas do conjunto de dados, crie uma lista apenas das colunas que planeja usar e passe-a para o argumento (opcional) select_columns do construtor.
End of explanation
"""


SELECT_COLUMNS = ['survived', 'age', 'n_siblings_spouses', 'parch', 'fare']
DEFAULTS = [0, 0.0, 0.0, 0.0, 0.0]
temp_dataset = get_dataset(train_file_path, 
                           select_columns=SELECT_COLUMNS,
                           column_defaults = DEFAULTS)

show_batch(temp_dataset)

example_batch, labels_batch = next(iter(temp_dataset)) 

"""
Explanation: Pré-processamento dos Dados
Um arquivo CSV pode conter uma variedade de tipos de dados. Normalmente, você deseja converter desses tipos mistos em um vetor de comprimento fixo antes de alimentar os dados em seu modelo.
O TensorFlow possui um sistema interno para descrever conversões de entrada comuns: tf.feature_column, consulte [este tutorial] (../keras/feature_columns) para detalhes.
Você pode pré-processar seus dados usando qualquer ferramenta que desejar (como [nltk] (https://www.nltk.org/) ou [sklearn] (https://scikit-learn.org/stable/)) e apenas passar a saída processada para o TensorFlow.
A principal vantagem de fazer o pré-processamento dentro do seu modelo é que, quando você exporta o modelo, ele inclui o pré-processamento. Dessa forma, você pode passar os dados brutos diretamente para o seu modelo.
Dados contínuos
Se seus dados já estiverem em um formato numérico apropriado, você poderá compactá-los em um vetor antes de transmiti-los ao modelo:
End of explanation
"""


def pack(features, label):
  return tf.stack(list(features.values()), axis=-1), label

"""
Explanation: Aqui está uma função simples que agrupará todas as colunas:
End of explanation
"""


packed_dataset = temp_dataset.map(pack)

for features, labels in packed_dataset.take(1):
  print(features.numpy())
  print()
  print(labels.numpy())

"""
Explanation: Aplique isso a cada elemento do conjunto de dados:
End of explanation
"""


show_batch(raw_train_data)

example_batch, labels_batch = next(iter(temp_dataset)) 

"""
Explanation: Se você tiver tipos de dados mistos, poderá separar esses campos numéricos simples. A API tf.feature_column pode lidar com eles, mas isso gera alguma sobrecarga e deve ser evitado, a menos que seja realmente necessário. Volte para o conjunto de dados misto:
End of explanation
"""


class PackNumericFeatures(object):
  def __init__(self, names):
    self.names = names

  def __call__(self, features, labels):
    numeric_features = [features.pop(name) for name in self.names]
    numeric_features = [tf.cast(feat, tf.float32) for feat in numeric_features]
    numeric_features = tf.stack(numeric_features, axis=-1)
    features['numeric'] = numeric_features

    return features, labels

NUMERIC_FEATURES = ['age','n_siblings_spouses','parch', 'fare']

packed_train_data = raw_train_data.map(
    PackNumericFeatures(NUMERIC_FEATURES))

packed_test_data = raw_test_data.map(
    PackNumericFeatures(NUMERIC_FEATURES))

show_batch(packed_train_data)

example_batch, labels_batch = next(iter(packed_train_data)) 

"""
Explanation: Portanto, defina um pré-processador mais geral que selecione uma lista de recursos numéricos e os agrupe em uma única coluna:
End of explanation
"""


import pandas as pd
desc = pd.read_csv(train_file_path)[NUMERIC_FEATURES].describe()
desc

MEAN = np.array(desc.T['mean'])
STD = np.array(desc.T['std'])

def normalize_numeric_data(data, mean, std):
  # Center the data
  return (data-mean)/std


"""
Explanation: Normalização dos dados
Dados contínuos sempre devem ser normalizados.
End of explanation
"""


# Veja o que você acabou de criar.
normalizer = functools.partial(normalize_numeric_data, mean=MEAN, std=STD)

numeric_column = tf.feature_column.numeric_column('numeric', normalizer_fn=normalizer, shape=[len(NUMERIC_FEATURES)])
numeric_columns = [numeric_column]
numeric_column

"""
Explanation: Agora crie uma coluna numérica. A API tf.feature_columns.numeric_column aceita um argumento normalizer_fn, que será executado em cada lote.
Ligue o MEAN e oSTD ao normalizador fn usando [functools.partial] (https://docs.python.org/3/library/functools.html#functools.partial)
End of explanation
"""


example_batch['numeric']

numeric_layer = tf.keras.layers.DenseFeatures(numeric_columns)
numeric_layer(example_batch).numpy()

"""
Explanation: Ao treinar o modelo, inclua esta coluna de característica para selecionar e centralizar este bloco de dados numéricos:
End of explanation
"""


CATEGORIES = {
    'sex': ['male', 'female'],
    'class' : ['First', 'Second', 'Third'],
    'deck' : ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'],
    'embark_town' : ['Cherbourg', 'Southhampton', 'Queenstown'],
    'alone' : ['y', 'n']
}


categorical_columns = []
for feature, vocab in CATEGORIES.items():
  cat_col = tf.feature_column.categorical_column_with_vocabulary_list(
        key=feature, vocabulary_list=vocab)
  categorical_columns.append(tf.feature_column.indicator_column(cat_col))

# Veja o que você acabou de criar.
categorical_columns

categorical_layer = tf.keras.layers.DenseFeatures(categorical_columns)
print(categorical_layer(example_batch).numpy()[0])

"""
Explanation: A normalização baseada em média usada aqui requer conhecer os meios de cada coluna antes do tempo.
Dados categóricos
Algumas das colunas nos dados CSV são colunas categóricas. Ou seja, o conteúdo deve ser um dentre um conjunto limitado de opções.
Use a API tf.feature_column para criar uma coleção com uma tf.feature_column.indicator_column para cada coluna categórica.
End of explanation
"""


preprocessing_layer = tf.keras.layers.DenseFeatures(categorical_columns+numeric_columns)

print(preprocessing_layer(example_batch).numpy()[0])

"""
Explanation: Isso fará parte de uma entrada de processamento de dados posteriormente, quando você construir o modelo.
Camada combinada de pré-processamento
Adicione as duas coleções de colunas de recursos e passe-as para um tf.keras.layers.DenseFeatures para criar uma camada de entrada que extrairá e pré-processará os dois tipos de entrada:
End of explanation
"""


model = tf.keras.Sequential([
  preprocessing_layer,
  tf.keras.layers.Dense(128, activation='relu'),
  tf.keras.layers.Dense(128, activation='relu'),
  tf.keras.layers.Dense(1),
])

model.compile(
    loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
    optimizer='adam',
    metrics=['accuracy'])

"""
Explanation: Construir o modelo
Crie um tf.keras.Sequential, começando com o preprocessing_layer.
End of explanation
"""


train_data = packed_train_data.shuffle(500)
test_data = packed_test_data

model.fit(train_data, epochs=20)

"""
Explanation: Treinar, avaliar, e prever
Agora o modelo pode ser instanciado e treinado.
End of explanation
"""


test_loss, test_accuracy = model.evaluate(test_data)

print('\n\nTest Loss {}, Test Accuracy {}'.format(test_loss, test_accuracy))

"""
Explanation: Depois que o modelo é treinado, você pode verificar sua acurácia no conjunto test_data.
End of explanation
"""


predictions = model.predict(test_data)

# Mostrar alguns resultados
for prediction, survived in zip(predictions[:10], list(test_data)[0][1][:10]):
  print("Predicted survival: {:.2%}".format(prediction[0]),
        " | Actual outcome: ",
        ("SURVIVED" if bool(survived) else "DIED"))


"""
Explanation: Use tf.keras.Model.predict para inferir rótulos em um lote ou em um conjunto de dados de lotes.
End of explanation
"""


