Halaman ini diterjemahkan oleh Cloud Translation API.
Switch to English

Klasifikasikan data terstruktur dengan kolom fitur

Lihat di TensorFlow.org Jalankan di Google Colab Lihat sumber di GitHub Unduh buku catatan

Tutorial ini menunjukkan cara mengklasifikasikan data terstruktur (misalnya, data tabel dalam CSV). Kami akan menggunakan Keras untuk menentukan model, dan kolom fitur sebagai jembatan untuk memetakan dari kolom di CSV ke fitur yang digunakan untuk melatih model. Tutorial ini berisi kode lengkap untuk:

  • Muat file CSV menggunakan Pandas .
  • Buat pipeline input untuk mengumpulkan dan mengocok baris menggunakan tf.data .
  • Petakan dari kolom di CSV ke fitur yang digunakan untuk melatih model menggunakan kolom fitur.
  • Buat, latih, dan evaluasi model menggunakan Keras.

Set Data

Kami akan menggunakan versi sederhana dari dataset PetFinder. Ada beberapa ribu baris di CSV. Setiap baris menggambarkan hewan peliharaan, dan setiap kolom menggambarkan atribut. Kami akan menggunakan informasi ini untuk memprediksi kecepatan adopsi hewan peliharaan.

Berikut adalah deskripsi dari dataset tersebut. Perhatikan bahwa ada kolom numerik dan kategorikal. Ada kolom teks gratis yang tidak akan kami gunakan dalam tutorial ini.

Kolom Deskripsi Jenis Fitur Tipe data
Tipe Jenis hewan (Anjing, Kucing) Kategorikal tali
Usia Usia hewan peliharaan Numerik bilangan bulat
Breed1 Jenis utama hewan peliharaan Kategorikal tali
Warna1 Warna 1 hewan peliharaan Kategorikal tali
Warna2 Warna 2 hewan peliharaan Kategorikal tali
MaturitySize Ukuran saat jatuh tempo Kategorikal tali
FurLength Panjang bulu Kategorikal tali
Vaksinasi Hewan peliharaan telah divaksinasi Kategorikal tali
Disterilkan Hewan peliharaan telah disterilkan Kategoris tali
Kesehatan Kondisi kesehatan Kategorikal tali
Biaya Biaya Adopsi Numerik bilangan bulat
Deskripsi Penulisan profil untuk hewan peliharaan ini Teks tali
PhotoAmt Total foto yang diunggah untuk hewan peliharaan ini Numerik bilangan bulat
AdoptionSpeed Kecepatan adopsi Klasifikasi bilangan bulat

Impor TensorFlow dan pustaka lainnya

pip install -q sklearn
WARNING: You are using pip version 20.2.2; however, version 20.2.3 is available.
You should consider upgrading via the '/tmpfs/src/tf_docs_env/bin/python -m pip install --upgrade pip' command.

import numpy as np
import pandas as pd

import tensorflow as tf

from tensorflow import feature_column
from tensorflow.keras import layers
from sklearn.model_selection import train_test_split

Gunakan Pandas untuk membuat kerangka data

Pandas adalah pustaka Python dengan banyak utilitas bermanfaat untuk memuat dan bekerja dengan data terstruktur. Kami akan menggunakan Pandas untuk mengunduh kumpulan data dari URL, dan memuatnya ke dalam bingkai data.

import pathlib

dataset_url = 'http://storage.googleapis.com/download.tensorflow.org/data/petfinder-mini.zip'
csv_file = 'datasets/petfinder-mini/petfinder-mini.csv'

tf.keras.utils.get_file('petfinder_mini.zip', dataset_url,
                        extract=True, cache_dir='.')
dataframe = pd.read_csv(csv_file)
Downloading data from http://storage.googleapis.com/download.tensorflow.org/data/petfinder-mini.zip
1671168/1668792 [==============================] - 0s 0us/step

dataframe.head()

Buat variabel target

Tugas dalam kumpulan data asli adalah memprediksi kecepatan adopsi hewan peliharaan (misalnya, pada minggu pertama, bulan pertama, tiga bulan pertama, dan seterusnya). Mari sederhanakan ini untuk tutorial kita. Di sini, kami akan mengubahnya menjadi masalah klasifikasi biner, dan hanya memprediksi apakah hewan peliharaan itu diadopsi, atau tidak.

Setelah mengubah kolom label, 0 menunjukkan hewan peliharaan tidak diadopsi, dan 1 menunjukkan hewan itu.

# In the original dataset "4" indicates the pet was not adopted.
dataframe['target'] = np.where(dataframe['AdoptionSpeed']==4, 0, 1)

# Drop un-used columns.
dataframe = dataframe.drop(columns=['AdoptionSpeed', 'Description'])

Pisahkan kerangka data menjadi pelatihan, validasi, dan pengujian

Kumpulan data yang kami unduh adalah satu file CSV. Kami akan membaginya menjadi set pelatihan, validasi, dan pengujian.

train, test = train_test_split(dataframe, test_size=0.2)
train, val = train_test_split(train, test_size=0.2)
print(len(train), 'train examples')
print(len(val), 'validation examples')
print(len(test), 'test examples')
7383 train examples
1846 validation examples
2308 test examples

Buat pipeline masukan menggunakan tf.data

Selanjutnya, kami akan membungkus dataframes dengan tf.data . Ini akan memungkinkan kita menggunakan kolom fitur sebagai jembatan untuk memetakan dari kolom di bingkai data Pandas ke fitur yang digunakan untuk melatih model. Jika kami bekerja dengan file CSV yang sangat besar (sangat besar sehingga tidak muat ke dalam memori), kami akan menggunakan tf.data untuk membacanya dari disk secara langsung. Itu tidak tercakup dalam tutorial ini.

# A utility method to create a tf.data dataset from a Pandas Dataframe
def df_to_dataset(dataframe, shuffle=True, batch_size=32):
  dataframe = dataframe.copy()
  labels = dataframe.pop('target')
  ds = tf.data.Dataset.from_tensor_slices((dict(dataframe), labels))
  if shuffle:
    ds = ds.shuffle(buffer_size=len(dataframe))
  ds = ds.batch(batch_size)
  return ds
batch_size = 5 # A small batch sized is used for demonstration purposes
train_ds = df_to_dataset(train, batch_size=batch_size)
val_ds = df_to_dataset(val, shuffle=False, batch_size=batch_size)
test_ds = df_to_dataset(test, shuffle=False, batch_size=batch_size)

Pahami pipeline input

Sekarang kita telah membuat pipeline input, mari kita panggil untuk melihat format data yang dikembalikannya. Kami telah menggunakan ukuran batch kecil agar output dapat dibaca.

for feature_batch, label_batch in train_ds.take(1):
  print('Every feature:', list(feature_batch.keys()))
  print('A batch of ages:', feature_batch['Age'])
  print('A batch of targets:', label_batch )
Every feature: ['Type', 'Age', 'Breed1', 'Gender', 'Color1', 'Color2', 'MaturitySize', 'FurLength', 'Vaccinated', 'Sterilized', 'Health', 'Fee', 'PhotoAmt']
A batch of ages: tf.Tensor([36 48  3 30 24], shape=(5,), dtype=int64)
A batch of targets: tf.Tensor([1 0 1 0 0], shape=(5,), dtype=int64)

Kita dapat melihat bahwa dataset mengembalikan kamus nama kolom (dari dataframe) yang memetakan ke nilai kolom dari baris di dataframe.

Peragakan beberapa tipe kolom fitur

TensorFlow menyediakan banyak jenis kolom fitur. Di bagian ini, kita akan membuat beberapa tipe kolom fitur, dan mendemonstrasikan bagaimana mereka mengubah kolom dari dataframe.

# We will use this batch to demonstrate several types of feature columns
example_batch = next(iter(train_ds))[0]
# A utility method to create a feature column
# and to transform a batch of data
def demo(feature_column):
  feature_layer = layers.DenseFeatures(feature_column)
  print(feature_layer(example_batch).numpy())

Kolom numerik

Output dari kolom fitur menjadi input ke model (menggunakan fungsi demo yang ditentukan di atas, kita akan dapat melihat dengan tepat bagaimana setiap kolom dari dataframe diubah). Kolom numerik adalah jenis kolom yang paling sederhana. Ini digunakan untuk mewakili fitur bernilai nyata. Saat menggunakan kolom ini, model Anda akan menerima nilai kolom dari dataframe tidak berubah.

photo_count = feature_column.numeric_column('PhotoAmt')
demo(photo_count)
[[1.]
 [2.]
 [2.]
 [4.]
 [1.]]

Dalam kumpulan data PetFinder, sebagian besar kolom dari kerangka data bersifat kategorikal.

Kolom yang dikelompokkan

Seringkali, Anda tidak ingin memasukkan angka secara langsung ke dalam model, tetapi membagi nilainya ke dalam kategori yang berbeda berdasarkan rentang numerik. Pertimbangkan data mentah yang menunjukkan usia seseorang. Daripada merepresentasikan usia sebagai kolom numerik, kita dapat membagi usia menjadi beberapa keranjang menggunakan kolom yang dikelompokkan . Perhatikan nilai one-hot di bawah ini yang menggambarkan rentang usia mana yang cocok untuk setiap baris.

age = feature_column.numeric_column('Age')
age_buckets = feature_column.bucketized_column(age, boundaries=[1, 3, 5])
demo(age_buckets)
[[0. 0. 0. 1.]
 [0. 0. 1. 0.]
 [0. 0. 0. 1.]
 [0. 1. 0. 0.]
 [0. 0. 1. 0.]]

Kolom kategoris

Dalam kumpulan data ini, Jenis direpresentasikan sebagai string (mis. 'Anjing', atau 'Kucing'). Kami tidak dapat memasukkan string secara langsung ke model. Sebagai gantinya, kita harus terlebih dahulu memetakannya ke nilai numerik. Kolom kosakata kategoris menyediakan cara untuk merepresentasikan string sebagai vektor one-hot (seperti yang telah Anda lihat di atas dengan kelompok usia). Kosakata dapat dikirimkan sebagai daftar menggunakan kategorikal_kolom_dengan_daftar_kategorikal , atau dimuat dari file menggunakan file_kategorikal_kolom_dengan_file_kategorikal .

animal_type = feature_column.categorical_column_with_vocabulary_list(
      'Type', ['Cat', 'Dog'])

animal_type_one_hot = feature_column.indicator_column(animal_type)
demo(animal_type_one_hot)
[[1. 0.]
 [1. 0.]
 [0. 1.]
 [0. 1.]
 [0. 1.]]

Menyematkan kolom

Misalkan alih-alih hanya memiliki beberapa kemungkinan string, kita memiliki ribuan (atau lebih) nilai per kategori. Karena sejumlah alasan, seiring bertambahnya jumlah kategori, melatih jaringan neural menggunakan enkode one-hot menjadi tidak mungkin. Kita bisa menggunakan kolom embedding untuk mengatasi batasan ini. Alih-alih merepresentasikan data sebagai vektor one-hot dari banyak dimensi, kolom embedding merepresentasikan data tersebut sebagai vektor padat berdimensi lebih rendah di mana setiap sel dapat berisi angka apa pun, bukan hanya 0 atau 1. Ukuran embedding ( 8, pada contoh di bawah) adalah parameter yang harus disetel.

# Notice the input to the embedding column is the categorical column
# we previously created
breed1 = feature_column.categorical_column_with_vocabulary_list(
      'Breed1', dataframe.Breed1.unique())
breed1_embedding = feature_column.embedding_column(breed1, dimension=8)
demo(breed1_embedding)
[[ 0.3324157   0.4197986   0.50347906 -0.49933374  0.01970459 -0.2535548
  -0.01637078  0.37853056]
 [ 0.38036337  0.20561606 -0.15727694  0.00184843 -0.19711411  0.46115682
  -0.05730496 -0.35953665]
 [-0.03274023  0.36311874  0.3822702   0.12975089 -0.6652591   0.5957904
   0.49060807 -0.05435312]
 [ 0.44843388 -0.00815179  0.11813674 -0.22067873  0.03251803 -0.3833288
  -0.45184475  0.5564358 ]
 [ 0.44843388 -0.00815179  0.11813674 -0.22067873  0.03251803 -0.3833288
  -0.45184475  0.5564358 ]]

Kolom fitur dengan hash

Cara lain untuk merepresentasikan kolom kategorikal dengan sejumlah besar nilai adalah dengan menggunakan kategorikal_kolom_dengan_hash_bucket . Kolom fitur ini menghitung nilai hash dari masukan, lalu memilih salah satu keranjang hash_bucket_size untuk mengenkode string. Saat menggunakan kolom ini, Anda tidak perlu menyediakan kosakata, dan Anda dapat memilih untuk membuat jumlah hash_bucket jauh lebih kecil daripada jumlah kategori sebenarnya untuk menghemat ruang.

breed1_hashed = feature_column.categorical_column_with_hash_bucket(
      'Breed1', hash_bucket_size=10)
demo(feature_column.indicator_column(breed1_hashed))
[[0. 0. 0. 0. 0. 0. 0. 0. 0. 1.]
 [0. 0. 0. 1. 0. 0. 0. 0. 0. 0.]
 [0. 0. 1. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 1. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 1. 0. 0.]]

Kolom fitur bersilangan

Menggabungkan fitur menjadi satu fitur, lebih dikenal sebagai persilangan fitur , memungkinkan model mempelajari bobot terpisah untuk setiap kombinasi fitur. Di sini, kami akan membuat fitur baru yaitu persilangan Usia dan Jenis. Perhatikan bahwa crossed_column tidak membangun tabel lengkap dari semua kemungkinan kombinasi (yang bisa sangat besar). Sebaliknya, ini didukung oleh hashed_column , sehingga Anda dapat memilih seberapa besar tabelnya.

crossed_feature = feature_column.crossed_column([age_buckets, animal_type], hash_bucket_size=10)
demo(feature_column.indicator_column(crossed_feature))
[[1. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 1. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 1. 0.]
 [0. 1. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 1. 0. 0. 0.]]

Pilih kolom mana yang akan digunakan

Kami telah melihat bagaimana menggunakan beberapa tipe kolom fitur. Sekarang kita akan menggunakannya untuk melatih model. Tujuan dari tutorial ini adalah untuk menunjukkan kepada Anda kode lengkap (misalnya mekanik) yang diperlukan untuk bekerja dengan kolom fitur. Kami telah memilih beberapa kolom untuk melatih model kami di bawah ini secara sewenang-wenang.

feature_columns = []

# numeric cols
for header in ['PhotoAmt', 'Fee', 'Age']:
  feature_columns.append(feature_column.numeric_column(header))
# bucketized cols
age = feature_column.numeric_column('Age')
age_buckets = feature_column.bucketized_column(age, boundaries=[1, 2, 3, 4, 5])
feature_columns.append(age_buckets)
# indicator_columns
indicator_column_names = ['Type', 'Color1', 'Color2', 'Gender', 'MaturitySize',
                          'FurLength', 'Vaccinated', 'Sterilized', 'Health']
for col_name in indicator_column_names:
  categorical_column = feature_column.categorical_column_with_vocabulary_list(
      col_name, dataframe[col_name].unique())
  indicator_column = feature_column.indicator_column(categorical_column)
  feature_columns.append(indicator_column)
# embedding columns
breed1 = feature_column.categorical_column_with_vocabulary_list(
      'Breed1', dataframe.Breed1.unique())
breed1_embedding = feature_column.embedding_column(breed1, dimension=8)
feature_columns.append(breed1_embedding)
# crossed columns
age_type_feature = feature_column.crossed_column([age_buckets, animal_type], hash_bucket_size=100)
feature_columns.append(feature_column.indicator_column(age_type_feature))

Buat lapisan fitur

Sekarang setelah kita mendefinisikan kolom fitur kita, kita akan menggunakan layer DenseFeatures untuk memasukkannya ke model Keras kita.

feature_layer = tf.keras.layers.DenseFeatures(feature_columns)

Sebelumnya, kami menggunakan ukuran batch kecil untuk mendemonstrasikan cara kerja kolom fitur. Kami membuat pipeline input baru dengan ukuran batch yang lebih besar.

batch_size = 32
train_ds = df_to_dataset(train, batch_size=batch_size)
val_ds = df_to_dataset(val, shuffle=False, batch_size=batch_size)
test_ds = df_to_dataset(test, shuffle=False, batch_size=batch_size)

Buat, kompilasi, dan latih model

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

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

model.fit(train_ds,
          validation_data=val_ds,
          epochs=10)
Epoch 1/10
WARNING:tensorflow:Layers in a Sequential model should only have a single input tensor, but we receive a <class 'dict'> input: {'Type': <tf.Tensor 'ExpandDims_11:0' shape=(None, 1) dtype=string>, 'Age': <tf.Tensor 'ExpandDims:0' shape=(None, 1) dtype=int64>, 'Breed1': <tf.Tensor 'ExpandDims_1:0' shape=(None, 1) dtype=string>, 'Gender': <tf.Tensor 'ExpandDims_6:0' shape=(None, 1) dtype=string>, 'Color1': <tf.Tensor 'ExpandDims_2:0' shape=(None, 1) dtype=string>, 'Color2': <tf.Tensor 'ExpandDims_3:0' shape=(None, 1) dtype=string>, 'MaturitySize': <tf.Tensor 'ExpandDims_8:0' shape=(None, 1) dtype=string>, 'FurLength': <tf.Tensor 'ExpandDims_5:0' shape=(None, 1) dtype=string>, 'Vaccinated': <tf.Tensor 'ExpandDims_12:0' shape=(None, 1) dtype=string>, 'Sterilized': <tf.Tensor 'ExpandDims_10:0' shape=(None, 1) dtype=string>, 'Health': <tf.Tensor 'ExpandDims_7:0' shape=(None, 1) dtype=string>, 'Fee': <tf.Tensor 'ExpandDims_4:0' shape=(None, 1) dtype=int64>, 'PhotoAmt': <tf.Tensor 'ExpandDims_9:0' shape=(None, 1) dtype=int64>}
Consider rewriting this model with the Functional API.
WARNING:tensorflow:Layers in a Sequential model should only have a single input tensor, but we receive a <class 'dict'> input: {'Type': <tf.Tensor 'ExpandDims_11:0' shape=(None, 1) dtype=string>, 'Age': <tf.Tensor 'ExpandDims:0' shape=(None, 1) dtype=int64>, 'Breed1': <tf.Tensor 'ExpandDims_1:0' shape=(None, 1) dtype=string>, 'Gender': <tf.Tensor 'ExpandDims_6:0' shape=(None, 1) dtype=string>, 'Color1': <tf.Tensor 'ExpandDims_2:0' shape=(None, 1) dtype=string>, 'Color2': <tf.Tensor 'ExpandDims_3:0' shape=(None, 1) dtype=string>, 'MaturitySize': <tf.Tensor 'ExpandDims_8:0' shape=(None, 1) dtype=string>, 'FurLength': <tf.Tensor 'ExpandDims_5:0' shape=(None, 1) dtype=string>, 'Vaccinated': <tf.Tensor 'ExpandDims_12:0' shape=(None, 1) dtype=string>, 'Sterilized': <tf.Tensor 'ExpandDims_10:0' shape=(None, 1) dtype=string>, 'Health': <tf.Tensor 'ExpandDims_7:0' shape=(None, 1) dtype=string>, 'Fee': <tf.Tensor 'ExpandDims_4:0' shape=(None, 1) dtype=int64>, 'PhotoAmt': <tf.Tensor 'ExpandDims_9:0' shape=(None, 1) dtype=int64>}
Consider rewriting this model with the Functional API.
225/231 [============================>.] - ETA: 0s - loss: 0.6649 - accuracy: 0.6749WARNING:tensorflow:Layers in a Sequential model should only have a single input tensor, but we receive a <class 'dict'> input: {'Type': <tf.Tensor 'ExpandDims_11:0' shape=(None, 1) dtype=string>, 'Age': <tf.Tensor 'ExpandDims:0' shape=(None, 1) dtype=int64>, 'Breed1': <tf.Tensor 'ExpandDims_1:0' shape=(None, 1) dtype=string>, 'Gender': <tf.Tensor 'ExpandDims_6:0' shape=(None, 1) dtype=string>, 'Color1': <tf.Tensor 'ExpandDims_2:0' shape=(None, 1) dtype=string>, 'Color2': <tf.Tensor 'ExpandDims_3:0' shape=(None, 1) dtype=string>, 'MaturitySize': <tf.Tensor 'ExpandDims_8:0' shape=(None, 1) dtype=string>, 'FurLength': <tf.Tensor 'ExpandDims_5:0' shape=(None, 1) dtype=string>, 'Vaccinated': <tf.Tensor 'ExpandDims_12:0' shape=(None, 1) dtype=string>, 'Sterilized': <tf.Tensor 'ExpandDims_10:0' shape=(None, 1) dtype=string>, 'Health': <tf.Tensor 'ExpandDims_7:0' shape=(None, 1) dtype=string>, 'Fee': <tf.Tensor 'ExpandDims_4:0' shape=(None, 1) dtype=int64>, 'PhotoAmt': <tf.Tensor 'ExpandDims_9:0' shape=(None, 1) dtype=int64>}
Consider rewriting this model with the Functional API.
231/231 [==============================] - 3s 11ms/step - loss: 0.6621 - accuracy: 0.6768 - val_loss: 0.5403 - val_accuracy: 0.6891
Epoch 2/10
231/231 [==============================] - 2s 8ms/step - loss: 0.5542 - accuracy: 0.7154 - val_loss: 0.5154 - val_accuracy: 0.7210
Epoch 3/10
231/231 [==============================] - 2s 8ms/step - loss: 0.5178 - accuracy: 0.7268 - val_loss: 0.4996 - val_accuracy: 0.7411
Epoch 4/10
231/231 [==============================] - 2s 8ms/step - loss: 0.5044 - accuracy: 0.7295 - val_loss: 0.4856 - val_accuracy: 0.7449
Epoch 5/10
231/231 [==============================] - 2s 7ms/step - loss: 0.4956 - accuracy: 0.7398 - val_loss: 0.4814 - val_accuracy: 0.7486
Epoch 6/10
231/231 [==============================] - 2s 8ms/step - loss: 0.4894 - accuracy: 0.7363 - val_loss: 0.4875 - val_accuracy: 0.7514
Epoch 7/10
231/231 [==============================] - 2s 7ms/step - loss: 0.4832 - accuracy: 0.7413 - val_loss: 0.4824 - val_accuracy: 0.7443
Epoch 8/10
231/231 [==============================] - 2s 7ms/step - loss: 0.4766 - accuracy: 0.7469 - val_loss: 0.4907 - val_accuracy: 0.7134
Epoch 9/10
231/231 [==============================] - 2s 8ms/step - loss: 0.4749 - accuracy: 0.7492 - val_loss: 0.4838 - val_accuracy: 0.7503
Epoch 10/10
231/231 [==============================] - 2s 7ms/step - loss: 0.4673 - accuracy: 0.7502 - val_loss: 0.4847 - val_accuracy: 0.7486

<tensorflow.python.keras.callbacks.History at 0x7f3b296a8e48>
loss, accuracy = model.evaluate(test_ds)
print("Accuracy", accuracy)
73/73 [==============================] - 0s 5ms/step - loss: 0.5179 - accuracy: 0.7413
Accuracy 0.7413344979286194

Langkah selanjutnya

Cara terbaik untuk mempelajari lebih lanjut tentang mengklasifikasikan data terstruktur adalah dengan mencobanya sendiri. Kami menyarankan untuk mencari set data lain untuk digunakan, dan melatih model untuk mengklasifikasikannya menggunakan kode yang mirip dengan di atas. Untuk meningkatkan akurasi, pikirkan baik-baik tentang fitur mana yang akan disertakan dalam model Anda, dan bagaimana mereka harus direpresentasikan.