طبقه بندی داده های ساخت یافته با استفاده از لایه های پیش پردازش Keras

مشاهده در TensorFlow.org در Google Colab اجرا شود مشاهده منبع در GitHub دانلود دفترچه یادداشت

این آموزش نحوه طبقه بندی داده های ساخت یافته مانند داده های جدولی را با استفاده از نسخه ساده شده مجموعه داده PetFinder از رقابت Kaggle که در یک فایل CSV ذخیره شده است، نشان می دهد.

شما از Keras برای تعریف مدل استفاده خواهید کرد و از لایه های پیش پردازش Keras به عنوان پلی برای نقشه برداری از ستون ها در یک فایل CSV به ویژگی های مورد استفاده برای آموزش مدل استفاده خواهید کرد. هدف این است که پیش بینی کنیم که آیا حیوان خانگی به فرزندی پذیرفته می شود.

این آموزش شامل کدهای کامل برای:

  • بارگیری یک فایل CSV در یک DataFrame با استفاده از پانداها .
  • ساخت یک خط لوله ورودی برای دسته بندی و به هم زدن ردیف ها با استفاده از tf.data . (برای جزئیات بیشتر به tf.data مراجعه کنید: خطوط لوله ورودی TensorFlow را بسازید .)
  • نقشه برداری از ستون ها در فایل CSV به ویژگی های مورد استفاده برای آموزش مدل با لایه های پیش پردازش Keras.
  • ساخت، آموزش و ارزیابی مدل با استفاده از روش‌های داخلی Keras.

مجموعه داده کوچک PetFinder.my

چندین هزار ردیف در فایل مجموعه داده CSV PetFinder.my mini وجود دارد که در هر ردیف یک حیوان خانگی (سگ یا گربه) و هر ستون یک ویژگی مانند سن، نژاد، رنگ و غیره را توصیف می کند.

در خلاصه مجموعه داده زیر، توجه داشته باشید که عمدتاً ستون‌های عددی و دسته‌بندی وجود دارد. در این آموزش، شما فقط با آن دو نوع ویژگی سر و کار خواهید داشت، حذف Description (یک ویژگی متن آزاد) و AdoptionSpeed (یک ویژگی طبقه بندی) در طول پیش پردازش داده ها.

ستون توضیحات حیوان خانگی نوع ویژگی نوع داده
Type نوع حیوان ( Dog ، Cat ) دسته بندی رشته
Age سن عددی عدد صحیح
Breed1 نژاد اولیه دسته بندی رشته
Color1 رنگ 1 دسته بندی رشته
Color2 رنگ 2 دسته بندی رشته
MaturitySize اندازه در بلوغ دسته بندی رشته
FurLength طول خز دسته بندی رشته
Vaccinated حیوان خانگی واکسینه شده است دسته بندی رشته
Sterilized حیوان خانگی عقیم شده است دسته بندی رشته
Health وضعیت سلامتی دسته بندی رشته
Fee هزینه فرزندخواندگی عددی عدد صحیح
Description نوشتن پروفایل متن رشته
PhotoAmt مجموع عکس های آپلود شده عددی عدد صحیح
AdoptionSpeed سرعت مقوله ای پذیرش طبقه بندی عدد صحیح

TensorFlow و کتابخانه های دیگر را وارد کنید

import numpy as np
import pandas as pd
import tensorflow as tf

from tensorflow.keras import layers
tf.__version__
'2.8.0-rc1'

مجموعه داده را بارگیری کنید و آن را در یک DataFrame پاندا بخوانید

pandas یک کتابخانه پایتون با بسیاری از ابزارهای مفید برای بارگیری و کار با داده های ساخت یافته است. از tf.keras.utils.get_file برای دانلود و استخراج فایل CSV با مجموعه داده کوچک PetFinder.my استفاده کنید و آن را در یک DataFrame با pandas.read_csv :

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

با بررسی پنج ردیف اول DataFrame، مجموعه داده را بررسی کنید:

dataframe.head()

یک متغیر هدف ایجاد کنید

وظیفه اصلی در رقابت Kaggle's PetFinder.my Adoption Prediction پیش بینی سرعت پذیرش حیوان خانگی بود (به عنوان مثال در هفته اول، ماه اول، سه ماه اول و غیره).

در این آموزش، کار را با تبدیل آن به یک مسئله طبقه بندی باینری ساده می کنید، که در آن شما به سادگی باید پیش بینی کنید که آیا حیوان خانگی پذیرفته شده است یا خیر.

پس از اصلاح ستون AdoptionSpeed ، 0 نشان می دهد که حیوان خانگی پذیرفته نشده است، و 1 نشان می دهد که حیوان خانگی پذیرفته نشده است.

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

# Drop unused features.
dataframe = dataframe.drop(columns=['AdoptionSpeed', 'Description'])

DataFrame را به مجموعه‌های آموزشی، اعتبارسنجی و آزمایشی تقسیم کنید

مجموعه داده در یک DataFrame پاندا است. به ترتیب با استفاده از نسبت 80:10:10، آن را به مجموعه های آموزشی، اعتبارسنجی و آزمایشی تقسیم کنید:

train, val, test = np.split(dataframe.sample(frac=1), [int(0.8*len(dataframe)), int(0.9*len(dataframe))])
print(len(train), 'training examples')
print(len(val), 'validation examples')
print(len(test), 'test examples')
9229 training examples
1154 validation examples
1154 test examples

با استفاده از tf.data یک خط لوله ورودی ایجاد کنید

سپس، یک تابع ابزار ایجاد کنید که هر آموزش، اعتبارسنجی و مجموعه آزمایشی DataFrame را به tf.data.Dataset تبدیل می‌کند، سپس داده‌ها را به هم می‌ریزد و دسته‌بندی می‌کند.

def df_to_dataset(dataframe, shuffle=True, batch_size=32):
  df = dataframe.copy()
  labels = df.pop('target')
  df = {key: value[:,tf.newaxis] for key, value in dataframe.items()}
  ds = tf.data.Dataset.from_tensor_slices((dict(df), labels))
  if shuffle:
    ds = ds.shuffle(buffer_size=len(dataframe))
  ds = ds.batch(batch_size)
  ds = ds.prefetch(batch_size)
  return ds

اکنون، از تابع جدید ایجاد شده ( df_to_dataset ) استفاده کنید تا فرمت داده‌هایی را که تابع کمکی خط لوله ورودی با فراخوانی آن بر روی داده‌های آموزشی برمی‌گرداند بررسی کنید و از یک اندازه دسته کوچک برای خواندن خروجی استفاده کنید:

batch_size = 5
train_ds = df_to_dataset(train, batch_size=batch_size)
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:4: FutureWarning: Support for multi-dimensional indexing (e.g. `obj[:, None]`) is deprecated and will be removed in a future version.  Convert to a numpy array before indexing instead.
  after removing the cwd from sys.path.
[(train_features, label_batch)] = train_ds.take(1)
print('Every feature:', list(train_features.keys()))
print('A batch of ages:', train_features['Age'])
print('A batch of targets:', label_batch )
Every feature: ['Type', 'Age', 'Breed1', 'Gender', 'Color1', 'Color2', 'MaturitySize', 'FurLength', 'Vaccinated', 'Sterilized', 'Health', 'Fee', 'PhotoAmt', 'target']
A batch of ages: tf.Tensor(
[[84]
 [ 1]
 [ 5]
 [ 1]
 [12]], shape=(5, 1), dtype=int64)
A batch of targets: tf.Tensor([1 1 0 1 0], shape=(5,), dtype=int64)

همانطور که خروجی نشان می دهد، مجموعه آموزشی یک فرهنگ لغت از نام ستون ها (از DataFrame) را برمی گرداند که مقادیر ستون ها را از ردیف ها نشان می دهد.

لایه های پیش پردازش Keras را اعمال کنید

لایه‌های پیش‌پردازش Keras به شما امکان می‌دهد خطوط لوله پردازش ورودی Keras را بسازید، که می‌تواند به عنوان کد پیش‌پردازش مستقل در جریان‌های کاری غیر Keras استفاده شود، مستقیماً با مدل‌های Keras ترکیب شده و به عنوان بخشی از Keras SavedModel صادر شود.

در این آموزش، شما از چهار لایه پیش پردازش زیر برای نشان دادن نحوه انجام پیش پردازش، رمزگذاری داده های ساخت یافته و مهندسی ویژگی استفاده خواهید کرد:

می‌توانید در راهنمای لایه‌های Working with preprocessing در مورد لایه‌های موجود بیشتر بدانید.

  • برای ویژگی‌های عددی مجموعه داده کوچک PetFinder.my، از یک لایه tf.keras.layers.Normalization برای استاندارد کردن توزیع داده‌ها استفاده خواهید کرد.
  • برای ویژگی‌های طبقه‌بندی‌شده ، مانند Type حیوانات خانگی (رشته‌های Dog و Cat )، آنها را با tf.keras.layers.CategoryEncoding به تانسورهای کدگذاری شده چند داغ تبدیل می‌کنید.

ستون های عددی

برای هر ویژگی عددی در مجموعه داده کوچک PetFinder.my، از یک لایه tf.keras.layers.Normalization برای استاندارد کردن توزیع داده ها استفاده خواهید کرد.

یک تابع ابزار جدید را تعریف کنید که لایه ای را برمی گرداند که با استفاده از لایه پیش پردازش Keras، نرمال سازی ویژگی ها را به ویژگی های عددی اعمال می کند:

def get_normalization_layer(name, dataset):
  # Create a Normalization layer for the feature.
  normalizer = layers.Normalization(axis=None)

  # Prepare a Dataset that only yields the feature.
  feature_ds = dataset.map(lambda x, y: x[name])

  # Learn the statistics of the data.
  normalizer.adapt(feature_ds)

  return normalizer

سپس، عملکرد جدید را با فراخوانی آن روی مجموع ویژگی‌های عکس حیوان خانگی آپلود شده آزمایش کنید تا 'PhotoAmt' عادی شود:

photo_count_col = train_features['PhotoAmt']
layer = get_normalization_layer('PhotoAmt', train_ds)
layer(photo_count_col)
<tf.Tensor: shape=(5, 1), dtype=float32, numpy=
array([[-0.8272058 ],
       [-0.19125296],
       [ 1.3986291 ],
       [-0.19125296],
       [-0.50922936]], dtype=float32)>

ستون های طبقه بندی شده

Type Pet در مجموعه داده به صورت رشته‌هایی نمایش داده می‌شود - Dog و Cat - که باید قبل از وارد شدن به مدل کدگذاری شوند. ویژگی Age

یک تابع ابزار جدید دیگر را تعریف کنید که لایه ای را برمی گرداند که مقادیر را از واژگان به شاخص های عدد صحیح نگاشت و ویژگی ها را با استفاده از tf.keras.layers.StringLookup ، tf.keras.layers.IntegerLookup و tf.keras.CategoryEncoding می کند. لایه های:

def get_category_encoding_layer(name, dataset, dtype, max_tokens=None):
  # Create a layer that turns strings into integer indices.
  if dtype == 'string':
    index = layers.StringLookup(max_tokens=max_tokens)
  # Otherwise, create a layer that turns integer values into integer indices.
  else:
    index = layers.IntegerLookup(max_tokens=max_tokens)

  # Prepare a `tf.data.Dataset` that only yields the feature.
  feature_ds = dataset.map(lambda x, y: x[name])

  # Learn the set of possible values and assign them a fixed integer index.
  index.adapt(feature_ds)

  # Encode the integer indices.
  encoder = layers.CategoryEncoding(num_tokens=index.vocabulary_size())

  # Apply multi-hot encoding to the indices. The lambda function captures the
  # layer, so you can use them, or include them in the Keras Functional model later.
  return lambda feature: encoder(index(feature))

تابع get_category_encoding_layer را با فراخوانی آن روی ویژگی‌های 'Type' آزمایش کنید تا آن‌ها را به تانسورهای رمزگذاری شده چند داغ تبدیل کنید:

test_type_col = train_features['Type']
test_type_layer = get_category_encoding_layer(name='Type',
                                              dataset=train_ds,
                                              dtype='string')
test_type_layer(test_type_col)
<tf.Tensor: shape=(5, 3), dtype=float32, numpy=
array([[0., 1., 0.],
       [0., 1., 0.],
       [0., 1., 0.],
       [0., 1., 0.],
       [0., 1., 0.]], dtype=float32)>

این روند را در ویژگی های 'Age' حیوان خانگی تکرار کنید:

test_age_col = train_features['Age']
test_age_layer = get_category_encoding_layer(name='Age',
                                             dataset=train_ds,
                                             dtype='int64',
                                             max_tokens=5)
test_age_layer(test_age_col)
<tf.Tensor: shape=(5, 5), dtype=float32, numpy=
array([[1., 0., 0., 0., 0.],
       [0., 0., 0., 1., 0.],
       [1., 0., 0., 0., 0.],
       [0., 0., 0., 1., 0.],
       [1., 0., 0., 0., 0.]], dtype=float32)>

ویژگی های انتخاب شده را برای آموزش مدل بر روی آن از قبل پردازش کنید

شما یاد گرفته اید که چگونه از چندین نوع لایه پیش پردازش Keras استفاده کنید. در مرحله بعد، شما:

  • توابع ابزار پیش پردازش را که قبلاً در 13 ویژگی عددی و دسته بندی از مجموعه داده کوچک PetFinder.my تعریف شده است، اعمال کنید.
  • تمام ورودی های ویژگی را به یک لیست اضافه کنید.

همانطور که در ابتدا ذکر شد، برای آموزش مدل، از مجموعه داده‌های کوچک PetFinder.my از عددی ( 'PhotoAmt' , 'Fee' ) و دسته‌بندی ( 'Age' Sage', ' 'Type' ', 'Color1' Color1', 'Color2 'Color2' , 'Gender' استفاده خواهید کرد. ویژگی‌های 'Gender' ، 'MaturitySize' ، 'FurLength' ، 'Vaccinated' ، «عقیم‌شده 'Sterilized' ، 'Health' ، 'Breed1' ).

قبلاً از یک اندازه دسته کوچک برای نشان دادن خط لوله ورودی استفاده می کردید. بیایید اکنون یک خط لوله ورودی جدید با اندازه دسته ای بزرگتر 256 ایجاد کنیم:

batch_size = 256
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)
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:4: FutureWarning: Support for multi-dimensional indexing (e.g. `obj[:, None]`) is deprecated and will be removed in a future version.  Convert to a numpy array before indexing instead.
  after removing the cwd from sys.path.

ویژگی‌های عددی (تعداد عکس‌های حیوان خانگی و هزینه پذیرش) را عادی کنید و آنها را به فهرستی از ورودی‌ها به نام encoded_features :

all_inputs = []
encoded_features = []

# Numerical features.
for header in ['PhotoAmt', 'Fee']:
  numeric_col = tf.keras.Input(shape=(1,), name=header)
  normalization_layer = get_normalization_layer(header, train_ds)
  encoded_numeric_col = normalization_layer(numeric_col)
  all_inputs.append(numeric_col)
  encoded_features.append(encoded_numeric_col)

مقادیر مقوله‌ای اعداد صحیح از مجموعه داده (سن حیوان خانگی) را به شاخص‌های صحیح تبدیل کنید، کدگذاری چندگانه را انجام دهید و ورودی‌های ویژگی حاصل را به encoded_features کنید:

age_col = tf.keras.Input(shape=(1,), name='Age', dtype='int64')

encoding_layer = get_category_encoding_layer(name='Age',
                                             dataset=train_ds,
                                             dtype='int64',
                                             max_tokens=5)
encoded_age_col = encoding_layer(age_col)
all_inputs.append(age_col)
encoded_features.append(encoded_age_col)

همین مرحله را برای مقادیر دسته بندی رشته تکرار کنید:

categorical_cols = ['Type', 'Color1', 'Color2', 'Gender', 'MaturitySize',
                    'FurLength', 'Vaccinated', 'Sterilized', 'Health', 'Breed1']

for header in categorical_cols:
  categorical_col = tf.keras.Input(shape=(1,), name=header, dtype='string')
  encoding_layer = get_category_encoding_layer(name=header,
                                               dataset=train_ds,
                                               dtype='string',
                                               max_tokens=5)
  encoded_categorical_col = encoding_layer(categorical_col)
  all_inputs.append(categorical_col)
  encoded_features.append(encoded_categorical_col)

مدل را ایجاد، کامپایل و آموزش دهید

مرحله بعدی ایجاد یک مدل با استفاده از Keras Functional API است. برای اولین لایه در مدل خود، لیست ورودی های ویژگی - encoded_features - را از طریق الحاق با tf.keras.layers.concatenate در یک بردار ادغام کنید.

all_features = tf.keras.layers.concatenate(encoded_features)
x = tf.keras.layers.Dense(32, activation="relu")(all_features)
x = tf.keras.layers.Dropout(0.5)(x)
output = tf.keras.layers.Dense(1)(x)

model = tf.keras.Model(all_inputs, output)

مدل را با Keras Model.compile کنید:

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

بیایید نمودار اتصال را تجسم کنیم:

# Use `rankdir='LR'` to make the graph horizontal.
tf.keras.utils.plot_model(model, show_shapes=True, rankdir="LR")

png

سپس، مدل را آموزش و آزمایش کنید:

model.fit(train_ds, epochs=10, validation_data=val_ds)
Epoch 1/10
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/keras/engine/functional.py:559: UserWarning: Input dict contained keys ['target'] which did not match any model input. They will be ignored by the model.
  inputs = self._flatten_to_reference_inputs(inputs)
37/37 [==============================] - 2s 19ms/step - loss: 0.6524 - accuracy: 0.5034 - val_loss: 0.5887 - val_accuracy: 0.6941
Epoch 2/10
37/37 [==============================] - 0s 8ms/step - loss: 0.5906 - accuracy: 0.6648 - val_loss: 0.5627 - val_accuracy: 0.7218
Epoch 3/10
37/37 [==============================] - 0s 8ms/step - loss: 0.5697 - accuracy: 0.6924 - val_loss: 0.5463 - val_accuracy: 0.7504
Epoch 4/10
37/37 [==============================] - 0s 8ms/step - loss: 0.5558 - accuracy: 0.6978 - val_loss: 0.5346 - val_accuracy: 0.7504
Epoch 5/10
37/37 [==============================] - 0s 8ms/step - loss: 0.5502 - accuracy: 0.7105 - val_loss: 0.5272 - val_accuracy: 0.7487
Epoch 6/10
37/37 [==============================] - 0s 8ms/step - loss: 0.5415 - accuracy: 0.7123 - val_loss: 0.5210 - val_accuracy: 0.7608
Epoch 7/10
37/37 [==============================] - 0s 8ms/step - loss: 0.5354 - accuracy: 0.7171 - val_loss: 0.5152 - val_accuracy: 0.7435
Epoch 8/10
37/37 [==============================] - 0s 8ms/step - loss: 0.5301 - accuracy: 0.7214 - val_loss: 0.5113 - val_accuracy: 0.7513
Epoch 9/10
37/37 [==============================] - 0s 8ms/step - loss: 0.5286 - accuracy: 0.7189 - val_loss: 0.5087 - val_accuracy: 0.7574
Epoch 10/10
37/37 [==============================] - 0s 8ms/step - loss: 0.5252 - accuracy: 0.7260 - val_loss: 0.5058 - val_accuracy: 0.7539
<keras.callbacks.History at 0x7f5f9fa91c50>
loss, accuracy = model.evaluate(test_ds)
print("Accuracy", accuracy)
5/5 [==============================] - 0s 6ms/step - loss: 0.5012 - accuracy: 0.7626
Accuracy 0.762565016746521

انجام استنباط

مدلی که توسعه داده‌اید اکنون می‌تواند یک ردیف از یک فایل CSV را مستقیماً پس از اینکه لایه‌های پیش‌پردازش را در خود مدل قرار دادید طبقه‌بندی کند.

اکنون می توانید مدل Keras را با Model.save و Model.load_model ذخیره و بارگذاری مجدد کنید قبل از انجام استنتاج بر روی داده های جدید:

model.save('my_pet_classifier')
reloaded_model = tf.keras.models.load_model('my_pet_classifier')
2022-01-26 06:20:08.013613: W tensorflow/python/util/util.cc:368] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.
WARNING:absl:Function `_wrapped_model` contains input name(s) PhotoAmt, Fee, Age, Type, Color1, Color2, Gender, MaturitySize, FurLength, Vaccinated, Sterilized, Health, Breed1 with unsupported characters which will be renamed to photoamt, fee, age, type, color1, color2, gender, maturitysize, furlength, vaccinated, sterilized, health, breed1 in the SavedModel.
INFO:tensorflow:Assets written to: my_pet_classifier/assets
INFO:tensorflow:Assets written to: my_pet_classifier/assets

برای به دست آوردن یک پیش بینی برای یک نمونه جدید، می توانید به سادگی با روش Keras Model.predict تماس بگیرید. فقط دو کار وجود دارد که باید انجام دهید:

  1. اسکالرها را در یک لیست قرار دهید تا یک بعد دسته ای داشته باشد ( Model فقط دسته ای از داده ها را پردازش می کند، نه نمونه های منفرد).
  2. برای هر ویژگی، tf.convert_to_tensor را فراخوانی کنید.
sample = {
    'Type': 'Cat',
    'Age': 3,
    'Breed1': 'Tabby',
    'Gender': 'Male',
    'Color1': 'Black',
    'Color2': 'White',
    'MaturitySize': 'Small',
    'FurLength': 'Short',
    'Vaccinated': 'No',
    'Sterilized': 'No',
    'Health': 'Healthy',
    'Fee': 100,
    'PhotoAmt': 2,
}

input_dict = {name: tf.convert_to_tensor([value]) for name, value in sample.items()}
predictions = reloaded_model.predict(input_dict)
prob = tf.nn.sigmoid(predictions[0])

print(
    "This particular pet had a %.1f percent probability "
    "of getting adopted." % (100 * prob)
)
This particular pet had a 77.7 percent probability of getting adopted.

مراحل بعدی

برای کسب اطلاعات بیشتر در مورد طبقه بندی داده های ساخت یافته، سعی کنید با مجموعه داده های دیگر کار کنید. برای بهبود دقت در طول آموزش و آزمایش مدل های خود، به دقت فکر کنید که کدام ویژگی ها را در مدل خود بگنجانید و چگونه باید نشان داده شوند.

در زیر چند پیشنهاد برای مجموعه داده ها آورده شده است:

  • مجموعه داده های TensorFlow: MovieLens : مجموعه ای از رتبه بندی فیلم ها از یک سرویس توصیه فیلم.
  • مجموعه داده های TensorFlow: کیفیت شراب : دو مجموعه داده مربوط به انواع قرمز و سفید شراب پرتغالی "Vinho Verde". همچنین می‌توانید مجموعه داده‌های کیفیت شراب قرمز را در Kaggle پیدا کنید.
  • Kaggle: arXiv Dataset : مجموعه ای از 1.7 میلیون مقاله علمی از arXiv که شامل فیزیک، علوم کامپیوتر، ریاضیات، آمار، مهندسی برق، زیست شناسی کمی و اقتصاد می شود.