TFRecords
آموزش‌های پایه‌ای هوش مصنوعیپایتون و ابزارهای یادگیری عمیقیادگیری عمیق

TFRecords و tf.train.Example و نحوه کار با آن‌ها

    0
    مدت زمان مطالعه: ۸ دقیقه

    در مقاله آموزشی پیش‌رو به شما نشان می‌دهیم که چگونه می‌توان داده‌هایی که فرمت TFRecords دارند را ذخیره کرد و خواند. فرمت TFRecord فرمت محبوب تنسورفلو است. به همین منظور از پروتکل بافر پیام tf.train.Example استفاده خواهیم کرد.

    در مقاله آموزشی حاضر از Tensorflow 2.0 استفاده خواهیم کرد، برای نصب آن به روش زیر عمل کنید:

    پروتکل بافرهای Tensorflow

    پروتکل بافرها فرمت جدیدی برای ذخیره کردن و خواندن داده‌ها هستند. ساختار داده در یک پروتکل بافر پیام در فایل .proto نوشته می‌شود. فایل .proto  شیوه ذخیره‌سازی داده‌ها را به کامپایلر پروتکل بافر اطلاع می‌دهد. در گام بعدی کامپایلر یک کلاس ایجاد می‌کند که داده‌ها را کدگزاری و تجزیه و تحلیل می‌کند. این کلاس برای دریافت و ذخیره داده‌ها متدهای مختلفی به کار می‌بندد. این کلاس را به نوعی می‌توان نمونه‌ای از XML در نظر گرفت. در مقابل می‌توانید نمونه‌ای از پروتکل بافر پیام را مشاهده کنید:

    • هر نوع پیام یک یا بیش از یک فیلد دارد که با اعداد مختلف عددگذاری شده‌اند. هر یک از فیلدها هم یک نام و یک نوع داده دارد. نوع داده‌ها می‌توانند عدد ( صحیح یا اعشاری) ، بولی، رشته (string)، بایت‌های خام و  حتی (همانند مثال فوق) پروتکل بافر پیام باشند و شما می‌توانید با استفاده از آن‌ها داده‌های‌تان را به صورت سلسله مراتبی مرتب کنید.

    برای انجام پروژه پیش‌رو نیازی نیست خودتان یک پروتکل بافر پیام بنویسید و به همین دلیل ما هم از معرفی کامل پروتکل بافرها صرف نظر می‌کنیم. همین‌که با پروتکل بافرهای پیام مقابل ( خاص Tensorflow) آشنایی داشته باشید، کافی است:

    1. train.BytesList ، tf.train.FloatList ، tf.train.Int64List : این پروتکل بافرهای پیام فقط یک فیلد دارند که “value” نام دارد و می‌تواند داده‌هایی با فرمت مقابل را در خود ذخیره کند:
    – رشته

    – بایت

    –  float (float32)

    – double (float64)

    –   bool

    –  enum

    –  int32

    – uint32

    –  int64

    – uint64

    این سه پیام نوع داده هستند.

    ۲-  tf.train.Feature:  این پیام فقط یک فیلد دارد که یکی از سه نوع داده فوق را می‌پذیرد. این پیام را می‌توان یک ویژگی واحد برای یک نقطه‌داده در نظر گرفت.

    ۳-  tf.train.Features :  این پروتکل بافر پیام یک نگاشت {“string”: tf.train.Feature} است. این پیام فهرستی از ویژگی‌های یک نقطه داده مشخص است.

    ۴-  tf.train.Example :  این پروتکل بافر پیام فقط یک فیلد از نوع tf.train.Feature دارد که ‘features’ نامیده می‌شود.  این پیام انتزاعی از یک نقطه داده واحد است. در واقع این پیام پوششی پیرامون tf.train.Features است.

    برای تبدیل یک نقطه داده یا یک ردیف از داده‌ها به یک tf.train.Example باید یک tf.train.Feature برای هر یک از ویژگی‌های داده‌ها ایجاد کنید. به همین منظور در سند TensorFlow یک تابع میان‌بُر معرفی شده:

    ۱

    def _bytes_feature(value):
    ۲    “””Returns a bytes_list from a string / byte.”””
    ۳    # If the value is an eager tensor BytesList won’t unpack a string from an EagerTensor.
    ۴    if isinstance(value, type(tf.constant(0))):
    ۵        value = value.numpy()
    ۶    return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))
    ۷
    ۸def _float_feature(value):
    ۹    “””Returns a float_list from a float / double.”””
    ۱۰    return tf.train.Feature(float_list=tf.train.FloatList(value=[value]))
    ۱۱
    ۱۲def _int64_feature(value):
    ۱۳    “””Returns an int64_list from a bool / enum / int / uint.”””
    ۱۴    return tf.train.Feature(int64_list=tf.train.Int64List(value=[value]))

    ورودی هر یک از این توابع یک مقدار عددی Scalar input value
     است و یک tf.train.Feature شامل یکی از سه نوع فوق باز می‌گردانند. به مثال مقابل توجه کنید:

    و خروجی آن:

    با استفاده از تابع tf.io.serialize_tensor نیز می‌توان ویژگی‌های غیرعددی را به رشته‌های باینری تبدیل کرد. برای این‌که رشته باینری را مجدداً به حالت تنسور برگردانید، از تابع tf.io.parse_tensor استفاده کنید:

    در صورتی‌که پیام tf.train.Example را از داده‌ها ایجاد کنیم:

    برای هر یک نقطه‌داده‌ها طبق مراحل زیر عمل کنید:

    • برای هر یک از ویژگی‌ها، البته با توجه به نوع آن، یکی از سه تابع میان‌بر فوق را اجرا کنید تا یک پیام train.Feature  ایجاد شود.
    • یک دیکشنری ایجاد کنید که در آن هر کلید (Key) نام یک ویژگی و مقادیر آن پیام‌های train.Feature  هستند (که در گام اول ایجاد کردیم). دیکشنری این‌چنین ظاهری خواهد داشـت:

    feature = {

    ‘feature0’: _int64_feature(feature0),
    ‘feature1’: _int64_feature(feature1),
    ‘feature2’: _bytes_feature(feature2),
    ‘feature3’: _float_feature(feature3),
    }
    • سپس یک پیام train.Example  از دیکشنری ( که در گام دوم ایجاد کردیم) ایجاد کنید. فراموش نکنید که پیام tf.train.Example  فقط یک فیلد از نوع tf.train.Features دارد. به همین دلیل ابتدا پیام tf.train.Features را از دیکشنری ایجاد کنید و با استفاده از آن یک پیام tf.train.Example ایجاد کنید. چیزی در نهایت ایجاد می‌شود اینگونه خواهد بود:

    example_proto = tf.train.Example(features =

    tf.train.Features(feature=feature))

    برای این‌که با ارائه یک مثال این فرایند را به شما نشان دهیم، یک دیتاست ساختگی ایجاد می‌کنیم. این دیتاست ۴ ویژگی دارد.

    سپس طبق مراحل زیر یک تابع بنویسید تا یک tf.train.Example ایجاد کنید:

    در ادامه از اولین نقطه داده یک نمونه پیام ایجاد می‌کنیم:

    به دلیل این‌که feature3 یک ویژگی غیر عددی است با استفاده از tf.io.serialize_tensor  آن را به یک بایت-رشته تبدیل کردیم.

    اکنون شیوه ایجاد پیام‌های tf.train.Example را از داده‌ها می‌دانید. در قدم بعدی به شیوه نوشتن آن‌ را در یک فایل TFRecord و نحوه خواندن آن‌ها را به شما نشان می‌دهیم.

    TFRecords

    • برای خوانش راحت‌تر داده‌ها می‌توانید آن‌ها را سریال‌سازی کرده و در مجموعه‌ای از فایل‌ها (۱۰۰ تا ۲۰۰ مگابایتی) ذخیره کنید، در این صورت می‌تواند هر کدام از آن‌ها را به صورت خطی بخوانید. به ویژه اگر داده‌ها در سراسر یک شبکه پخش شده باشند، این روش مفید خواهد بود. این روش در کَش کردن عملیات‌های پیش‌پردازش داده نیز کاربرد دارد. فرمت TFRecord فرمت ساده‌ای برای ذخیره‌ مجموعه‌ای از رکوردهای باینری است.

    هر فایل TFRecord از یک توالی از رکوردها تشکیل شده است. در این توالی هر یک از رکوردها یک رشته-بایت است. لزومی ندارد در فایل‌های  TFRecords از پیام‌های tf.train.Example استفاده کنیم اما در این مقاله آموزشی از آن‌ها استفاده خواهیم کرد. در قسمت بالا توضیح دادیم که چگونه می‌توان پیام‌های tf.train.Example را از داده‌ها ایجاد کرد. برای این‌که بتوانیم این پیام‌ها را با فرمت TFRecords بنویسیم، باید اول آن‌ها را به رشته-بایت تبدیل کنیم. به همین منظور، می‌توانیم از متد SerializeToString()  استفاده کنیم. طبق مراحل زیر می‌توانیم تابع را به روز‌رسانی کنیم و پیام Example را به رشته-بایت تبدیل کنیم:

    نمونه سریال‌سازی شده به شکل زیر خواهد بود:

    و خروجی آن:

    نوشتن داده‌ها در TFRecords

    برای اینکه بتوانیم داده‌ها را در یک فایل TFRecords بنویسیم باید طبق مراحل فوق هر یک از نقطه‌داده‌ها را به یک رشته-بایت تبدیل کنیم و با استفاده از tf.io.TFRecordsWriter آن را در فایل بنویسیم:

    در نتیجه فایل data.tfrecords در یک مسیر مشخص ایجاد می‌شود که در مورد فوق همان دیکشنری است.

    یکی از مکان‌های مناسب برای اجرای برخی از عملیات‌های پیش‌ پردازش بر روی داده‌ها، از جمله داده افزایی Data augmentation این است که از قبل نمونه‌ را سریال‌سازی کرده و در فایل بنویسید. در ادامه مثالی از آن را با ذکر یک نمونه تصویری نشان خواهیم داد.

    خواندن فایل TFRecords

    در این قسمت نحوه خواندن رکوردهایی که ایجاد کرده‌ایم را به شما نشان خواهیم داد. به همین منظور ابتدا یک tf.data.TFRecordDataset  از فهرست مسیرهای فایل TFRecord ایجاد می‌کنیم.

    در نتیجه تمامی نقطه‌داده‌هایی که در دیتاست قرار دارند به رشته-بایت‌های خامی تبدیل می‌شوند که تابع serialize_example بازگردانده است. تابع پیش‌رو یک serialized_example را می‌خواند و با استفاده از توصیف ویژگی آن را تجزیه و تحلیل می‌کند.

    اکنون می‌توانیم این تابع را بر روی

    tfrecord_dataset اجرا کنیم و ویژگی‌های مورد نظرمان را برگردانیم.

    ذکر مثال با یک نمونه تصویری

    در این قسمت مثالی با یک نمونه تصویری ارائه می‌دهیم. من از دیتاست سگ‌ها و گربه‌ها استفاده خواهم کرد و برای سهولت فقط از ۱۰۰ تصویر اول هر دسته استفاده خواهم کرد و آن‌ها را در پوشه‌ای به نام “data” در دیکشنری قرار می‌دهیم.

    در قدم اول فهرستی از مسیرهای تصاویر ایجاد می‌کنیم.

    ۱۰۰ تصویر اول، تصویر گربه است و ۱۰۰ تصویر بعدی، تصویر سگ. تصاویر گربه را با ۰ و تصاویر سگ را با ۱ برچسب‌گذاری می‌کنیم.

    حالا ۹ تصویر اول را نگاه می‌کنیم.

    TFRecords

    حالا می‌توانیم TFrecords را ایجاد کنیم. به غیر از توصیفات ویژگی، تابع serialize_example همانند فوق است.

    و بر روی اعضای دیتاست یک حلقه تعریف می‌کنیم و در فایل می‌نویسیم.

    در حلقه‌ بالا، ابتدا تصویر را به یک آرایه numpy تبدیل می‌کنیم و سپس برخی از عملیات‌های داده افزایی را اجرا می‌کنیم که در این مورد را random_zoom  اجرا خواهیم کرد. سپس آرایه‌ numpy را به رشته‌-بایت تبدیل می‌کنیم و آن را به همراه برچسب‌ها و ابعاد تصویر در یک فایل می‌نویسیم.

    برای اینکه بتوانیم داده‌ها را در فایل tfrecords بخوانیم باید طبق مراحل فوق عمل کنیم.

    در گام بعدی این تابع را بر روی دیتاست tfrecords اجرا می‌کنیم و دوباره ۹ تصویر اول را نگاه می‌کنیم.

    TFRecords

    البته توجه داشته باشید پیش از این‌که داده‌ها را در فایل بنویسیم، tf.keras.preprocessing.image.random_zoom را اجرا می‌کنیم و به همین دلیل تصاویر را به صورت تصاویر بزرگنمایی (zoom-in) مشاهده می‌کنیم.

    چکیده

    TFRecords یک فرمت بهینه است که می‌توانیم از آن در فرایندهای پردازش داده‌ها استفاده کنیم و پیام‌های پروتکل بافر روش مناسبی برای نوشتن داده‌ها در فایل‌های TFRecord هستند. استفاده از فایل‌های TFRecords می‌تواند سرعت عملیات‌ها را افزایش دهد به ویژه اگر در فرایند آموزش با مشکل بارگذاری داده‌ها در مواجه هستید.

    این مطلب چه میزان برای شما مفید بوده است؟
    [کل: ۰ میانگین: ۰]

    داده کاوی سحاب ؛ توسعه ابزار برای توسعه‌دهندگان، شبکه‌های اجتماعی و متن‌کاوی

    مقاله قبلی

    استفاده از هوش مصنوعی به منظور جلوگیری از خودزنی دانش‌آموزان

    مقاله بعدی

    شما همچنین ممکن است دوست داشته باشید

    نظرات

    پاسخ دهید

    نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *