عرض على TensorFlow.org | تشغيل في Google Colab | عرض المصدر على جيثب | تحميل دفتر |
يقدم هذا البرنامج التعليمي أمثلة على كيفية تحميل إطارات بيانات الباندا في TensorFlow.
ستستخدم مجموعة بيانات صغيرة خاصة بأمراض القلب مقدمة من مستودع التعلم الآلي الخاص بالاتحاد الدولي للدراجات. هناك عدة مئات من الصفوف في ملف CSV. يصف كل صف مريضًا ، ويصف كل عمود سمة. ستستخدم هذه المعلومات للتنبؤ بما إذا كان المريض يعاني من أمراض القلب ، وهي مهمة تصنيف ثنائي.
قراءة البيانات باستخدام الباندا
import pandas as pd
import tensorflow as tf
SHUFFLE_BUFFER = 500
BATCH_SIZE = 2
قم بتنزيل ملف CSV الذي يحتوي على مجموعة بيانات أمراض القلب:
csv_file = tf.keras.utils.get_file('heart.csv', 'https://storage.googleapis.com/download.tensorflow.org/data/heart.csv')
Downloading data from https://storage.googleapis.com/download.tensorflow.org/data/heart.csv 16384/13273 [=====================================] - 0s 0us/step 24576/13273 [=======================================================] - 0s 0us/step
اقرأ ملف CSV باستخدام الباندا:
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
ستقوم ببناء نماذج للتنبؤ بالتسمية الموجودة في العمود target
.
target = df.pop('target')
DataFrame كمصفوفة
إذا كانت بياناتك تحتوي على نوع بيانات موحد ، أو نوع dtype
، فمن الممكن استخدام pandas DataFrame في أي مكان يمكنك فيه استخدام مصفوفة NumPy. يعمل هذا لأن فئة pandas.DataFrame
تدعم بروتوكول __array__
، وتقبل الدالة tf.convert_to_tensor
الخاصة بـ TensorFlow الكائنات التي تدعم البروتوكول.
خذ الميزات الرقمية من مجموعة البيانات (تخطي الميزات الفئوية في الوقت الحالي):
numeric_feature_names = ['age', 'thalach', 'trestbps', 'chol', 'oldpeak']
numeric_features = df[numeric_feature_names]
numeric_features.head()
يمكن تحويل DataFrame إلى مصفوفة DataFrame.values
باستخدام الخاصية DataFrame.values أو numpy.array(df)
. لتحويله إلى موتر ، استخدم tf.convert_to_tensor
:
tf.convert_to_tensor(numeric_features)
<tf.Tensor: shape=(303, 5), dtype=float64, numpy= array([[ 63. , 150. , 145. , 233. , 2.3], [ 67. , 108. , 160. , 286. , 1.5], [ 67. , 129. , 120. , 229. , 2.6], ..., [ 65. , 127. , 135. , 254. , 2.8], [ 48. , 150. , 130. , 256. , 0. ], [ 63. , 154. , 150. , 407. , 4. ]])>
بشكل عام ، إذا كان يمكن تحويل كائن إلى موتر باستخدام tf.convert_to_tensor
، فيمكن تمريره في أي مكان يمكنك فيه تمرير tf.Tensor
.
مع Model.fit
يمكن استخدام DataFrame ، الذي يتم تفسيره على أنه موتر واحد ، مباشرةً كوسيطة للطريقة Model.fit
.
يوجد أدناه مثال لتدريب نموذج على السمات الرقمية لمجموعة البيانات.
الخطوة الأولى هي تسوية نطاقات الإدخال. استخدم tf.keras.layers.Normalization
layer لذلك الغرض.
لتعيين متوسط الطبقة والانحراف المعياري قبل تشغيله ، تأكد من استدعاء طريقة Normalization.adapt
:
normalizer = tf.keras.layers.Normalization(axis=-1)
normalizer.adapt(numeric_features)
قم باستدعاء الطبقة الموجودة في الصفوف الثلاثة الأولى من DataFrame لتصور مثالاً للإخراج من هذه الطبقة:
normalizer(numeric_features.iloc[:3])
<tf.Tensor: shape=(3, 5), dtype=float32, numpy= array([[ 0.93383914, 0.03480718, 0.74578077, -0.26008663, 1.0680453 ], [ 1.3782105 , -1.7806165 , 1.5923285 , 0.7573877 , 0.38022864], [ 1.3782105 , -0.87290466, -0.6651321 , -0.33687714, 1.3259765 ]], dtype=float32)>
استخدم طبقة التسوية كطبقة أولى لنموذج بسيط:
def get_basic_model():
model = tf.keras.Sequential([
normalizer,
tf.keras.layers.Dense(10, activation='relu'),
tf.keras.layers.Dense(10, activation='relu'),
tf.keras.layers.Dense(1)
])
model.compile(optimizer='adam',
loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
metrics=['accuracy'])
return model
عند تمرير DataFrame كوسيطة x
إلى Model.fit
، يتعامل Keras مع DataFrame كما لو كان مصفوفة NumPy:
model = get_basic_model()
model.fit(numeric_features, target, epochs=15, batch_size=BATCH_SIZE)
Epoch 1/15 152/152 [==============================] - 1s 2ms/step - loss: 0.6839 - accuracy: 0.7690 Epoch 2/15 152/152 [==============================] - 0s 2ms/step - loss: 0.5789 - accuracy: 0.7789 Epoch 3/15 152/152 [==============================] - 0s 2ms/step - loss: 0.5195 - accuracy: 0.7723 Epoch 4/15 152/152 [==============================] - 0s 2ms/step - loss: 0.4814 - accuracy: 0.7855 Epoch 5/15 152/152 [==============================] - 0s 2ms/step - loss: 0.4566 - accuracy: 0.7789 Epoch 6/15 152/152 [==============================] - 0s 2ms/step - loss: 0.4427 - accuracy: 0.7888 Epoch 7/15 152/152 [==============================] - 0s 2ms/step - loss: 0.4342 - accuracy: 0.7921 Epoch 8/15 152/152 [==============================] - 0s 2ms/step - loss: 0.4290 - accuracy: 0.7855 Epoch 9/15 152/152 [==============================] - 0s 2ms/step - loss: 0.4240 - accuracy: 0.7987 Epoch 10/15 152/152 [==============================] - 0s 2ms/step - loss: 0.4232 - accuracy: 0.7987 Epoch 11/15 152/152 [==============================] - 0s 2ms/step - loss: 0.4208 - accuracy: 0.7987 Epoch 12/15 152/152 [==============================] - 0s 2ms/step - loss: 0.4186 - accuracy: 0.7954 Epoch 13/15 152/152 [==============================] - 0s 2ms/step - loss: 0.4172 - accuracy: 0.8020 Epoch 14/15 152/152 [==============================] - 0s 2ms/step - loss: 0.4156 - accuracy: 0.8020 Epoch 15/15 152/152 [==============================] - 0s 2ms/step - loss: 0.4138 - accuracy: 0.8020 <keras.callbacks.History at 0x7f1ddc27b110>
مع tf.data
إذا كنت تريد تطبيق تحويلات tf.data
على DataFrame من نوع dtype موحد ، فإن طريقة dtype
Dataset.from_tensor_slices
مجموعة بيانات تتكرر عبر صفوف DataFrame. كل صف هو في البداية متجه من القيم. لتدريب نموذج ، تحتاج إلى أزواج (inputs, labels)
، لذا قم بتمرير (features, labels)
Dataset.from_tensor_slices
بإرجاع أزواج الشرائح المطلوبة:
numeric_dataset = tf.data.Dataset.from_tensor_slices((numeric_features, target))
for row in numeric_dataset.take(3):
print(row)
(<tf.Tensor: shape=(5,), dtype=float64, numpy=array([ 63. , 150. , 145. , 233. , 2.3])>, <tf.Tensor: shape=(), dtype=int64, numpy=0>) (<tf.Tensor: shape=(5,), dtype=float64, numpy=array([ 67. , 108. , 160. , 286. , 1.5])>, <tf.Tensor: shape=(), dtype=int64, numpy=1>) (<tf.Tensor: shape=(5,), dtype=float64, numpy=array([ 67. , 129. , 120. , 229. , 2.6])>, <tf.Tensor: shape=(), dtype=int64, numpy=0>)
numeric_batches = numeric_dataset.shuffle(1000).batch(BATCH_SIZE)
model = get_basic_model()
model.fit(numeric_batches, epochs=15)
Epoch 1/15 152/152 [==============================] - 1s 2ms/step - loss: 0.7677 - accuracy: 0.6865 Epoch 2/15 152/152 [==============================] - 0s 2ms/step - loss: 0.6319 - accuracy: 0.7591 Epoch 3/15 152/152 [==============================] - 0s 2ms/step - loss: 0.5717 - accuracy: 0.7459 Epoch 4/15 152/152 [==============================] - 0s 2ms/step - loss: 0.5228 - accuracy: 0.7558 Epoch 5/15 152/152 [==============================] - 0s 2ms/step - loss: 0.4820 - accuracy: 0.7624 Epoch 6/15 152/152 [==============================] - 0s 2ms/step - loss: 0.4584 - accuracy: 0.7657 Epoch 7/15 152/152 [==============================] - 0s 2ms/step - loss: 0.4454 - accuracy: 0.7657 Epoch 8/15 152/152 [==============================] - 0s 2ms/step - loss: 0.4379 - accuracy: 0.7789 Epoch 9/15 152/152 [==============================] - 0s 2ms/step - loss: 0.4324 - accuracy: 0.7789 Epoch 10/15 152/152 [==============================] - 0s 2ms/step - loss: 0.4282 - accuracy: 0.7756 Epoch 11/15 152/152 [==============================] - 0s 2ms/step - loss: 0.4273 - accuracy: 0.7789 Epoch 12/15 152/152 [==============================] - 0s 2ms/step - loss: 0.4268 - accuracy: 0.7756 Epoch 13/15 152/152 [==============================] - 0s 2ms/step - loss: 0.4248 - accuracy: 0.7789 Epoch 14/15 152/152 [==============================] - 0s 2ms/step - loss: 0.4235 - accuracy: 0.7855 Epoch 15/15 152/152 [==============================] - 0s 2ms/step - loss: 0.4223 - accuracy: 0.7888 <keras.callbacks.History at 0x7f1ddc406510>
A DataFrame بمثابة قاموس
عندما تبدأ في التعامل مع البيانات غير المتجانسة ، لم يعد من الممكن التعامل مع DataFrame كما لو كان مصفوفة واحدة. تتطلب موترات TensorFlow أن يكون لجميع العناصر نفس dtype
.
لذلك ، في هذه الحالة ، تحتاج إلى البدء في معاملته كقاموس للأعمدة ، حيث يحتوي كل عمود على نوع موحد. يشبه DataFrame إلى حد كبير قاموس المصفوفات ، لذا فعادة ما يكون كل ما عليك فعله هو إرسال DataFrame إلى ملف Python. تدعم العديد من واجهات برمجة تطبيقات TensorFlow الهامة (المتداخلة) قواميس المصفوفات كمدخلات.
تتعامل خطوط أنابيب الإدخال tf.data
مع هذا الأمر جيدًا. تتعامل جميع عمليات tf.data
مع القواميس والمجموعات تلقائيًا. لذلك ، لإنشاء مجموعة بيانات لأمثلة من القاموس من DataFrame ، ما عليك سوى نقلها إلى dict قبل تقطيعها باستخدام Dataset.from_tensor_slices
:
numeric_dict_ds = tf.data.Dataset.from_tensor_slices((dict(numeric_features), target))
فيما يلي الأمثلة الثلاثة الأولى من مجموعة البيانات هذه:
for row in numeric_dict_ds.take(3):
print(row)
({'age': <tf.Tensor: shape=(), dtype=int64, numpy=63>, 'thalach': <tf.Tensor: shape=(), dtype=int64, numpy=150>, 'trestbps': <tf.Tensor: shape=(), dtype=int64, numpy=145>, 'chol': <tf.Tensor: shape=(), dtype=int64, numpy=233>, 'oldpeak': <tf.Tensor: shape=(), dtype=float64, numpy=2.3>}, <tf.Tensor: shape=(), dtype=int64, numpy=0>) ({'age': <tf.Tensor: shape=(), dtype=int64, numpy=67>, 'thalach': <tf.Tensor: shape=(), dtype=int64, numpy=108>, 'trestbps': <tf.Tensor: shape=(), dtype=int64, numpy=160>, 'chol': <tf.Tensor: shape=(), dtype=int64, numpy=286>, 'oldpeak': <tf.Tensor: shape=(), dtype=float64, numpy=1.5>}, <tf.Tensor: shape=(), dtype=int64, numpy=1>) ({'age': <tf.Tensor: shape=(), dtype=int64, numpy=67>, 'thalach': <tf.Tensor: shape=(), dtype=int64, numpy=129>, 'trestbps': <tf.Tensor: shape=(), dtype=int64, numpy=120>, 'chol': <tf.Tensor: shape=(), dtype=int64, numpy=229>, 'oldpeak': <tf.Tensor: shape=(), dtype=float64, numpy=2.6>}, <tf.Tensor: shape=(), dtype=int64, numpy=0>)
قواميس مع Keras
عادةً ما تتوقع نماذج وطبقات Keras وجود موتر إدخال فردي ، ولكن يمكن لهذه الفئات قبول وإرجاع الهياكل المتداخلة للقواميس ، و tuples ، و tensors. تُعرف هذه الهياكل باسم "الأعشاش" (راجع الوحدة النمطية tf.nest
للحصول على التفاصيل).
هناك طريقتان مكافئتان لكتابة نموذج keras يقبل القاموس كمدخلات.
1. نمط الفئة الفرعية النموذجية
تكتب فئة فرعية من tf.keras.Model
(أو tf.keras.Layer
). أنت تتعامل مباشرة مع المدخلات ، وتقوم بإنشاء المخرجات:
def stack_dict(inputs, fun=tf.stack):
values = []
for key in sorted(inputs.keys()):
values.append(tf.cast(inputs[key], tf.float32))
return fun(values, axis=-1)
class MyModel(tf.keras.Model):
def __init__(self):
# Create all the internal layers in init.
super().__init__(self)
self.normalizer = tf.keras.layers.Normalization(axis=-1)
self.seq = tf.keras.Sequential([
self.normalizer,
tf.keras.layers.Dense(10, activation='relu'),
tf.keras.layers.Dense(10, activation='relu'),
tf.keras.layers.Dense(1)
])
def adapt(self, inputs):
# Stach the inputs and `adapt` the normalization layer.
inputs = stack_dict(inputs)
self.normalizer.adapt(inputs)
def call(self, inputs):
# Stack the inputs
inputs = stack_dict(inputs)
# Run them through all the layers.
result = self.seq(inputs)
return result
model = MyModel()
model.adapt(dict(numeric_features))
model.compile(optimizer='adam',
loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
metrics=['accuracy'],
run_eagerly=True)
يمكن لهذا النموذج أن يقبل إما قاموس الأعمدة أو مجموعة بيانات من عناصر القاموس للتدريب:
model.fit(dict(numeric_features), target, epochs=5, batch_size=BATCH_SIZE)
Epoch 1/5 152/152 [==============================] - 3s 17ms/step - loss: 0.6736 - accuracy: 0.7063 Epoch 2/5 152/152 [==============================] - 3s 17ms/step - loss: 0.5577 - accuracy: 0.7294 Epoch 3/5 152/152 [==============================] - 2s 16ms/step - loss: 0.4869 - accuracy: 0.7591 Epoch 4/5 152/152 [==============================] - 2s 16ms/step - loss: 0.4525 - accuracy: 0.7690 Epoch 5/5 152/152 [==============================] - 2s 16ms/step - loss: 0.4403 - accuracy: 0.7624 <keras.callbacks.History at 0x7f1de4fa9390>
numeric_dict_batches = numeric_dict_ds.shuffle(SHUFFLE_BUFFER).batch(BATCH_SIZE)
model.fit(numeric_dict_batches, epochs=5)
Epoch 1/5 152/152 [==============================] - 2s 15ms/step - loss: 0.4328 - accuracy: 0.7756 Epoch 2/5 152/152 [==============================] - 2s 14ms/step - loss: 0.4297 - accuracy: 0.7888 Epoch 3/5 152/152 [==============================] - 2s 15ms/step - loss: 0.4270 - accuracy: 0.7888 Epoch 4/5 152/152 [==============================] - 2s 15ms/step - loss: 0.4245 - accuracy: 0.8020 Epoch 5/5 152/152 [==============================] - 2s 15ms/step - loss: 0.4240 - accuracy: 0.7921 <keras.callbacks.History at 0x7f1ddc0dba90>
فيما يلي تنبؤات الأمثلة الثلاثة الأولى:
model.predict(dict(numeric_features.iloc[:3]))
array([[[0.00565109]], [[0.60601974]], [[0.03647463]]], dtype=float32)
2. أسلوب Keras الوظيفي
inputs = {}
for name, column in numeric_features.items():
inputs[name] = tf.keras.Input(
shape=(1,), name=name, dtype=tf.float32)
inputs
{'age': <KerasTensor: shape=(None, 1) dtype=float32 (created by layer 'age')>, 'thalach': <KerasTensor: shape=(None, 1) dtype=float32 (created by layer 'thalach')>, 'trestbps': <KerasTensor: shape=(None, 1) dtype=float32 (created by layer 'trestbps')>, 'chol': <KerasTensor: shape=(None, 1) dtype=float32 (created by layer 'chol')>, 'oldpeak': <KerasTensor: shape=(None, 1) dtype=float32 (created by layer 'oldpeak')>}
x = stack_dict(inputs, fun=tf.concat)
normalizer = tf.keras.layers.Normalization(axis=-1)
normalizer.adapt(stack_dict(dict(numeric_features)))
x = normalizer(x)
x = tf.keras.layers.Dense(10, activation='relu')(x)
x = tf.keras.layers.Dense(10, activation='relu')(x)
x = tf.keras.layers.Dense(1)(x)
model = tf.keras.Model(inputs, x)
model.compile(optimizer='adam',
loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
metrics=['accuracy'],
run_eagerly=True)
tf.keras.utils.plot_model(model, rankdir="LR", show_shapes=True)
يمكنك تدريب النموذج الوظيفي بنفس طريقة تدريب الفئة الفرعية للنموذج:
model.fit(dict(numeric_features), target, epochs=5, batch_size=BATCH_SIZE)
Epoch 1/5 152/152 [==============================] - 2s 15ms/step - loss: 0.6529 - accuracy: 0.7492 Epoch 2/5 152/152 [==============================] - 2s 15ms/step - loss: 0.5448 - accuracy: 0.7624 Epoch 3/5 152/152 [==============================] - 2s 15ms/step - loss: 0.4935 - accuracy: 0.7756 Epoch 4/5 152/152 [==============================] - 2s 15ms/step - loss: 0.4650 - accuracy: 0.7789 Epoch 5/5 152/152 [==============================] - 2s 15ms/step - loss: 0.4486 - accuracy: 0.7855 <keras.callbacks.History at 0x7f1ddc0d0f90>
numeric_dict_batches = numeric_dict_ds.shuffle(SHUFFLE_BUFFER).batch(BATCH_SIZE)
model.fit(numeric_dict_batches, epochs=5)
Epoch 1/5 152/152 [==============================] - 2s 15ms/step - loss: 0.4398 - accuracy: 0.7855 Epoch 2/5 152/152 [==============================] - 2s 15ms/step - loss: 0.4330 - accuracy: 0.7855 Epoch 3/5 152/152 [==============================] - 2s 16ms/step - loss: 0.4294 - accuracy: 0.7921 Epoch 4/5 152/152 [==============================] - 2s 16ms/step - loss: 0.4271 - accuracy: 0.7888 Epoch 5/5 152/152 [==============================] - 2s 16ms/step - loss: 0.4231 - accuracy: 0.7855 <keras.callbacks.History at 0x7f1d7c5d5d10>
المثال الكامل
إذا قمت بتمرير DataFrame
غير متجانس إلى Keras ، فقد يحتاج كل عمود إلى معالجة مسبقة فريدة. يمكنك إجراء هذه المعالجة المسبقة مباشرةً في DataFrame ، ولكن لكي يعمل النموذج بشكل صحيح ، تحتاج المدخلات دائمًا إلى المعالجة المسبقة بنفس الطريقة. لذلك ، فإن أفضل نهج هو بناء المعالجة المسبقة في النموذج. تغطي طبقات Keras المسبقة المعالجة العديد من المهام الشائعة.
بناء رأس المعالجة المسبقة
في مجموعة البيانات هذه ، بعض ميزات "العدد الصحيح" في البيانات الأولية هي في الواقع مؤشرات فئوية. هذه المؤشرات ليست قيمًا رقمية مرتبة بالفعل (راجع وصف مجموعة البيانات للحصول على التفاصيل). لأن هذه غير مرتبة ، فهي غير مناسبة لتغذية النموذج مباشرة ؛ النموذج سوف يفسرها على أنها مرتبة. لاستخدام هذه المدخلات ، ستحتاج إلى ترميزها ، إما كمتجهات واحدة أو متجهات تضمين. الأمر نفسه ينطبق على السمات الفئوية.
من ناحية أخرى ، لا تحتاج الميزات الثنائية عمومًا إلى الترميز أو التسوية.
ابدأ بإنشاء قائمة بالميزات التي تقع في كل مجموعة:
binary_feature_names = ['sex', 'fbs', 'exang']
categorical_feature_names = ['cp', 'restecg', 'slope', 'thal', 'ca']
تتمثل الخطوة التالية في بناء نموذج معالجة مسبقة يطبق معالجة مسبقة مناسبة لكل مدخل على كل مدخل ويربط النتائج.
يستخدم هذا القسم واجهة برمجة تطبيقات Keras الوظيفية لتنفيذ المعالجة المسبقة. تبدأ بإنشاء tf.keras.Input
واحد لكل عمود من أعمدة البيانات:
inputs = {}
for name, column in df.items():
if type(column[0]) == str:
dtype = tf.string
elif (name in categorical_feature_names or
name in binary_feature_names):
dtype = tf.int64
else:
dtype = tf.float32
inputs[name] = tf.keras.Input(shape=(), name=name, dtype=dtype)
inputs
{'age': <KerasTensor: shape=(None,) dtype=float32 (created by layer 'age')>, 'sex': <KerasTensor: shape=(None,) dtype=int64 (created by layer 'sex')>, 'cp': <KerasTensor: shape=(None,) dtype=int64 (created by layer 'cp')>, 'trestbps': <KerasTensor: shape=(None,) dtype=float32 (created by layer 'trestbps')>, 'chol': <KerasTensor: shape=(None,) dtype=float32 (created by layer 'chol')>, 'fbs': <KerasTensor: shape=(None,) dtype=int64 (created by layer 'fbs')>, 'restecg': <KerasTensor: shape=(None,) dtype=int64 (created by layer 'restecg')>, 'thalach': <KerasTensor: shape=(None,) dtype=float32 (created by layer 'thalach')>, 'exang': <KerasTensor: shape=(None,) dtype=int64 (created by layer 'exang')>, 'oldpeak': <KerasTensor: shape=(None,) dtype=float32 (created by layer 'oldpeak')>, 'slope': <KerasTensor: shape=(None,) dtype=int64 (created by layer 'slope')>, 'ca': <KerasTensor: shape=(None,) dtype=int64 (created by layer 'ca')>, 'thal': <KerasTensor: shape=(None,) dtype=string (created by layer 'thal')>}
لكل إدخال ، ستقوم بتطبيق بعض التحويلات باستخدام طبقات Keras و TensorFlow ops. تبدأ كل ميزة كدفعة من الحجميات ( shape=(batch,)
). يجب أن يكون ناتج كل مجموعة من متجهات tf.float32
( shape=(batch, n)
). ستجمع الخطوة الأخيرة كل هذه النواقل معًا.
المدخلات الثنائية
نظرًا لأن المدخلات الثنائية لا تحتاج إلى أي معالجة مسبقة ، فما عليك سوى إضافة محور المتجه ، ثم تحويلها إلى float32
وإضافتها إلى قائمة المدخلات المعالجة مسبقًا:
preprocessed = []
for name in binary_feature_names:
inp = inputs[name]
inp = inp[:, tf.newaxis]
float_value = tf.cast(inp, tf.float32)
preprocessed.append(float_value)
preprocessed
[<KerasTensor: shape=(None, 1) dtype=float32 (created by layer 'tf.cast_5')>, <KerasTensor: shape=(None, 1) dtype=float32 (created by layer 'tf.cast_6')>, <KerasTensor: shape=(None, 1) dtype=float32 (created by layer 'tf.cast_7')>]
المدخلات الرقمية
كما في القسم السابق ، سترغب في تشغيل هذه المدخلات الرقمية من خلال طبقة tf.keras.layers.Normalization
قبل استخدامها. الفرق هو أنهم هذه المرة يتم إدخالهم كإملاء. يجمع الكود أدناه الميزات الرقمية من DataFrame ، ويجمعها معًا ويمررها إلى طريقة Normalization.adapt
.
normalizer = tf.keras.layers.Normalization(axis=-1)
normalizer.adapt(stack_dict(dict(numeric_features)))
يقوم الكود أدناه بتكديس الميزات الرقمية وتشغيلها خلال طبقة التسوية.
numeric_inputs = {}
for name in numeric_feature_names:
numeric_inputs[name]=inputs[name]
numeric_inputs = stack_dict(numeric_inputs)
numeric_normalized = normalizer(numeric_inputs)
preprocessed.append(numeric_normalized)
preprocessed
[<KerasTensor: shape=(None, 1) dtype=float32 (created by layer 'tf.cast_5')>, <KerasTensor: shape=(None, 1) dtype=float32 (created by layer 'tf.cast_6')>, <KerasTensor: shape=(None, 1) dtype=float32 (created by layer 'tf.cast_7')>, <KerasTensor: shape=(None, 5) dtype=float32 (created by layer 'normalization_3')>]
الميزات الفئوية
لاستخدام الميزات الفئوية ، ستحتاج أولاً إلى ترميزها إما في متجهات ثنائية أو في حفلات الزفاف. نظرًا لأن هذه الميزات تحتوي فقط على عدد صغير من الفئات ، قم بتحويل المدخلات مباشرة إلى متجهات واحدة ساخنة باستخدام خيار output_mode='one_hot'
، المدعوم من قبل كل من طبقات tf.keras.layers.StringLookup
و tf.keras.layers.IntegerLookup
.
فيما يلي مثال على كيفية عمل هذه الطبقات:
vocab = ['a','b','c']
lookup = tf.keras.layers.StringLookup(vocabulary=vocab, output_mode='one_hot')
lookup(['c','a','a','b','zzz'])
<tf.Tensor: shape=(5, 4), dtype=float32, numpy= array([[0., 0., 0., 1.], [0., 1., 0., 0.], [0., 1., 0., 0.], [0., 0., 1., 0.], [1., 0., 0., 0.]], dtype=float32)>
vocab = [1,4,7,99]
lookup = tf.keras.layers.IntegerLookup(vocabulary=vocab, output_mode='one_hot')
lookup([-1,4,1])
<tf.Tensor: shape=(3, 5), dtype=float32, numpy= array([[1., 0., 0., 0., 0.], [0., 0., 1., 0., 0.], [0., 1., 0., 0., 0.]], dtype=float32)>
لتحديد المفردات لكل إدخال ، قم بإنشاء طبقة لتحويل تلك المفردات إلى متجه واحد ساخن:
for name in categorical_feature_names:
vocab = sorted(set(df[name]))
print(f'name: {name}')
print(f'vocab: {vocab}\n')
if type(vocab[0]) is str:
lookup = tf.keras.layers.StringLookup(vocabulary=vocab, output_mode='one_hot')
else:
lookup = tf.keras.layers.IntegerLookup(vocabulary=vocab, output_mode='one_hot')
x = inputs[name][:, tf.newaxis]
x = lookup(x)
preprocessed.append(x)
name: cp vocab: [0, 1, 2, 3, 4] name: restecg vocab: [0, 1, 2] name: slope vocab: [1, 2, 3] name: thal vocab: ['1', '2', 'fixed', 'normal', 'reversible'] name: ca vocab: [0, 1, 2, 3]
قم بتجميع رأس المعالجة المسبقة
في هذه المرحلة ، تكون preprocessed
مجرد قائمة Python لجميع نتائج المعالجة المسبقة ، ولكل نتيجة شكل (batch_size, depth)
:
preprocessed
[<KerasTensor: shape=(None, 1) dtype=float32 (created by layer 'tf.cast_5')>, <KerasTensor: shape=(None, 1) dtype=float32 (created by layer 'tf.cast_6')>, <KerasTensor: shape=(None, 1) dtype=float32 (created by layer 'tf.cast_7')>, <KerasTensor: shape=(None, 5) dtype=float32 (created by layer 'normalization_3')>, <KerasTensor: shape=(None, 6) dtype=float32 (created by layer 'integer_lookup_1')>, <KerasTensor: shape=(None, 4) dtype=float32 (created by layer 'integer_lookup_2')>, <KerasTensor: shape=(None, 4) dtype=float32 (created by layer 'integer_lookup_3')>, <KerasTensor: shape=(None, 6) dtype=float32 (created by layer 'string_lookup_1')>, <KerasTensor: shape=(None, 5) dtype=float32 (created by layer 'integer_lookup_4')>]
اربط جميع الميزات المعالجة مسبقًا على طول محور depth
، بحيث يتم تحويل كل مثال من القاموس إلى متجه واحد. يحتوي المتجه على ميزات فئوية وميزات رقمية وميزات فئوية واحدة ساخنة:
preprocesssed_result = tf.concat(preprocessed, axis=-1)
preprocesssed_result
<KerasTensor: shape=(None, 33) dtype=float32 (created by layer 'tf.concat_1')>
الآن قم بإنشاء نموذج من هذا الحساب حتى يمكن إعادة استخدامه:
preprocessor = tf.keras.Model(inputs, preprocesssed_result)
tf.keras.utils.plot_model(preprocessor, rankdir="LR", show_shapes=True)
لاختبار المعالج المسبق ، استخدم الموصل DataFrame.iloc لتقطيع المثال الأول من DataFrame. ثم قم بتحويله إلى قاموس وقم بتمرير القاموس إلى المعالج المسبق. والنتيجة هي متجه واحد يحتوي على السمات الثنائية ، والسمات الرقمية الطبيعية والميزات الفئوية الساخنة ، بالترتيب التالي:
preprocessor(dict(df.iloc[:1]))
<tf.Tensor: shape=(1, 33), dtype=float32, numpy= array([[ 1. , 1. , 0. , 0.93383914, -0.26008663, 1.0680453 , 0.03480718, 0.74578077, 0. , 0. , 1. , 0. , 0. , 0. , 0. , 0. , 0. , 1. , 0. , 0. , 0. , 1. , 0. , 0. , 0. , 1. , 0. , 0. , 0. , 1. , 0. , 0. , 0. ]], dtype=float32)>
إنشاء وتدريب نموذج
الآن قم ببناء الجسم الرئيسي للنموذج. استخدم نفس التكوين كما في المثال السابق: زوجان من طبقات خطية مصححة Dense
وطبقة إخراج Dense(1)
للتصنيف.
body = tf.keras.Sequential([
tf.keras.layers.Dense(10, activation='relu'),
tf.keras.layers.Dense(10, activation='relu'),
tf.keras.layers.Dense(1)
])
الآن ضع القطعتين معًا باستخدام واجهة برمجة تطبيقات Keras الوظيفية.
inputs
{'age': <KerasTensor: shape=(None,) dtype=float32 (created by layer 'age')>, 'sex': <KerasTensor: shape=(None,) dtype=int64 (created by layer 'sex')>, 'cp': <KerasTensor: shape=(None,) dtype=int64 (created by layer 'cp')>, 'trestbps': <KerasTensor: shape=(None,) dtype=float32 (created by layer 'trestbps')>, 'chol': <KerasTensor: shape=(None,) dtype=float32 (created by layer 'chol')>, 'fbs': <KerasTensor: shape=(None,) dtype=int64 (created by layer 'fbs')>, 'restecg': <KerasTensor: shape=(None,) dtype=int64 (created by layer 'restecg')>, 'thalach': <KerasTensor: shape=(None,) dtype=float32 (created by layer 'thalach')>, 'exang': <KerasTensor: shape=(None,) dtype=int64 (created by layer 'exang')>, 'oldpeak': <KerasTensor: shape=(None,) dtype=float32 (created by layer 'oldpeak')>, 'slope': <KerasTensor: shape=(None,) dtype=int64 (created by layer 'slope')>, 'ca': <KerasTensor: shape=(None,) dtype=int64 (created by layer 'ca')>, 'thal': <KerasTensor: shape=(None,) dtype=string (created by layer 'thal')>}
x = preprocessor(inputs)
x
<KerasTensor: shape=(None, 33) dtype=float32 (created by layer 'model_1')>
result = body(x)
result
<KerasTensor: shape=(None, 1) dtype=float32 (created by layer 'sequential_3')>
model = tf.keras.Model(inputs, result)
model.compile(optimizer='adam',
loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
metrics=['accuracy'])
يتوقع هذا النموذج قاموس المدخلات. إن أبسط طريقة لتمرير البيانات هي تحويل DataFrame إلى ديكت وتمرير هذا الأمر كمعامل x
إلى Model.fit
:
history = model.fit(dict(df), target, epochs=5, batch_size=BATCH_SIZE)
Epoch 1/5 152/152 [==============================] - 1s 4ms/step - loss: 0.6911 - accuracy: 0.6997 Epoch 2/5 152/152 [==============================] - 1s 4ms/step - loss: 0.5073 - accuracy: 0.7393 Epoch 3/5 152/152 [==============================] - 1s 4ms/step - loss: 0.4129 - accuracy: 0.7888 Epoch 4/5 152/152 [==============================] - 1s 4ms/step - loss: 0.3663 - accuracy: 0.7921 Epoch 5/5 152/152 [==============================] - 1s 4ms/step - loss: 0.3363 - accuracy: 0.8152
يعمل استخدام tf.data
أيضًا:
ds = tf.data.Dataset.from_tensor_slices((
dict(df),
target
))
ds = ds.batch(BATCH_SIZE)
import pprint
for x, y in ds.take(1):
pprint.pprint(x)
print()
print(y)
{'age': <tf.Tensor: shape=(2,), dtype=int64, numpy=array([63, 67])>, 'ca': <tf.Tensor: shape=(2,), dtype=int64, numpy=array([0, 3])>, 'chol': <tf.Tensor: shape=(2,), dtype=int64, numpy=array([233, 286])>, 'cp': <tf.Tensor: shape=(2,), dtype=int64, numpy=array([1, 4])>, 'exang': <tf.Tensor: shape=(2,), dtype=int64, numpy=array([0, 1])>, 'fbs': <tf.Tensor: shape=(2,), dtype=int64, numpy=array([1, 0])>, 'oldpeak': <tf.Tensor: shape=(2,), dtype=float64, numpy=array([2.3, 1.5])>, 'restecg': <tf.Tensor: shape=(2,), dtype=int64, numpy=array([2, 2])>, 'sex': <tf.Tensor: shape=(2,), dtype=int64, numpy=array([1, 1])>, 'slope': <tf.Tensor: shape=(2,), dtype=int64, numpy=array([3, 2])>, 'thal': <tf.Tensor: shape=(2,), dtype=string, numpy=array([b'fixed', b'normal'], dtype=object)>, 'thalach': <tf.Tensor: shape=(2,), dtype=int64, numpy=array([150, 108])>, 'trestbps': <tf.Tensor: shape=(2,), dtype=int64, numpy=array([145, 160])>} tf.Tensor([0 1], shape=(2,), dtype=int64)
history = model.fit(ds, epochs=5)
Epoch 1/5 152/152 [==============================] - 1s 5ms/step - loss: 0.3150 - accuracy: 0.8284 Epoch 2/5 152/152 [==============================] - 1s 5ms/step - loss: 0.2989 - accuracy: 0.8449 Epoch 3/5 152/152 [==============================] - 1s 5ms/step - loss: 0.2870 - accuracy: 0.8449 Epoch 4/5 152/152 [==============================] - 1s 5ms/step - loss: 0.2782 - accuracy: 0.8482 Epoch 5/5 152/152 [==============================] - 1s 5ms/step - loss: 0.2712 - accuracy: 0.8482