TensorFlow.org'da görüntüleyin | Google Colab'da çalıştırın | Kaynağı GitHub'da görüntüleyin | Not defterini indir |
Bu öğretici, yapılandırılmış verilerin nasıl sınıflandırılacağını gösterir (örneğin, bir CSV'deki tablo verileri). Modeli tanımlamak için Keras'ı ve bir CSV'deki sütunlardan modeli eğitmek için kullanılan özelliklere eşlemek için bir köprü olarak tf.feature_column
. Bu eğitici, aşağıdakiler için eksiksiz bir kod içerir:
- Panda'ları kullanarak bir CSV dosyası yükleyin.
- tf.data kullanarak satırları toplu hale getirmek ve karıştırmak için bir girdi ardışık düzeni oluşturun.
- CSV'deki sütunlardan, özellik sütunlarını kullanarak modeli eğitmek için kullanılan özelliklere eşleyin.
- Keras'ı kullanarak bir model oluşturun, eğitin ve değerlendirin.
Veri Kümesi
PetFinder veri setinin basitleştirilmiş bir versiyonunu kullanacağız. CSV'de birkaç bin satır var. Her satır bir evcil hayvanı ve her sütun bir özelliği tanımlar. Bu bilgiyi evcil hayvanın sahiplenilme hızını tahmin etmek için kullanacağız.
Aşağıda bu veri kümesinin açıklaması yer almaktadır. Hem sayısal hem de kategorik sütunlar olduğuna dikkat edin. Bu eğitimde kullanmayacağımız bir serbest metin sütunu var.
Kolon | Açıklama | Özellik Türü | Veri tipi |
---|---|---|---|
Tip | Hayvan türü (Köpek, Kedi) | Kategorik | sicim |
Yaş | evcil hayvan yaşı | Sayısal | tam sayı |
cins1 | Evcil hayvanın birincil cinsi | Kategorik | sicim |
Renk1 | Evcil hayvanın rengi 1 | Kategorik | sicim |
Renk2 | Evcil hayvanın 2. rengi | Kategorik | sicim |
OlgunlukBoyutu | Olgunluktaki boyut | Kategorik | sicim |
Kürk Uzunluğu | kürk uzunluğu | Kategorik | sicim |
aşılı | Evcil hayvan aşılandı | Kategorik | sicim |
Sterilize | Evcil hayvan sterilize edildi | Kategorik | sicim |
Sağlık | Sağlık durumu | Kategorik | sicim |
Ücret | Evlat Edinme Ücreti | Sayısal | tam sayı |
Açıklama | Bu evcil hayvan için profil yazısı | Metin | sicim |
FotoğrafAmt | Bu evcil hayvan için yüklenen toplam fotoğraf | Sayısal | tam sayı |
BenimsemeHızı | benimseme hızı | sınıflandırma | tam sayı |
TensorFlow ve diğer kitaplıkları içe aktarın
pip install sklearn
tutucu1 l10n-yerimport 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
Bir veri çerçevesi oluşturmak için Pandaları kullanın
Pandas , yapılandırılmış verileri yüklemek ve bunlarla çalışmak için birçok yararlı yardımcı program içeren bir Python kitaplığıdır. Veri kümesini bir URL'den indirmek ve bir veri çerçevesine yüklemek için Panda'ları kullanacağız.
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 1679360/1668792 [==============================] - 0s 0us/step-yer tutucu4 l10n-yer
dataframe.head()
Hedef değişken oluştur
Orijinal veri kümesindeki görev, bir evcil hayvanın sahiplenilme hızını tahmin etmektir (örneğin, ilk hafta, ilk ay, ilk üç ay, vb.). Bunu öğreticimiz için basitleştirelim. Burada bunu bir ikili sınıflandırma problemine dönüştüreceğiz ve sadece evcil hayvanın sahiplenilip alınmadığını tahmin edeceğiz.
Etiket sütununu değiştirdikten sonra 0, evcil hayvanın sahiplenilmediğini ve 1 ise kabul edildiğini gösterecektir.
# 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'])
Veri çerçevesini tren, doğrulama ve test olarak ayırın
İndirdiğimiz veri seti tek bir CSV dosyasıydı. Bunu tren, doğrulama ve test setlerine ayıracağız.
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')
tutucu7 l10n-yer7383 train examples 1846 validation examples 2308 test examples
tf.data kullanarak bir girdi işlem hattı oluşturun
Ardından, veri çerçevelerini tf.data ile saracağız . Bu, Pandas veri çerçevesindeki sütunlardan modeli eğitmek için kullanılan özelliklere eşlemek için özellik sütunlarını bir köprü olarak kullanmamızı sağlayacaktır. Çok büyük bir CSV dosyasıyla (belleğe sığmayacak kadar büyük) çalışıyor olsaydık, onu doğrudan diskten okumak için tf.data kullanırdık. Bu, bu eğitimde ele alınmamıştır.
# 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
tutucu9 l10n-yerbatch_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)
Giriş hattını anlayın
Şimdi girdi ardışık düzenini oluşturduğumuza göre, döndürdüğü verinin biçimini görmek için onu çağıralım. Çıktıyı okunabilir kılmak için küçük bir toplu iş boyutu kullandık.
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 )
tutucu11 l10n-yerEvery feature: ['Type', 'Age', 'Breed1', 'Gender', 'Color1', 'Color2', 'MaturitySize', 'FurLength', 'Vaccinated', 'Sterilized', 'Health', 'Fee', 'PhotoAmt'] A batch of ages: tf.Tensor([ 6 2 36 2 2], shape=(5,), dtype=int64) A batch of targets: tf.Tensor([1 1 1 1 1], shape=(5,), dtype=int64)
Veri kümesinin, veri çerçevesindeki satırlardan sütun değerleriyle eşleşen bir sütun adları sözlüğü (veri çerçevesinden) döndürdüğünü görebiliriz.
Birkaç tür özellik sütunu gösterin
TensorFlow, birçok türde özellik sütunu sağlar. Bu bölümde, birkaç tür özellik sütunu oluşturacağız ve bunların veri çerçevesinden bir sütunu nasıl dönüştürdüklerini göstereceğiz.
# We will use this batch to demonstrate several types of feature columns
example_batch = next(iter(train_ds))[0]
tutucu13 l10n-yer# 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())
sayısal sütunlar
Bir özellik sütununun çıktısı, modelin girdisi olur (yukarıda tanımlanan demo işlevini kullanarak, veri çerçevesinden her bir sütunun tam olarak nasıl dönüştürüldüğünü görebileceğiz). Sayısal sütun , en basit sütun türüdür. Gerçek değerli özellikleri temsil etmek için kullanılır. Bu sütunu kullanırken, modeliniz veri çerçevesinden sütun değerini değişmeden alacaktır.
photo_count = feature_column.numeric_column('PhotoAmt')
demo(photo_count)
tutucu15 l10n-yer[[2.] [4.] [4.] [1.] [2.]]
PetFinder veri kümesinde, veri çerçevesindeki çoğu sütun kategoriktir.
Paketlenmiş sütunlar
Çoğu zaman, modele doğrudan bir sayı beslemek istemezsiniz, bunun yerine değerini sayısal aralıklara dayalı olarak farklı kategorilere bölersiniz. Bir kişinin yaşını temsil eden ham verileri düşünün. Yaşı sayısal bir sütun olarak göstermek yerine, bir gruplandırılmış sütun kullanarak yaşı birkaç bölüme ayırabiliriz. Aşağıdaki tek-sıcak değerlerin, her satırın hangi yaş aralığıyla eşleştiğini açıkladığına dikkat edin.
age = feature_column.numeric_column('Age')
age_buckets = feature_column.bucketized_column(age, boundaries=[1, 3, 5])
demo(age_buckets)
tutucu17 l10n-yer[[0. 0. 0. 1.] [0. 1. 0. 0.] [0. 0. 0. 1.] [0. 0. 1. 0.] [0. 1. 0. 0.]]
kategorik sütunlar
Bu veri kümesinde, Tür bir dize olarak temsil edilir (örneğin, 'Köpek' veya 'Kedi'). Dizeleri doğrudan bir modele besleyemeyiz. Bunun yerine, önce onları sayısal değerlerle eşlemeliyiz. Kategorik sözcük dağarcığı sütunları, dizeleri tek-sıcak bir vektör olarak göstermenin bir yolunu sağlar (yukarıda yaş gruplarıyla gördüğünüz gibi). Sözcük, categorical_column_with_vocabulary_list kullanılarak bir liste olarak geçirilebilir veya categorical_column_with_vocabulary_file kullanılarak bir dosyadan yüklenebilir.
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)
tutucu19 l10n-yer[[1. 0.] [1. 0.] [1. 0.] [1. 0.] [0. 1.]]
Sütunları gömme
Birkaç olası dizgeye sahip olmak yerine, kategori başına binlerce (veya daha fazla) değerimiz olduğunu varsayalım. Bir dizi nedenden dolayı, kategorilerin sayısı arttıkça, tek-sıcak kodlamalar kullanarak bir sinir ağını eğitmek olanaksız hale gelir. Bu sınırlamanın üstesinden gelmek için bir gömme sütunu kullanabiliriz. Bir gömme sütunu , verileri birçok boyuttaki tek-sıcak vektör olarak temsil etmek yerine, bu verileri daha düşük boyutlu, yoğun bir vektör olarak temsil eder; burada her hücre yalnızca 0 veya 1 değil, herhangi bir sayı içerebilir. Gömmenin boyutu ( 8, aşağıdaki örnekte) ayarlanması gereken bir parametredir.
# 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)
tutucu21 l10n-yer[[-0.22380038 -0.09379731 0.21349265 0.33451992 -0.49730566 0.05174963 0.2668497 0.27391028] [-0.5484653 -0.03492585 0.05648395 -0.09792244 0.02530896 -0.15477926 -0.10695003 -0.45474145] [-0.22380038 -0.09379731 0.21349265 0.33451992 -0.49730566 0.05174963 0.2668497 0.27391028] [ 0.10050306 0.43513173 0.375823 0.5652766 0.40925583 -0.03928828 0.4901914 0.20637617] [-0.2319875 -0.21874283 0.12272807 0.33345345 -0.4563055 0.21609035 -0.2410521 0.4736915 ]]
Karma özellik sütunları
Çok sayıda değer içeren kategorik bir sütunu temsil etmenin başka bir yolu da categorical_column_with_hash_bucket kullanmaktır. Bu özellik sütunu, girişin bir karma değerini hesaplar, ardından bir dizeyi kodlamak için hash_bucket_size
birini seçer. Bu sütunu kullanırken, kelime bilgisi sağlamanız gerekmez ve yerden tasarruf etmek için hash_buckets sayısını gerçek kategori sayısından önemli ölçüde daha küçük yapmayı seçebilirsiniz.
breed1_hashed = feature_column.categorical_column_with_hash_bucket(
'Breed1', hash_bucket_size=10)
demo(feature_column.indicator_column(breed1_hashed))
tutucu23 l10n-yer[[0. 0. 0. 0. 0. 0. 0. 0. 0. 1.] [0. 0. 0. 0. 0. 0. 0. 1. 0. 0.] [0. 0. 0. 0. 0. 0. 0. 0. 0. 1.] [0. 0. 0. 0. 0. 0. 1. 0. 0. 0.] [0. 0. 0. 0. 0. 0. 0. 1. 0. 0.]]
Çapraz özellik sütunları
Unsurları tek bir unsurda birleştirmek, daha çok unsur çaprazları olarak bilinir, bir modelin her unsur kombinasyonu için ayrı ağırlıklar öğrenmesini sağlar. Burada, Yaş ve Tür çaprazı olan yeni bir özellik oluşturacağız. crossed_column
tüm olası kombinasyonların (çok büyük olabilir) tam tablosunu oluşturmadığını unutmayın. Bunun yerine, bir hashed_column
tarafından desteklenir, böylece tablonun ne kadar büyük olduğunu seçebilirsiniz.
crossed_feature = feature_column.crossed_column([age_buckets, animal_type], hash_bucket_size=10)
demo(feature_column.indicator_column(crossed_feature))
tutucu25 l10n-yer[[1. 0. 0. 0. 0. 0. 0. 0. 0. 0.] [0. 0. 0. 1. 0. 0. 0. 0. 0. 0.] [1. 0. 0. 0. 0. 0. 0. 0. 0. 0.] [0. 1. 0. 0. 0. 0. 0. 0. 0. 0.] [0. 1. 0. 0. 0. 0. 0. 0. 0. 0.]]
Hangi sütunların kullanılacağını seçin
Birkaç tür özellik sütununun nasıl kullanılacağını gördük. Şimdi onları bir modeli eğitmek için kullanacağız. Bu öğreticinin amacı, özellik sütunlarıyla çalışmak için gereken kodun tamamını (ör. mekanik) size göstermektir. Aşağıdaki modelimizi keyfi olarak eğitmek için birkaç sütun seçtik.
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))
Bir özellik katmanı oluşturun
Özellik sütunlarımızı tanımladığımıza göre, bunları Keras modelimize girmek için bir DenseFeatures katmanı kullanacağız.
feature_layer = tf.keras.layers.DenseFeatures(feature_columns)
Daha önce, özellik sütunlarının nasıl çalıştığını göstermek için küçük bir toplu iş boyutu kullandık. Daha büyük bir parti boyutuna sahip yeni bir girdi işlem hattı oluşturuyoruz.
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)
Modeli oluşturun, derleyin ve eğitin
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. Received: inputs={'Type': <tf.Tensor 'IteratorGetNext:11' shape=(None,) dtype=string>, 'Age': <tf.Tensor 'IteratorGetNext:0' shape=(None,) dtype=int64>, 'Breed1': <tf.Tensor 'IteratorGetNext:1' shape=(None,) dtype=string>, 'Gender': <tf.Tensor 'IteratorGetNext:6' shape=(None,) dtype=string>, 'Color1': <tf.Tensor 'IteratorGetNext:2' shape=(None,) dtype=string>, 'Color2': <tf.Tensor 'IteratorGetNext:3' shape=(None,) dtype=string>, 'MaturitySize': <tf.Tensor 'IteratorGetNext:8' shape=(None,) dtype=string>, 'FurLength': <tf.Tensor 'IteratorGetNext:5' shape=(None,) dtype=string>, 'Vaccinated': <tf.Tensor 'IteratorGetNext:12' shape=(None,) dtype=string>, 'Sterilized': <tf.Tensor 'IteratorGetNext:10' shape=(None,) dtype=string>, 'Health': <tf.Tensor 'IteratorGetNext:7' shape=(None,) dtype=string>, 'Fee': <tf.Tensor 'IteratorGetNext:4' shape=(None,) dtype=int64>, 'PhotoAmt': <tf.Tensor 'IteratorGetNext:9' shape=(None,) dtype=int64>}. Consider rewriting this model with the Functional API. WARNING:tensorflow:Layers in a Sequential model should only have a single input tensor. Received: inputs={'Type': <tf.Tensor 'IteratorGetNext:11' shape=(None,) dtype=string>, 'Age': <tf.Tensor 'IteratorGetNext:0' shape=(None,) dtype=int64>, 'Breed1': <tf.Tensor 'IteratorGetNext:1' shape=(None,) dtype=string>, 'Gender': <tf.Tensor 'IteratorGetNext:6' shape=(None,) dtype=string>, 'Color1': <tf.Tensor 'IteratorGetNext:2' shape=(None,) dtype=string>, 'Color2': <tf.Tensor 'IteratorGetNext:3' shape=(None,) dtype=string>, 'MaturitySize': <tf.Tensor 'IteratorGetNext:8' shape=(None,) dtype=string>, 'FurLength': <tf.Tensor 'IteratorGetNext:5' shape=(None,) dtype=string>, 'Vaccinated': <tf.Tensor 'IteratorGetNext:12' shape=(None,) dtype=string>, 'Sterilized': <tf.Tensor 'IteratorGetNext:10' shape=(None,) dtype=string>, 'Health': <tf.Tensor 'IteratorGetNext:7' shape=(None,) dtype=string>, 'Fee': <tf.Tensor 'IteratorGetNext:4' shape=(None,) dtype=int64>, 'PhotoAmt': <tf.Tensor 'IteratorGetNext:9' shape=(None,) dtype=int64>}. Consider rewriting this model with the Functional API. 231/231 [==============================] - ETA: 0s - loss: 0.6759 - accuracy: 0.6802WARNING:tensorflow:Layers in a Sequential model should only have a single input tensor. Received: inputs={'Type': <tf.Tensor 'IteratorGetNext:11' shape=(None,) dtype=string>, 'Age': <tf.Tensor 'IteratorGetNext:0' shape=(None,) dtype=int64>, 'Breed1': <tf.Tensor 'IteratorGetNext:1' shape=(None,) dtype=string>, 'Gender': <tf.Tensor 'IteratorGetNext:6' shape=(None,) dtype=string>, 'Color1': <tf.Tensor 'IteratorGetNext:2' shape=(None,) dtype=string>, 'Color2': <tf.Tensor 'IteratorGetNext:3' shape=(None,) dtype=string>, 'MaturitySize': <tf.Tensor 'IteratorGetNext:8' shape=(None,) dtype=string>, 'FurLength': <tf.Tensor 'IteratorGetNext:5' shape=(None,) dtype=string>, 'Vaccinated': <tf.Tensor 'IteratorGetNext:12' shape=(None,) dtype=string>, 'Sterilized': <tf.Tensor 'IteratorGetNext:10' shape=(None,) dtype=string>, 'Health': <tf.Tensor 'IteratorGetNext:7' shape=(None,) dtype=string>, 'Fee': <tf.Tensor 'IteratorGetNext:4' shape=(None,) dtype=int64>, 'PhotoAmt': <tf.Tensor 'IteratorGetNext:9' shape=(None,) dtype=int64>}. Consider rewriting this model with the Functional API. 231/231 [==============================] - 4s 10ms/step - loss: 0.6759 - accuracy: 0.6802 - val_loss: 0.5361 - val_accuracy: 0.7351 Epoch 2/10 231/231 [==============================] - 2s 9ms/step - loss: 0.5742 - accuracy: 0.7054 - val_loss: 0.5178 - val_accuracy: 0.7411 Epoch 3/10 231/231 [==============================] - 2s 9ms/step - loss: 0.5369 - accuracy: 0.7231 - val_loss: 0.5031 - val_accuracy: 0.7438 Epoch 4/10 231/231 [==============================] - 2s 9ms/step - loss: 0.5161 - accuracy: 0.7214 - val_loss: 0.5115 - val_accuracy: 0.7259 Epoch 5/10 231/231 [==============================] - 2s 9ms/step - loss: 0.5034 - accuracy: 0.7296 - val_loss: 0.5173 - val_accuracy: 0.7237 Epoch 6/10 231/231 [==============================] - 2s 8ms/step - loss: 0.4983 - accuracy: 0.7301 - val_loss: 0.5153 - val_accuracy: 0.7254 Epoch 7/10 231/231 [==============================] - 2s 9ms/step - loss: 0.4912 - accuracy: 0.7412 - val_loss: 0.5258 - val_accuracy: 0.7010 Epoch 8/10 231/231 [==============================] - 2s 9ms/step - loss: 0.4890 - accuracy: 0.7360 - val_loss: 0.5066 - val_accuracy: 0.7221 Epoch 9/10 231/231 [==============================] - 2s 9ms/step - loss: 0.4824 - accuracy: 0.7443 - val_loss: 0.5091 - val_accuracy: 0.7481 Epoch 10/10 231/231 [==============================] - 2s 9ms/step - loss: 0.4758 - accuracy: 0.7466 - val_loss: 0.5159 - val_accuracy: 0.7492 <keras.callbacks.History at 0x7f06b52a1810>yer tutucu35 l10n-yer
loss, accuracy = model.evaluate(test_ds)
print("Accuracy", accuracy)
73/73 [==============================] - 0s 6ms/step - loss: 0.4812 - accuracy: 0.7543 Accuracy 0.7543327808380127
Sonraki adımlar
Yapılandırılmış verileri sınıflandırma hakkında daha fazla bilgi edinmenin en iyi yolu, onu kendiniz denemektir. Çalışmak için başka bir veri kümesi bulmanızı ve yukarıdakine benzer bir kod kullanarak sınıflandırmak için bir model eğitmenizi öneririz. Doğruluğu artırmak için modelinize hangi özellikleri ekleyeceğinizi ve bunların nasıl temsil edilmesi gerektiğini dikkatlice düşünün.