תאימות גרסת TensorFlow

מסמך זה מיועד למשתמשים הזקוקים לתאימות לאחור בגרסאות שונות של TensorFlow (עבור קוד או נתונים), ולמפתחים שרוצים לשנות את TensorFlow תוך שמירה על תאימות.

גירסאות סמנטיות 2.0

TensorFlow עוקב אחר Semantic Versioning 2.0 ( semver ) עבור ה-API הציבורי שלו. לכל גרסת מהדורה של TensorFlow יש את הצורה MAJOR.MINOR.PATCH . לדוגמה, לגרסת TensorFlow 1.2.3 יש גרסה 1 MAJOR , גרסה MINOR 2 וגרסה 3 PATCH . לשינויים בכל מספר יש את המשמעות הבאה:

  • עיקרי : שינויים פוטנציאליים לא תואמים לאחור. קוד ונתונים שעבדו עם מהדורה מרכזית קודמת לא בהכרח יעבדו עם המהדורה החדשה. עם זאת, במקרים מסוימים, גרפים ונקודות ביקורת קיימים של TensorFlow עשויים להיות ניתנים להעברה למהדורה החדשה יותר; ראה תאימות של גרפים ונקודות ביקורת לפרטים על תאימות נתונים.

  • MINOR : תכונות תואמות לאחור, שיפורי מהירות וכו'. קוד ונתונים שעבדו עם מהדורה מינורית קודמת ותלויים רק בממשק ה-API הציבורי שאינו ניסיוני ימשיכו לעבוד ללא שינוי. לפרטים על מהו ה-API הציבורי ומהו לא, ראה מה מכוסה .

  • תיקון : תיקוני באגים תואמים לאחור.

לדוגמה, גרסה 1.0.0 הציגה שינויים לא תואמים לאחור מגרסה 0.12.1. עם זאת, מהדורה 1.1.1 הייתה תואמת לאחור לגרסה 1.0.0.

מה מכוסה

רק ממשקי ה-API הציבוריים של TensorFlow תואמים לאחור על פני גרסאות משניות ותיקון. ממשקי ה-API הציבוריים מורכבים מ

  • כל הפונקציות והמחלקות של Python המתועדות במודול tensorflow ותתי המודולים שלו, למעט

    • סמלים פרטיים: כל פונקציה, מחלקה וכו', ששמה מתחיל ב _
    • סמלים ניסיוניים ו- tf.contrib , ראה למטה לפרטים.

    שים לב שהקוד בדוגמאות examples/ tools/ ספריות אינו נגיש דרך מודול tensorflow Python ולכן אינו מכוסה על ידי ערבות התאימות.

    אם סמל זמין דרך מודול tensorflow Python או תת-מודוליו, אך אינו מתועד, אז הוא אינו נחשב לחלק מה-API הציבורי.

  • ה-API של התאימות (ב-Python, מודול tf.compat ). בגרסאות העיקריות, אנו עשויים לשחרר כלי עזר ונקודות קצה נוספות כדי לסייע למשתמשים במעבר לגרסה עיקרית חדשה. סמלי API אלה הוצאו משימוש ואינם נתמכים (כלומר, לא נוסיף תכונות כלשהן, ולא נתקן באגים מלבד תיקון נקודות תורפה), אך הם נופלים תחת ערבויות התאימות שלנו.

  • ה-API של TensorFlow C:

  • קבצי מאגר הפרוטוקול הבאים:

מספר גרסה נפרד עבור TensorFlow Lite

נכון לעכשיו TensorFlow Lite מופץ כחלק מ- TensorFlow. עם זאת, אנו שומרים לעצמנו את הזכות לבצע שינויים עתידיים בממשקי API של TensorFlow Lite בלוח זמנים שונה מזה של ממשקי API אחרים של TensorFlow, או אפילו להעביר את TensorFlow Lite להפצת מקור נפרדת ו/או למאגר מקור נפרד מאשר TensorFlow.

בשל כך, אנו משתמשים במספר גרסה שונה עבור TensorFlow Lite ( TFLITE_VERSION_STRING ב- tensorflow/lite/version.h , ו- TfLiteVersion() ב- tensorflow/lite/c/c_api.h ) מאשר עבור TensorFlow ( TF_VERSION_STRING ב- tensorflow/core/public/version.h ו- TF_Version() ב- tensorflow/c/c_api.h ). נכון לעכשיו, לשני מספרי הגרסאות הללו יש את אותו ערך. אבל בעתיד, הם עשויים להתפצל; לדוגמה, אנו עשויים להגדיל את מספר הגרסה הראשית של TensorFlow Lite מבלי להגדיל את מספר הגרסה הראשית של TensorFlow, או להיפך.

משטח ה-API המכוסה על ידי מספר הגרסה של TensorFlow Lite מורכב מממשקי ה-API הציבוריים הבאים:

סמלים ניסויים אינם מכוסים; ראה למטה לפרטים.

מספר גרסה נפרד עבור ממשקי API של TensorFlow Lite Extension

TensorFlow Lite מספק ממשקי API של C להרחבת מתורגמן TensorFlow Lite עם "מבצעים מותאמים אישית", המספקים פעולות מוגדרות על ידי משתמש בגרף, או "נציגים", המאפשרים האצלת חישוב עבור גרף (או עבור תת-קבוצה של גרף) אחורי מותאם אישית. ממשקי API אלה, שאנו מכנים ביחד "ממשקי API להרחבת TensorFlow Lite", דורשים תלות אינטימית יותר בחלק מהפרטים של יישום TensorFlow Lite.

אנו שומרים לעצמנו את הזכות לבצע שינויים עתידיים בממשקי API אלה, שעשויים לרבות שינויים שאינם תואמים לאחור, בלוח זמנים שונה מזה של ממשקי API אחרים של TensorFlow Lite. אז אנו משתמשים במספר גרסה שונה עבור ממשקי ה-API של TensorFlow Lite Extension מאשר מספרי הגרסה עבור TensorFlow Lite או TensorFlow (שתוארו בסעיף הקודם). אנו מציגים כמה ממשקי API חדשים ב-TensorFlow Lite גרסה 2.15 כדי לקבל את גרסת TensorFlow Lite Extension APIs ( TFLITE_EXTENSION_APIS_VERSION_STRING ב- tensorflow/lite/version.h , ו-TfLiteExtensionApisVersion() ב- tensorflow/lite/c/c_api.h ). מספר הגרסה של ממשקי ה-API של TensorFlow Lite Extension זהה כרגע למספר הגרסה של TensorFlow ו- TensorFlow Lite. אבל בעתיד, הם עשויים להתפצל; לדוגמה, אנו עשויים להגדיל את מספר הגרסה הראשית של ממשקי API של TensorFlow Lite Extension מבלי להגדיל את מספר הגרסה הראשית של TensorFlow Lite, או להיפך.

משטח ה-API המכוסה על ידי מספר הגרסה של TensorFlow Lite Extension APIs מורכב מממשקי ה-API הציבוריים הבאים:

שוב, סמלים ניסיוניים אינם מכוסים; ראה למטה לפרטים.

מה לא מכוסה

חלקים מסוימים של TensorFlow יכולים להשתנות בדרכים לא תואמות לאחור בכל נקודה. אלו כוללים:

  • ממשקי API ניסיוניים : כדי להקל על הפיתוח, אנו פוטרים כמה סמלי API המסומנים בבירור כניסיוניים מהבטחות התאימות. בפרט, הדברים הבאים אינם מכוסים על ידי ערבויות תאימות כלשהן:

    • כל סמל במודול tf.contrib או בתתי המודולים שלו;
    • כל סמל (מודול, פונקציה, ארגומנט, מאפיין, מחלקה, קבוע, סוג, חבילה וכו') ששמו מכיל experimental או Experimental ; אוֹ
    • כל סמל ששמו המלא כולל מודול או מחלקה או חבילה שהם עצמם ניסיוניים. זה כולל שדות ותת-הודעות של כל מאגר פרוטוקול הנקרא experimental .
  • שפות אחרות : ממשקי API של TensorFlow בשפות שאינן Python ו-C, כגון:

    וממשקי API של TensorFlow Lite בשפות שאינן Java/Kotlin, C, Objective-C ו- Swift, בפרט

  • פרטים של פעולות מורכבות: פונקציות ציבוריות רבות ב-Python מתרחבות למספר אופציות פרימיטיביות בגרף, ופרטים אלו יהיו חלק מכל גרף שנשמר בדיסק כ- GraphDef s. פרטים אלה עשויים להשתנות עבור מהדורות קטנות. בפרט, מבחני רגרסיה הבודקים התאמה מדויקת בין גרפים צפויים לפרוץ על פני מהדורות קטנות, למרות שהתנהגות הגרף צריכה להיות ללא שינוי ונקודות ביקורת קיימות עדיין יפעלו.

  • פרטים מספריים של נקודה צפה: ערכי הנקודה הצפה הספציפית המחושבים על ידי פעולות עשויות להשתנות בכל עת. משתמשים צריכים להסתמך רק על דיוק משוער ויציבות מספרית, לא על הסיביות הספציפיות המחושבות. שינויים בנוסחאות מספריות במהדורות מינוריות ותיקונים אמורים להביא לדיוק דומה או משופר, עם האזהרה שלמידת מכונה דיוק משופר של נוסחאות ספציפיות עשוי לגרום לירידה ברמת הדיוק של המערכת הכוללת.

  • מספרים אקראיים: המספרים האקראיים הספציפיים שחושבו עשויים להשתנות בכל עת. על המשתמשים להסתמך רק על התפלגויות נכונות בערך ועל חוזק סטטיסטי, לא על הסיביות הספציפיות המחושבות. עיין במדריך ליצירת מספרים אקראיים לפרטים.

  • הטיית גרסה ב-Tensorflow מבוזרת: אין תמיכה בהפעלת שתי גרסאות שונות של TensorFlow באשכול יחיד. אין ערבויות לגבי תאימות לאחור של פרוטוקול החוט.

  • באגים: אנו שומרים לעצמנו את הזכות לבצע שינויים בהתנהגות לא תואמת לאחור (אם כי לא ב-API) אם היישום הנוכחי שבור בבירור, כלומר, אם הוא סותר את התיעוד או אם התנהגות מיועדת ידועה ומוגדרת היטב אינה מיושמת כראוי עקב לבאג. לדוגמה, אם אופטימיזר מתיימר ליישם אלגוריתם אופטימיזציה ידוע אך אינו תואם לאלגוריתם זה בגלל באג, אז נתקן את האופטימיזציה. התיקון שלנו עשוי לשבור קוד בהסתמך על התנהגות שגויה לצורך התכנסות. נציין שינויים כאלה בהערות השחרור.

  • ממשק API לא בשימוש: אנו שומרים לעצמנו את הזכות לבצע שינויים לא תואמים לאחור בממשקי API שלא מוצאים להם שימושים מתועדים (על ידי ביצוע ביקורת על השימוש ב-TensorFlow באמצעות חיפוש GitHub). לפני ביצוע שינויים כאלה, נודיע על כוונתנו לבצע את השינוי ברשימת התפוצה announce@ , נספק הנחיות כיצד לטפל בכל שבר (אם רלוונטי), ונמתין שבועיים כדי לתת לקהילה שלנו הזדמנות לשתף את המשוב שלהם .

  • התנהגות שגיאה: אנו עשויים להחליף שגיאות בהתנהגות שאינה שגיאה. לדוגמה, אנו עשויים לשנות פונקציה כדי לחשב תוצאה במקום להעלות שגיאה, גם אם השגיאה הזו מתועדת. אנו שומרים לעצמנו את הזכות לשנות את הטקסט של הודעות השגיאה. בנוסף, סוג השגיאה עשוי להשתנות אלא אם סוג החריג עבור מצב שגיאה ספציפי מצוין בתיעוד.

תאימות של SavedModels, גרפים ונקודות ביקורת

SavedModel הוא פורמט ההסדרה המועדף לשימוש בתוכניות TensorFlow. SavedModels מכילים שני חלקים: גרף אחד או יותר המקודד כ- GraphDefs ו-Checkpoint. הגרפים מתארים את זרימת הנתונים של פעולות שיש להפעיל, ונקודות ביקורת מכילות את ערכי הטנזור השמורים של משתנים בגרף.

משתמשי TensorFlow רבים יוצרים SavedModels, וטוענים ומבצעים אותם עם מהדורה מאוחרת יותר של TensorFlow. בהתאם ל- semver , SavedModels שנכתבו עם גרסה אחת של TensorFlow ניתן לטעון ולהעריך עם גרסה מאוחרת יותר של TensorFlow עם אותה מהדורה מרכזית.

אנו נותנים ערבויות נוספות עבור SavedModels נתמכים . אנו קוראים ל-SavedModel שנוצר באמצעות ממשקי API לא הוצא משימוש, לא ניסיוני, ללא תאימות בגרסה הראשית של TensorFlow N , SavedModel הנתמך בגרסה N ניתן לטעון ולהפעיל כל SavedModel N בגרסה N+1 של TensorFlow הראשית. עם זאת, ייתכן שהפונקציונליות הנדרשת לבנייה או שינוי של דגם כזה לא תהיה זמינה יותר, ולכן אחריות זו חלה רק על SavedModel ללא שינוי.

אנו נשתדל לשמור על תאימות לאחור זמן רב ככל האפשר, כך שהקבצים בסידרה יהיו ניתנים לשימוש לאורך פרקי זמן ארוכים.

תאימות GraphDef

גרפים מסודרים באמצעות מאגר פרוטוקול GraphDef . כדי להקל על שינויים לא תואמים לאחור בגרפים, לכל GraphDef יש מספר גרסה נפרד מגרסת TensorFlow. לדוגמה, גרסת GraphDef 17 הוציאה משימוש את ה- inv op לטובת reciprocal . הסמנטיקה היא:

  • כל גרסה של TensorFlow תומכת במרווח של גרסאות GraphDef . מרווח זה יהיה קבוע על פני מהדורות תיקון, ויגדל רק על פני מהדורות קטנות. הפסקת התמיכה בגרסת GraphDef תתרחש רק עבור מהדורה מרכזית של TensorFlow (ורק בהתאמה לתמיכה בגרסה המובטחת עבור SavedModels).

  • גרפים חדשים שנוצרו מקבלים את מספר הגרסה העדכנית ביותר GraphDef .

  • אם גרסה נתונה של TensorFlow תומכת בגרסת GraphDef של גרף, היא תיטען ותעריך באותה התנהגות כמו גרסת TensorFlow ששימשה ליצירתו (למעט פרטים מספריים של נקודה צפה ומספרים אקראיים כמתואר לעיל), ללא קשר לעיקרי גרסה של TensorFlow. בפרט, GraphDef שתואם לקובץ ביקורת בגרסה אחת של TensorFlow (כגון המקרה ב-SavedModel) יישאר תואם לנקודת ביקורת זו בגרסאות הבאות, כל עוד ה-GraphDef נתמך.

    שים לב שזה חל רק על גרפים מסודרים ב-GraphDefs (וב-SavedModels): ייתכן שקוד שקורא נקודת ביקורת לא יוכל לקרוא נקודות ביקורת שנוצרו על ידי אותו קוד המריץ גרסה אחרת של TensorFlow.

  • אם הגבול העליון GraphDef גדל ל-X במהדורה (מינורית), יעברו לפחות שישה חודשים עד שהגבול התחתון יוגדל ל-X. לדוגמה (אנו משתמשים כאן במספרי גרסאות היפותטיים):

    • TensorFlow 1.2 עשוי לתמוך בגרסאות GraphDef 4 עד 7.
    • TensorFlow 1.3 יכול להוסיף GraphDef גרסה 8 ולתמוך בגרסאות 4 עד 8.
    • לפחות שישה חודשים מאוחר יותר, TensorFlow 2.0.0 עלולה להפסיק את התמיכה בגרסאות 4 עד 7, ולהשאיר את גרסה 8 בלבד.

    שימו לב שבגלל שגרסאות עיקריות של TensorFlow מתפרסמות בדרך כלל בהפרש של יותר מ-6 חודשים, הערבויות עבור SavedModels הנתמכות המפורטות למעלה חזקות בהרבה מהאחריות של 6 חודשים עבור GraphDefs.

לבסוף, כאשר התמיכה בגרסת GraphDef תבוטל, ננסה לספק כלים להמרה אוטומטית של גרפים לגרסת GraphDef נתמכת חדשה יותר.

תאימות גרפים ונקודות ביקורת בעת הרחבת TensorFlow

סעיף זה רלוונטי רק בעת ביצוע שינויים לא תואמים בפורמט GraphDef , כגון בעת ​​הוספת פעולות, הסרת פעולות או שינוי הפונקציונליות של פעולות קיימות. הסעיף הקודם אמור להספיק לרוב המשתמשים.

תאימות לאחור וחלקית קדימה

לתוכנית ניהול הגרסאות שלנו יש שלוש דרישות:

  • תאימות לאחור לתמיכה בטעינת גרפים ונקודות ביקורת שנוצרו עם גרסאות ישנות יותר של TensorFlow.
  • תאימות קדימה לתמיכה בתרחישים שבהם יצרן הגרף או המחסום משודרג לגרסה חדשה יותר של TensorFlow לפני הצרכן.
  • אפשר את TensorFlow מתפתח בדרכים לא תואמות. לדוגמה, הסרת פעולות, הוספת תכונות והסרת תכונות.

שים לב שבעוד שמנגנון גרסת GraphDef נפרד מגרסת TensorFlow, שינויים לא תואמים לאחור בפורמט GraphDef עדיין מוגבלים על ידי גירסאות סמנטיות. המשמעות היא שניתן להסיר או לשנות את הפונקציונליות רק בין גרסאות MAJOR של TensorFlow (כגון 1.7 עד 2.0 ). בנוסף, תאימות קדימה נאכפת בתוך מהדורות תיקון (לדוגמה 1.x.1 עד 1.x.2 ).

כדי להשיג תאימות אחורה וקדימה ולדעת מתי לאכוף שינויים בפורמטים, לגרפים ולנקודות ביקורת יש מטא נתונים המתארים מתי הם הופקו. הסעיפים שלהלן מפרטים את הטמעת TensorFlow ואת ההנחיות עבור גרסאות GraphDef המתפתחות.

סכימות גרסאות נתונים עצמאיות

קיימות גרסאות נתונים שונות עבור גרפים ונקודות ביקורת. שני פורמטי הנתונים מתפתחים בקצבים שונים זה מזה וגם בקצבים שונים מ-TensorFlow. שתי מערכות הגירסה מוגדרות ב- core/public/version.h . בכל פעם שמתווסף גרסה חדשה, מתווספת הערה לכותרת המפרטת מה השתנה ואת התאריך.

נתונים, יצרנים וצרכנים

אנו מבחינים בין הסוגים הבאים של מידע גרסת נתונים:

  • מפיקים : קבצים בינאריים שמייצרים נתונים. ליצרנים יש גרסה ( producer ) וגרסת צרכן מינימלית שהם תואמים ( min_consumer ).
  • צרכנים : קבצים בינאריים שצורכים נתונים. לצרכנים יש גרסה ( consumer ) וגרסת יצרן מינימלית שהם תואמים ( min_producer ).

לכל פיסת נתונים עם גרסאות יש שדה VersionDef versions שמתעד את producer שיצר את הנתונים, ה- min_consumer שהוא תואם לו, ורשימה של גרסאות bad_consumers שאינן מותרות.

כברירת מחדל, כאשר מפיק יוצר נתונים מסוימים, הנתונים יורשים את גרסאות producer וה- min_consumer של היצרן. ניתן להגדיר bad_consumers אם ידוע כי גרסאות צרכנים ספציפיות מכילות באגים ויש להימנע מהן. צרכן יכול לקבל נתון אם כל הדברים הבאים נכונים:

  • consumer >= min_consumer של הנתונים
  • producer נתונים >= min_producer של הצרכן
  • consumer לא ב- bad_consumers של הנתונים

מכיוון שגם היצרנים וגם הצרכנים מגיעים מאותו בסיס קוד TensorFlow, core/public/version.h מכילה גרסת נתונים עיקרית אשר מטופלת producer או consumer בהתאם להקשר וגם כ- min_consumer ו- min_producer (נדרשת על ידי יצרנים וצרכנים, בהתאמה) . באופן ספציפי,

  • עבור גרסאות GraphDef , יש לנו TF_GRAPH_DEF_VERSION , TF_GRAPH_DEF_VERSION_MIN_CONSUMER ו- TF_GRAPH_DEF_VERSION_MIN_PRODUCER .
  • עבור גרסאות נקודת ביקורת, יש לנו TF_CHECKPOINT_VERSION , TF_CHECKPOINT_VERSION_MIN_CONSUMER ו- TF_CHECKPOINT_VERSION_MIN_PRODUCER .

הוסף תכונה חדשה עם ברירת מחדל לאופציה קיימת

ביצוע ההנחיות שלהלן נותן לך תאימות קדימה רק אם ערכת הפעולות לא השתנתה:

  1. אם תרצו תאימות קדימה, הגדר strip_default_attrs ל- True תוך כדי ייצוא המודל באמצעות שיטות tf.saved_model.SavedModelBuilder.add_meta_graph_and_variables ו- tf.saved_model.SavedModelBuilder.add_meta_graph של המחלקה SavedModelBuilder tf.estimator.Estimator.export_saved_model
  2. זה מסיר את תכונות ברירת המחדל המוערכות בזמן ייצור/ייצוא הדגמים. זה מוודא שה- tf.MetaGraphDef המיוצא לא מכיל את תכונת ה-op החדשה כאשר נעשה שימוש בערך ברירת המחדל.
  3. שליטה זו עלולה לאפשר לצרכנים לא מעודכנים (לדוגמה, הגשת קבצים בינאריים שאחרים לאימון בינאריים) להמשיך לטעון את המודלים ולמנוע הפרעות בהגשת המודל.

גרסאות GraphDef מתפתחות

סעיף זה מסביר כיצד להשתמש במנגנון ניהול גרסאות זה כדי לבצע סוגים שונים של שינויים בפורמט GraphDef .

הוסף אופציה

הוסף את האופציה החדשה הן לצרכנים והן ליצרנים בו זמנית, ואל תשנה אף גרסת GraphDef . סוג זה של שינוי תואם אוטומטית לאחור, ואינו משפיע על תוכנית התאימות קדימה מכיוון שסקריפטים קיימים של מפיק לא ישתמשו לפתע בפונקציונליות החדשה.

הוסף הפעלה והחלף עטיפות Python קיימות כדי להשתמש בה

  1. הטמע פונקציונליות צרכנית חדשה והגדל את גרסת GraphDef .
  2. אם אפשר לגרום לעוטפים להשתמש בפונקציונליות החדשה רק במקרים שלא עבדו קודם, ניתן לעדכן את העטיפות כבר עכשיו.
  3. שנה את עטיפות Python כדי להשתמש בפונקציונליות החדשה. אל תגדיל min_consumer , מכיוון שמודלים שאינם משתמשים באופציה זו לא אמורים להישבר.

הסר או הגבל את הפונקציונליות של הפעלה

  1. תקן את כל התסריטים של המפיק (לא TensorFlow עצמו) כדי לא להשתמש באופ או בפונקציונליות האסורים.
  2. הגדל את גרסת GraphDef והטמיע פונקציונליות צרכנית חדשה האוסרת את ההפעלה או הפונקציונליות שהוסרה עבור GraphDefs בגרסה החדשה ומעלה. אם אפשר, גרמו ל-TensorFlow להפסיק לייצר GraphDefs עם הפונקציונליות האסורה. לשם כך, הוסף את ה- REGISTER_OP(...).Deprecated(deprecated_at_version, message) .
  3. המתן לשחרור גדול למטרות תאימות לאחור.
  4. הגדל min_producer לגרסת GraphDef מ-(2) והסר את הפונקציונליות לחלוטין.

שנה את הפונקציונליות של מבצע

  1. הוסף אופציה דומה חדשה בשם SomethingV2 או דומה ועבור את תהליך הוספה והחלפת עטיפות Python קיימות לשימוש בו. כדי להבטיח תאימות קדימה השתמשו בבדיקות המוצעות ב- compat.py בעת שינוי העטיפות של Python.
  2. הסר את האופ הישן (יכול להתרחש רק עם שינוי גרסה גדול עקב תאימות לאחור).
  3. הגדל min_consumer כדי לשלול צרכנים עם ה-Op הישן, הוסף בחזרה את ה-Op הישן ככינוי עבור SomethingV2 , ועבור את התהליך כדי להחליף עטיפות Python קיימות לשימוש בו.
  4. עברו על התהליך להסרת SomethingV2 .

חסום גרסה צרכנית אחת לא בטוחה

  1. חבט בגרסת GraphDef והוסף את הגרסה הגרועה ל- bad_consumers עבור כל ה-GraphDefs החדשים. אם אפשר, הוסף ל- bad_consumers רק עבור GraphDefs המכילים אופציה מסוימת או דומה.
  2. אם לצרכנים קיימים יש את הגרסה הגרועה, דחוף אותם החוצה בהקדם האפשרי.