אימון מבוזר הוא סוג של אימון מודל שבו דרישות משאבי המחשוב (למשל, מעבד, זיכרון RAM) מפוזרות בין מספר מחשבים. אימון מבוזר מאפשר להתאמן מהר יותר ועל מערכי נתונים גדולים יותר (עד כמה מיליארדי דוגמאות).
אימון מבוזר שימושי גם עבור אופטימיזציה אוטומטית של היפר-פרמטרים כאשר מספר מודלים מאומנים במקביל.
במסמך זה תלמד כיצד:
- אימון מודל TF-DF באמצעות אימון מבוזר.
- כוונן את הפרמטרים ההיפר של מודל TF-DF באמצעות אימון מבוזר.
מגבלות
נכון לעכשיו, הכשרה מבוזרת נתמכת עבור:
- אימון דגמי Gradient Boosted Trees עם
tfdf.keras.DistributedGradientBoostedTreesModel
. דגמי Distributed Gradient Boosted Trees שווים למקביליהם הלא-מבוזרים. - חיפוש יתר פרמטרים עבור כל סוג דגם TF-DF.
כיצד לאפשר הדרכה מבוזרת
סעיף זה מפרט את השלבים להפעלת הדרכה מבוזרת. לדוגמאות מלאות, עיין בסעיף הבא.
היקף ParameterServerStrategy
המודל ומערך הנתונים מוגדרים בהיקף ParameterServerStrategy
.
strategy = tf.distribute.experimental.ParameterServerStrategy(...)
with strategy.scope():
model = tfdf.keras.DistributedGradientBoostedTreesModel()
distributed_train_dataset = strategy.distribute_datasets_from_function(dataset_fn)
model.fit(distributed_train_dataset)
פורמט ערכת נתונים
בדומה להדרכה לא מבוזרת, ניתן לספק מערכי נתונים כ
- מערך נתונים מבוזר זרימת טנזור סופית, או
- נתיב לקבצי הנתונים באמצעות אחד מפורמטי הנתונים התואמים .
השימוש בקבצים מרוסקים הוא פשוט יותר באופן משמעותי משימוש בגישת מערך הנתונים המבוזרים של tensorflow (שורה אחת לעומת ~20 שורות קוד). עם זאת, רק גישת הנתונים של tensorflow תומכת בעיבוד מקדים של TensorFlow. אם הצינור שלך אינו מכיל עיבוד מקדים כלשהו, מומלצת אפשרות הנתונים המרוסקים.
בשני המקרים, יש לחלק את מערך הנתונים למספר קבצים כדי להפיץ את קריאת הנתונים ביעילות.
עובדי התקנה
תהליך ראשי הוא התוכנית שמריצה את קוד הפיתון שמגדיר את מודל TensorFlow. תהליך זה אינו מפעיל חישוב כבד. חישוב ההדרכה האפקטיבי נעשה על ידי עובדים . עובדים הם תהליכים המריצים שרת פרמטרים של TensorFlow.
יש להגדיר את הצ'יף עם כתובת ה-IP של העובדים. ניתן לעשות זאת באמצעות משתנה הסביבה TF_CONFIG
, או על ידי יצירת ClusterResolver
. ראה אימון שרת פרמטרים עם ParameterServerStrategy לפרטים נוספים.
ParameterServerStrategy של TensorFlow מגדירה שני סוגים של עובדים: "עובדים" ו"שרת פרמטרים". TensorFlow דורשת הפעלה של לפחות אחד מכל סוג של עובד. עם זאת, TF-DF משתמש רק ב"עובדים". אז, "שרת פרמטרים" אחד צריך להיות מופע אבל לא ישמש את TF-DF. לדוגמה, התצורה של אימון TF-DF עשויה להיראות כך:
- 1 צ'יף
- 50 עובדים
- שרת פרמטר אחד
העובדים דורשים גישה למבצעי ההדרכה המותאמים אישית של TensorFlow Decision Forests. ישנן שתי אפשרויות לאפשר גישה:
- השתמש בשרת פרמטר TF-DF C++ המוגדר מראש
//third_party/tensorflow_decision_forests/tensorflow/distribute:tensorflow_std_server
. - צור שרת פרמטרים על ידי קריאה ל-
tf.distribute.Server()
. במקרה זה, יש לייבא את TF-DFimport tensorflow_decision_forests
.
דוגמאות
סעיף זה מציג דוגמאות מלאות של תצורות אימון מבוזרות. לדוגמאות נוספות, בדוק את בדיקות יחידת TF-DF .
דוגמה: הדרכה מבוזרת על נתיב מערך הנתונים
חלק את מערך הנתונים שלך לקבוצה של קבצים מרוסקים באמצעות אחד מפורמטי הנתונים התואמים . מומלץ לתת שמות לקבצים באופן הבא: /path/to/dataset/train-<5 digit index>-of-<total files>
, למשל
/path/to/dataset/train-00000-of-00100
/path/to/dataset/train-00001-of-00005
/path/to/dataset/train-00002-of-00005
...
ליעילות מקסימלית, מספר הקבצים צריך להיות לפחות פי 10 ממספר העובדים. לדוגמה, אם אתה מתאמן עם 100 עובדים, ודא שמערך הנתונים מחולק ל-1000 קבצים לפחות.
לאחר מכן ניתן להפנות לקבצים באמצעות ביטוי ריסוק כגון:
- /path/to/dataset/train@1000
- /path/to/dataset/train@*
אימון מבוזר מתבצע באופן הבא. בדוגמה זו, מערך הנתונים מאוחסן כ-TFRecord של דוגמאות TensorFlow (מוגדר על ידי המפתח tfrecord+tfe
).
import tensorflow_decision_forests as tfdf
import tensorflow as tf
strategy = tf.distribute.experimental.ParameterServerStrategy(...)
with strategy.scope():
model = tfdf.keras.DistributedGradientBoostedTreesModel()
model.fit_on_dataset_path(
train_path="/path/to/dataset/train@1000",
label_key="label_key",
dataset_format="tfrecord+tfe")
print("Trained model")
model.summary()
דוגמה: אימון מבוזר על מערך נתונים מבוזר סופי של TensorFlow
TF-DF מצפה למערך נתונים של TensorFlow מבוזר סופי של עובד:
- מבוזר : מערך נתונים לא מבוזר עטוף ב-
strategy.distribute_datasets_from_function
. - finite : מערך הנתונים צריך לקרוא כל דוגמה פעם אחת בדיוק. מערך הנתונים לא אמור להכיל הוראות
repeat
. - worker-sharded : כל עובד צריך לקרוא חלק נפרד ממערך הנתונים.
הנה דוגמה:
import tensorflow_decision_forests as tfdf
import tensorflow as tf
def dataset_fn(context, paths):
"""Create a worker-sharded finite dataset from paths.
Like for non-distributed training, each example should be visited exactly
once (and by only one worker) during the training. In addition, for optimal
training speed, the reading of the examples should be distributed among the
workers (instead of being read by a single worker, or read and discarded
multiple times).
In other words, don't add a "repeat" statement and make sure to shard the
dataset at the file level and not at the example level.
"""
# List the dataset files
ds_path = tf.data.Dataset.from_tensor_slices(paths)
# Make sure the dataset is used with distributed training.
assert context is not None
# Split the among the workers.
#
# Note: The "shard" is applied on the file path. The shard should not be
# applied on the examples directly.
# Note: You cannot use 'context.num_input_pipelines' with ParameterServerV2.
current_worker = tfdf.keras.get_worker_idx_and_num_workers(context)
ds_path = ds_path.shard(
num_shards=current_worker.num_workers,
index=current_worker.worker_idx)
def read_csv_file(path):
"""Reads a single csv file."""
numerical = tf.constant([0.0], dtype=tf.float32)
categorical_string = tf.constant(["NA"], dtype=tf.string)
csv_columns = [
numerical, # feature 1
categorical_string, # feature 2
numerical, # feature 3
# ... define the features here.
]
return tf.data.experimental.CsvDataset(path, csv_columns, header=True)
ds_columns = ds_path.interleave(read_csv_file)
# We assume a binary classification label with the following possible values.
label_values = ["<=50K", ">50K"]
# Convert the text labels into integers:
# "<=50K" => 0
# ">50K" => 1
init_label_table = tf.lookup.KeyValueTensorInitializer(
keys=tf.constant(label_values),
values=tf.constant(range(label_values), dtype=tf.int64))
label_table = tf.lookup.StaticVocabularyTable(
init_label_table, num_oov_buckets=1)
def extract_label(*columns):
return columns[0:-1], label_table.lookup(columns[-1])
ds_dataset = ds_columns.map(extract_label)
# The batch size has no impact on the quality of the model. However, a larger
# batch size generally is faster.
ds_dataset = ds_dataset.batch(500)
return ds_dataset
strategy = tf.distribute.experimental.ParameterServerStrategy(...)
with strategy.scope():
model = tfdf.keras.DistributedGradientBoostedTreesModel()
train_dataset = strategy.distribute_datasets_from_function(
lambda context: dataset_fn(context, [...list of csv files...])
)
model.fit(train_dataset)
print("Trained model")
model.summary()
דוגמה: כוונון היפר-פרמטרים מבוזר בנתיב של מערך נתונים
כוונון היפר-פרמטר מבוזר בנתיב של מערך נתונים דומה לאימון מבוזר. ההבדל היחיד הוא שאופציה זו תואמת לדגמים שאינם מבוזרים. לדוגמה, אתה יכול להפיץ את כוונון ההיפר-פרמטר של מודל Gradient Boosted Trees (הלא מבוזר).
with strategy.scope():
tuner = tfdf.tuner.RandomSearch(num_trials=30, use_predefined_hps=True)
model = tfdf.keras.GradientBoostedTreesModel(tuner=tuner)
training_history = model.fit_on_dataset_path(
train_path=train_path,
label_key=label,
dataset_format="csv",
valid_path=test_path)
logging.info("Trained model:")
model.summary()
דוגמה: בדיקת יחידה
כדי לבחון יחידות הכשרה מבוזרת, אתה יכול ליצור תהליכי עבודה מדומים. ראה את השיטה _create_in_process_tf_ps_cluster
בבדיקות יחידות TF-DF למידע נוסף.