Загрузка pandas.DataFrame

Смотрите на TensorFlow.org Запустите в Google Colab Изучайте код на GitHub Скачайте ноутбук

Из этого руководства вы узнаете, как загрузить датафрейм Pandas в tf.data.Dataset.

Это руководство использует небольшой датасет предоставленный Фондом сердечных заболеваний кливлендской клиники. В ней несколько сотен строк в формате CSV. Каждая строка описывает пациента, а каждый столбец описывает свойство. Мы используем эту информацию чтобы предсказать имеет ли пациент сердечное заболевание, что в этом датасете является задачей двоичной классификации.

Прочитайте данные используя pandas

from __future__ import absolute_import, division, print_function, unicode_literals

import pandas as pd
import tensorflow as tf

Скачайте файл csv содержащий датасет с пациентами.

csv_file = tf.keras.utils.get_file('heart.csv', 'https://storage.googleapis.com/applied-dl/heart.csv')
Downloading data from https://storage.googleapis.com/applied-dl/heart.csv
16384/13273 [=====================================] - 0s 0us/step

Прочитайте csv файл используя pandas.

df = pd.read_csv(csv_file)
df.head()
df.dtypes
age           int64
sex           int64
cp            int64
trestbps      int64
chol          int64
fbs           int64
restecg       int64
thalach       int64
exang         int64
oldpeak     float64
slope         int64
ca            int64
thal         object
target        int64
dtype: object

Конвертируйте столбец thal являющийся object в датафрейме в дискретные числовые значения.

df['thal'] = pd.Categorical(df['thal'])
df['thal'] = df.thal.cat.codes
df.head()

Загрузите данные используя tf.data.Dataset

Используйте tf.data.Dataset.from_tensor_slices чтобы прочитать значения из датафрейма pandas.

Одним из преимуществ использования tf.data.Dataset является то, что он позволяет вам писать простые высокоэффективные конвейеры данных. Прочитайте руководство по загрузке данных для подробностей.

target = df.pop('target')
dataset = tf.data.Dataset.from_tensor_slices((df.values, target.values))
for feat, targ in dataset.take(5):
  print ('Признаки: {}, Цель: {}'.format(feat, targ))
Признаки: [ 63.    1.    1.  145.  233.    1.    2.  150.    0.    2.3   3.    0.
   2. ], Цель: 0
Признаки: [ 67.    1.    4.  160.  286.    0.    2.  108.    1.    1.5   2.    3.
   3. ], Цель: 1
Признаки: [ 67.    1.    4.  120.  229.    0.    2.  129.    1.    2.6   2.    2.
   4. ], Цель: 0
Признаки: [ 37.    1.    3.  130.  250.    0.    0.  187.    0.    3.5   3.    0.
   3. ], Цель: 0
Признаки: [ 41.    0.    2.  130.  204.    0.    2.  172.    0.    1.4   1.    0.
   3. ], Цель: 0

Поскольку pd.Series реализует протокол __array__ он может быть использован практически везде где вы бы использовали np.array или tf.Tensor.

tf.constant(df['thal'])
<tf.Tensor: id=21, shape=(303,), dtype=int32, numpy=
array([2, 3, 4, 3, 3, 3, 3, 3, 4, 4, 2, 3, 2, 4, 4, 3, 4, 3, 3, 3, 3, 3,
       3, 4, 4, 3, 3, 3, 3, 4, 3, 4, 3, 4, 3, 3, 4, 2, 4, 3, 4, 3, 4, 4,
       2, 3, 3, 4, 3, 3, 4, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 4, 4, 3, 3, 4,
       4, 2, 3, 3, 4, 3, 4, 3, 3, 4, 4, 3, 3, 4, 4, 3, 3, 3, 3, 4, 4, 4,
       3, 3, 4, 3, 4, 4, 3, 4, 3, 3, 3, 4, 3, 4, 4, 3, 3, 4, 4, 4, 4, 4,
       3, 3, 3, 3, 4, 3, 4, 3, 4, 4, 3, 3, 2, 4, 4, 2, 3, 3, 4, 4, 3, 4,
       3, 3, 4, 2, 4, 4, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4,
       4, 3, 3, 3, 4, 3, 4, 3, 4, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3,
       3, 3, 3, 3, 3, 3, 3, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 2,
       4, 4, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 2, 2, 4, 3, 4, 2, 4, 3,
       3, 4, 3, 3, 3, 3, 4, 3, 4, 3, 4, 2, 2, 4, 3, 4, 3, 2, 4, 3, 3, 2,
       4, 4, 4, 4, 3, 0, 3, 3, 3, 3, 1, 4, 3, 3, 3, 4, 3, 4, 3, 3, 3, 4,
       3, 3, 4, 4, 4, 4, 3, 3, 4, 3, 4, 3, 4, 4, 3, 4, 4, 3, 4, 4, 3, 3,
       3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 3, 2, 4, 4, 4, 4], dtype=int32)>

Перемешайте датасет и разбейте его на пакеты.

train_dataset = dataset.shuffle(len(df)).batch(1)

Создайте и обучите модель

def get_compiled_model():
  model = tf.keras.Sequential([
    tf.keras.layers.Dense(10, activation='relu'),
    tf.keras.layers.Dense(10, activation='relu'),
    tf.keras.layers.Dense(1, activation='sigmoid')
  ])

  model.compile(optimizer='adam',
                loss='binary_crossentropy',
                metrics=['accuracy'])
  return model
model = get_compiled_model()
model.fit(train_dataset, epochs=15)
WARNING:tensorflow:Layer sequential is casting an input tensor from dtype float64 to the layer's dtype of float32, which is new behavior in TensorFlow 2.  The layer has dtype float32 because it's dtype defaults to floatx.

If you intended to run this layer in float32, you can safely ignore this warning. If in doubt, this warning is likely only an issue if you are porting a TensorFlow 1.X model to TensorFlow 2.

To change all layers to have dtype float64 by default, call `tf.keras.backend.set_floatx('float64')`. To change just this layer, pass dtype='float64' to the layer constructor. If you are the author of this layer, you can disable autocasting by passing autocast=False to the base Layer constructor.

Epoch 1/15
303/303 [==============================] - 2s 6ms/step - loss: 1.8131 - accuracy: 0.6436
Epoch 2/15
303/303 [==============================] - 1s 2ms/step - loss: 1.0602 - accuracy: 0.7030
Epoch 3/15
303/303 [==============================] - 1s 2ms/step - loss: 0.7938 - accuracy: 0.6865
Epoch 4/15
303/303 [==============================] - 1s 3ms/step - loss: 0.6712 - accuracy: 0.7162
Epoch 5/15
303/303 [==============================] - 1s 2ms/step - loss: 0.6837 - accuracy: 0.6898
Epoch 6/15
303/303 [==============================] - 1s 2ms/step - loss: 0.6162 - accuracy: 0.7228
Epoch 7/15
303/303 [==============================] - 1s 2ms/step - loss: 0.6185 - accuracy: 0.7360
Epoch 8/15
303/303 [==============================] - 1s 2ms/step - loss: 0.5836 - accuracy: 0.7426
Epoch 9/15
303/303 [==============================] - 1s 2ms/step - loss: 0.5547 - accuracy: 0.7459
Epoch 10/15
303/303 [==============================] - 1s 2ms/step - loss: 0.5812 - accuracy: 0.7459
Epoch 11/15
303/303 [==============================] - 1s 2ms/step - loss: 0.5591 - accuracy: 0.7426
Epoch 12/15
303/303 [==============================] - 1s 2ms/step - loss: 0.5312 - accuracy: 0.7459
Epoch 13/15
303/303 [==============================] - 1s 2ms/step - loss: 0.5214 - accuracy: 0.7624
Epoch 14/15
303/303 [==============================] - 1s 2ms/step - loss: 0.5043 - accuracy: 0.7525
Epoch 15/15
303/303 [==============================] - 1s 2ms/step - loss: 0.5256 - accuracy: 0.7558

<tensorflow.python.keras.callbacks.History at 0x7f4588206f28>

Альтернатива столбцам признаков

Передать словарь в качестве входных данных для модели так же просто, как и создать словарь соответствия слоев tf.keras.layers.Input, применяя любой препроцессинг и складывая их, используя функциональный api. Вы можете использовать это в качестве альтернативы столбцов признаков.

inputs = {key: tf.keras.layers.Input(shape=(), name=key) for key in df.keys()}
x = tf.stack(list(inputs.values()), axis=-1)

x = tf.keras.layers.Dense(10, activation='relu')(x)
output = tf.keras.layers.Dense(1, activation='sigmoid')(x)

model_func = tf.keras.Model(inputs=inputs, outputs=output)

model_func.compile(optimizer='adam',
                   loss='binary_crossentropy',
                   metrics=['accuracy'])

Простейший способ сохранения структуры столбцов в pd.DataFrame при использовании с tf.data это конвертация pd.DataFrame в dict и сделав срезы этого словаря.

dict_slices = tf.data.Dataset.from_tensor_slices((df.to_dict('list'), target.values)).batch(16)
for dict_slice in dict_slices.take(1):
  print (dict_slice)
({'age': <tf.Tensor: id=14768, shape=(16,), dtype=int32, numpy=
array([63, 67, 67, 37, 41, 56, 62, 57, 63, 53, 57, 56, 56, 44, 52, 57],
      dtype=int32)>, 'sex': <tf.Tensor: id=14776, shape=(16,), dtype=int32, numpy=array([1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1], dtype=int32)>, 'cp': <tf.Tensor: id=14771, shape=(16,), dtype=int32, numpy=array([1, 4, 4, 3, 2, 2, 4, 4, 4, 4, 4, 2, 3, 2, 3, 3], dtype=int32)>, 'trestbps': <tf.Tensor: id=14780, shape=(16,), dtype=int32, numpy=
array([145, 160, 120, 130, 130, 120, 140, 120, 130, 140, 140, 140, 130,
       120, 172, 150], dtype=int32)>, 'chol': <tf.Tensor: id=14770, shape=(16,), dtype=int32, numpy=
array([233, 286, 229, 250, 204, 236, 268, 354, 254, 203, 192, 294, 256,
       263, 199, 168], dtype=int32)>, 'fbs': <tf.Tensor: id=14773, shape=(16,), dtype=int32, numpy=array([1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0], dtype=int32)>, 'restecg': <tf.Tensor: id=14775, shape=(16,), dtype=int32, numpy=array([2, 2, 2, 0, 2, 0, 2, 0, 2, 2, 0, 2, 2, 0, 0, 0], dtype=int32)>, 'thalach': <tf.Tensor: id=14779, shape=(16,), dtype=int32, numpy=
array([150, 108, 129, 187, 172, 178, 160, 163, 147, 155, 148, 153, 142,
       173, 162, 174], dtype=int32)>, 'exang': <tf.Tensor: id=14772, shape=(16,), dtype=int32, numpy=array([0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0], dtype=int32)>, 'oldpeak': <tf.Tensor: id=14774, shape=(16,), dtype=float32, numpy=
array([2.3, 1.5, 2.6, 3.5, 1.4, 0.8, 3.6, 0.6, 1.4, 3.1, 0.4, 1.3, 0.6,
       0. , 0.5, 1.6], dtype=float32)>, 'slope': <tf.Tensor: id=14777, shape=(16,), dtype=int32, numpy=array([3, 2, 2, 3, 1, 1, 3, 1, 2, 3, 2, 2, 2, 1, 1, 1], dtype=int32)>, 'ca': <tf.Tensor: id=14769, shape=(16,), dtype=int32, numpy=array([0, 3, 2, 0, 0, 0, 2, 0, 1, 0, 0, 0, 1, 0, 0, 0], dtype=int32)>, 'thal': <tf.Tensor: id=14778, shape=(16,), dtype=int32, numpy=array([2, 3, 4, 3, 3, 3, 3, 3, 4, 4, 2, 3, 2, 4, 4, 3], dtype=int32)>}, <tf.Tensor: id=14781, shape=(16,), dtype=int64, numpy=array([0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0])>)
model_func.fit(dict_slices, epochs=15)
Epoch 1/15
19/19 [==============================] - 0s 25ms/step - loss: 227.4808 - accuracy: 0.2739
Epoch 2/15
19/19 [==============================] - 0s 4ms/step - loss: 203.2047 - accuracy: 0.2739
Epoch 3/15
19/19 [==============================] - 0s 4ms/step - loss: 177.1424 - accuracy: 0.2739
Epoch 4/15
19/19 [==============================] - 0s 4ms/step - loss: 153.6068 - accuracy: 0.2739
Epoch 5/15
19/19 [==============================] - 0s 4ms/step - loss: 132.2382 - accuracy: 0.2739
Epoch 6/15
19/19 [==============================] - 0s 4ms/step - loss: 112.5972 - accuracy: 0.2739
Epoch 7/15
19/19 [==============================] - 0s 4ms/step - loss: 94.6724 - accuracy: 0.2739
Epoch 8/15
19/19 [==============================] - 0s 4ms/step - loss: 78.7136 - accuracy: 0.2739
Epoch 9/15
19/19 [==============================] - 0s 4ms/step - loss: 64.3623 - accuracy: 0.2739
Epoch 10/15
19/19 [==============================] - 0s 4ms/step - loss: 50.9214 - accuracy: 0.2739
Epoch 11/15
19/19 [==============================] - 0s 4ms/step - loss: 38.1603 - accuracy: 0.2739
Epoch 12/15
19/19 [==============================] - 0s 4ms/step - loss: 25.9764 - accuracy: 0.2739
Epoch 13/15
19/19 [==============================] - 0s 4ms/step - loss: 13.7229 - accuracy: 0.2739
Epoch 14/15
19/19 [==============================] - 0s 4ms/step - loss: 3.4483 - accuracy: 0.3498
Epoch 15/15
19/19 [==============================] - 0s 4ms/step - loss: 2.2888 - accuracy: 0.6667

<tensorflow.python.keras.callbacks.History at 0x7f4593891c50>