تصنيف البيانات المهيكلة باستخدام طبقات معالجة Keras

عرض على TensorFlow.org تشغيل في Google Colab عرض المصدر على جيثب تحميل دفتر

يوضح هذا البرنامج التعليمي كيفية تصنيف البيانات المنظمة ، مثل البيانات المجدولة ، باستخدام نسخة مبسطة من مجموعة بيانات 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 هي مكتبة Python بها العديد من الأدوات المساعدة لتحميل البيانات المهيكلة والعمل معها. استخدم 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 للتنبؤ بالتبني هي توقع السرعة التي سيتم بها تبني حيوان أليف (على سبيل المثال في الأسبوع الأول والشهر الأول والأشهر الثلاثة الأولى وما إلى ذلك).

في هذا البرنامج التعليمي ، ستقوم بتبسيط المهمة عن طريق تحويلها إلى مشكلة تصنيف ثنائية ، حيث عليك ببساطة توقع ما إذا كان قد تم تبني حيوان أليف أم لا.

بعد تعديل عمود 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 إلى مجموعات تدريب وتحقق واختبار

مجموعة البيانات موجودة في إطار بيانات الباندا واحد. قسّمها إلى مجموعات تدريب وتحقق من الصحة واختبار باستخدام ، على سبيل المثال ، نسبة 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 )
placeholder14 l10n-placeholder15
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.

في هذا البرنامج التعليمي ، ستستخدم طبقات المعالجة المسبقة الأربع التالية لتوضيح كيفية إجراء المعالجة المسبقة ، وتشفير البيانات المنظمة ، وهندسة الميزات:

يمكنك معرفة المزيد حول الطبقات المتوفرة في دليل العمل مع طبقات المعالجة المسبقة .

  • بالنسبة إلى الميزات العددية لمجموعة البيانات المصغرة PetFinder.my ، سوف تستخدم tf.keras.layers.Normalization layer لتوحيد توزيع البيانات.
  • بالنسبة إلى الميزات الفئوية ، مثل Type الحيوانات الأليفة (سلاسل Dog Cat ) ، ستقوم بتحويلها إلى موترات متعددة التشفير باستخدام tf.keras.layers.CategoryEncoding .

أعمدة عددية

لكل معلم رقمي في PetFinder.my mini dataet ، سوف تستخدم tf.keras.layers.Normalization layer لتوحيد توزيع البيانات.

حدد وظيفة أداة مساعدة جديدة تقوم بإرجاع طبقة تطبق التسوية الحكيمة للميزات على الميزات العددية باستخدام طبقة المعالجة المسبقة لـ 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 s في مجموعة البيانات كسلاسل - Dog Cat - والتي تحتاج إلى تشفير متعدد السخونة قبل إدخالها في النموذج. ميزة Age

حدد وظيفة أداة مساعدة جديدة أخرى تقوم بإرجاع طبقة تقوم بتعيين القيم من المفردات إلى فهارس الأعداد الصحيحة وتشفير الخصائص المتعددة باستخدام tf.keras.layers.StringLookup و tf.keras.layers.IntegerLookup و tf.keras.CategoryEncoding preprocessing الطبقات:

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' ، 'Type' ، 'Color1' ، 'Color2' ، 'Gender' ، 'MaturitySize' 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 . بالنسبة للطبقة الأولى في النموذج الخاص بك ، قم بدمج قائمة مدخلات الميزات - المميزات المشفرة - في متجه واحد عبر tf.keras.layers.concatenate encoded_features

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")

بي إن جي

بعد ذلك ، قم بتدريب النموذج واختباره:

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

للحصول على تنبؤ لعينة جديدة ، يمكنك ببساطة استدعاء طريقة 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.

الخطوات التالية

لمعرفة المزيد حول تصنيف البيانات المنظمة ، حاول العمل مع مجموعات البيانات الأخرى. لتحسين الدقة أثناء التدريب واختبار النماذج الخاصة بك ، فكر جيدًا في الميزات التي يجب تضمينها في نموذجك وكيف ينبغي تمثيلها.

فيما يلي بعض الاقتراحات لمجموعات البيانات: