مشاهده در TensorFlow.org | در Google Colab اجرا شود | مشاهده منبع در GitHub | دانلود دفترچه یادداشت |
این آموزش نمونه هایی از نحوه بارگذاری DataFrames پانداها در TensorFlow را ارائه می دهد.
شما از یک مجموعه داده کوچک بیماری قلبی ارائه شده توسط UCI Machine Learning Repository استفاده خواهید کرد. چند صد ردیف در 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
، میتوانید در هر جایی که میتوانید از آرایه NumPy استفاده کنید، از DataFrame pandas استفاده کنید. این کار به این دلیل کار می کند که کلاس pandas.DataFrame
از پروتکل __array__
پشتیبانی می کند و تابع tf.convert_to_tensor
اشیایی را می پذیرد که از پروتکل پشتیبانی می کنند.
ویژگیهای عددی را از مجموعه داده بگیرید (فعلاً از ویژگیهای دستهبندی صرفنظر کنید):
numeric_feature_names = ['age', 'thalach', 'trestbps', 'chol', 'oldpeak']
numeric_features = df[numeric_feature_names]
numeric_features.head()
DataFrame را می توان با استفاده از ویژگی DataFrame.values
یا numpy.array(df)
به آرایه NumPy تبدیل کرد. برای تبدیل آن به تانسور، از 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
استفاده کنید.
برای تنظیم میانگین و انحراف استاندارد لایه قبل از اجرای آن، حتماً متد 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
یکنواخت اعمال کنید، متد Dataset.from_tensor_slices
یک مجموعه داده ایجاد میکند که روی ردیفهای DataFrame تکرار میشود. هر ردیف در ابتدا یک بردار از مقادیر است. برای آموزش یک مدل، به جفت (inputs, labels)
نیاز دارید، بنابراین pass (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>
یک DataFrame به عنوان یک فرهنگ لغت
وقتی شروع به کار با داده های ناهمگن می کنید، دیگر نمی توان با DataFrame به گونه ای رفتار کرد که گویی یک آرایه واحد است. تانسورهای TensorFlow نیاز دارند که همه عناصر دارای dtype
یکسان باشند.
بنابراین، در این مورد، باید آن را به عنوان یک فرهنگ لغت از ستون ها در نظر بگیرید، که در آن هر ستون دارای dtype یکنواخت است. یک DataFrame بسیار شبیه به فرهنگ لغت آرایهها است، بنابراین معمولاً تنها کاری که باید انجام دهید این است که DataFrame را به یک دستور Python ارسال کنید. بسیاری از API های مهم TensorFlow از فرهنگ لغت (تودرتو) آرایه ها به عنوان ورودی پشتیبانی می کنند.
خطوط لوله ورودی tf.data
به خوبی از عهده این کار بر می آیند. همه عملیات tf.data
دیکشنری ها و تاپل ها را به طور خودکار مدیریت می کنند. بنابراین، برای ایجاد مجموعه دادهای از نمونههای فرهنگ لغت از یک DataFrame، کافی است قبل از برش دادن آن با 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 انتظار یک تانسور ورودی را دارند، اما این کلاسها میتوانند ساختارهای تودرتو از دیکشنریها، تاپلها و تانسورها را بپذیرند و برگردانند. این ساختارها به عنوان "nest" شناخته می شوند (برای جزئیات به ماژول tf.nest
مراجعه کنید).
دو روش معادل برای نوشتن یک مدل keras وجود دارد که یک فرهنگ لغت را به عنوان ورودی می پذیرد.
1. سبک Model-subclass
شما یک زیر کلاس از 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 Functional API برای پیاده سازی پیش پردازش استفاده می کند. شما با ایجاد یک tf.keras.Input
برای هر ستون از dataframe شروع می کنید:
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، تغییراتی را اعمال خواهید کرد. هر ویژگی بهعنوان دستهای از اسکالرها شروع میشود ( 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
شده فقط یک لیست پایتون از تمام نتایج پیش پردازش است، هر نتیجه شکلی از (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)
برای آزمایش پیش پردازنده، از Accessor 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)
])
حالا دو قطعه را با استفاده از API عملکردی 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 را به یک dict تبدیل کنید و آن dict را به عنوان آرگومان 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