پرش به محتوای اصلی
پرش به محتوای مقاله

کتابخانه Kauldron گوگل جداسازی تنظیمات ML از کد را ممکن کرد

·۱۰ مهر ۱۴۰۵۱۸ دقیقه مطالعه
راهنما
راهنمای کدنویسی Kauldron گوگل: تنظیمات داده ساده، اتصال با رشته، و یک آموزش‌دهنده JAX قابل خواندن کامل
راهنمای کدنویسی Kauldron گوگل: تنظیمات داده ساده، اتصال با رشته، و یک آموزش‌دهنده JAX قابل خواندن کامل
اشتراک‌گذاری
واقعاً چه چیز جدید است؟

نوآوری اصلی در تفکیک کامل منطق اجرا از تعریف مدل از طریق سیم‌کشی رشته‌ای (String Wiring) است؛ به گونه‌ای که اجزای مدل بدون Import کردن یکدیگر، در زمان اجرا به هم متصل می‌شوند.

تغییر یک رشته متنی ساده در فایل تنظیمات اکنون می‌تواند جایگزین ساعت‌ها بازنویسی دستی کد در پژوهش‌های مبتنی بر JAX شود. گوگل ریسرچ (Google Research) کتابخانه Kauldron را منتشر کرد؛ ابزاری برای به حداکثر رساندن سرعت پژوهش که کل فرآیند آموزش — از بهینه‌ساز تا معماری مدل — را به شکل درختی از دیکشنری‌های ساده و تغییرپذیر می‌بیند.

پژوهش‌های مدرن یادگیری ماشین اغلب دچار «پراکندگی تنظیمات» (config sprawl) می‌شوند؛ وضعیتی که در آن ابرپارامترها (Hyperparameter) — شبیه به پیچ‌های تنظیم یک دستگاه رادیو قدیمی که هر کدام روی کیفیت صدا اثر می‌گذارند — در کلاس‌های تودرتو یا مستقیماً درون تعریف مدل دفن شده‌اند. این چالش با مفاهیم بنیادی‌تر ساختار مدل‌ها گره خورده است؛ همان‌طور که در بررسی ارکان تبدیل ریاضیات به هوش مصنوعی اشاره کردیم، پیکربندی در کنار وزن‌ها و توکن‌سازها، یکی از ستون‌های اصلی شکل‌دهی به هوش مصنوعی است. همان‌طور که در تحلیل قبلی ما درباره‌ی اینکه گوگل ریسرچ چگونه از خودبهبودی منظم (regularized self-improvement) برای کاهش بیش‌برازش در عامل‌های هوش مصنوعی استفاده می‌کند اشاره کردیم، Kauldron جنبه‌ی ساختاری این مشکل را هدف قرار داده است. این کتابخانه منطق «چگونه آموزش دهیم» را از کدهای پایتون خارج کرده و به یک لایه‌ی داده‌ای منتقل می‌کند که قابل تبدیل به JSON و تغییر از طریق دستورات خط فرمان است.

سامانه تنظیمات داده‌محور

در قلب Kauldron، سیستمی به نام konfig قرار دارد که درخت‌های فراخوانی پایتون را به دیکشنری‌های ساده تبدیل می‌کند. طبق مستندات این پروژه، وقتی محققی کتابخانه‌ای مانند Optax را در بلوک konfig.imports() وارد می‌کند، سیستم بلافاصله یک شیء بهینه‌ساز نمی‌سازد. در عوض، یک ConfigDict ایجاد می‌کند که نام تابع و آرگومان‌های آن را ذخیره می‌کند.

برای مثال، فراخوانی optax.adam(learning_rate=0.003) در این بلوک، به‌جای یک بهینه‌ساز فعال، یک ConfigDict برمی‌گرداند. این تنظیمات تغییرپذیر است؛ محقق می‌تواند مقدار cfg.learning_rate = 1e-4 را تغییر دهد و تنها در لحظه نهایی با دستور konfig.resolve(cfg)، شیء واقعی را ایجاد کند. این رویکرد تضمین می‌کند که تنظیمات تا لحظه اجرا، صرفاً «داده» باقی بمانند.

به دلیل اینکه این تنظیمات دیکشنری‌های تودرتو هستند، زنجیره‌های پیچیده بهینه‌ساز (Optimizer) — برای مثال زنجیره‌ای که clip_by_global_norm(1.0)، scale_by_adam(b2=0.99) و scale_by_learning_rate(0.003) را با هم ترکیب می‌کند — را می‌توان به JSON صادر کرد و دوباره به‌طور کامل بازسازی نمود. این یعنی دیگر نیازی به کلاس‌های پایه، سیستم‌های ثبت (registries) یا دکوراتورهای پیچیده در کتابخانه‌های مورد استفاده نیست. در واقع، کتابخانه‌ای مثل Optax اصلاً نمی‌داند konfig وجود دارد.

یکی از حیاتی‌ترین قابلیت‌ها، cfg.ref است. در سیستم‌های سنتی، اگر زمان‌بندی نرخ یادگیری به تعداد کل گام‌های آموزش وابسته باشد، تغییر گام‌ها مستلزم به‌روزرسانی دستی زمان‌بندی است. Kauldron از ارجاعات استفاده می‌کند؛ یک زمان‌بندی کاهش کسینوسی (warmup-cosine decay) می‌تواند decay_steps خود را به cfg.ref.num_train_steps متصل کند، به‌جای اینکه از یک مقدار سخت‌افزاری مثل ۱۰۰۰ استفاده کند. اگر محقق گام‌ها را از ۱۰۰۰ به ۲۰۰ تغییر دهد، زمان‌بندی به‌طور خودکار در لحظه اجرا بازسازی می‌شود. بدون این واسط، یک جست‌وجوی گسترده روی گام‌های آموزش منجر به نتایجی می‌شد که روی منحنی‌های اشتباه آموزش دیده‌اند و اعداد آن‌ها هرچند باورپذیر، اما از نظر ریاضی غلط است.

جداسازی از طریق سیم‌کشی رشته‌ای

Kauldron از مکانیزمی به نام kontext برای اتصال اجزایی استفاده می‌کند که نباید از وجود یکدیگر باخبر باشند. به‌جای اینکه یک تابع زیان برای امتیازدهی به خروجی‌ها، مدل را وارد (import) کند، اجزا از طریق مسیرهای کلیدی رشته‌ای به هم متصل می‌شوند.

مکانیزم‌های Kontext:

  • زمینه به مثابه داده: یک زمینه (Context) داده‌های تودرتوی معمولی است. مسیری مانند batch.image یا preds.aux[0].pos مستقیماً به کلیدهای دیکشنری، ویژگی‌ها (attributes) و ایندکس‌های لیست دسترسی پیدا می‌کند.
  • حاشیه‌نویسی کلیدها: هر شیئی می‌تواند ورودی‌های خود را با برچسب kontext.Key تعریف کند.
  • تفکیک (Resolution): تابع resolve_from_keyed_obj دقیقاً همان مسیرها را از زمینه استخراج کرده و به‌عنوان آرگومان‌های کلیدی (keyword arguments) به تابع تحویل می‌دهد.

به عنوان مثال، یک معیار ارزیابی را می‌توان طوری تنظیم کرد که پیش‌بینی‌ها را در مسیر preds.logits و اهداف را در batch.label جست‌وجو کند. در این حالت، معیار هرگز مدل را وارد نمی‌کند و مدل هم خبری از معیار ندارد. تغییر مسیر یک معیار به یک تنسور دیگر، به سادگی تغییر یک رشته در فایل تنظیمات است. اگر مسیری نامعتبر باشد، kontext یک KeyError صادر می‌کند که دقیقاً لیست می‌کند چه داده‌هایی در دسترس بوده‌اند.

این جداسازی تا لایه‌های داخلی مدل نیز پیش می‌رود. با استفاده از متغیرهای میانی ثبت‌شده در Flax، محقق می‌تواند نرم یک لایه داخلی را با ارجاع به مسیری مثل interms.enc.__call__[0] رصد کند. این یعنی نظارت بر فعال‌سازهای داخلی مدل بدون اضافه کردن حتی یک خط کد لاگ‌گذاری به متد __call__ مدل امکان‌پذیر است. این رویکرد در مدیریت متمرکز داده‌ها و زمینه‌ها شباهت زیادی به استراتژی‌های مقیاس‌پذیر دارد؛ همان‌طور که در تحلیل مدیریت Context در مقیاس سازمانی بررسی کردیم، تفکیک صحیح زمینه‌ها برای عملیاتی کردن مدل‌های زبانی در سطح سازمان حیاتی است.

ایمنی شکل در زمان اجرا

برای جلوگیری از خطاهای رایج «عدم تطابق شکل» (shape mismatch) که توسعه با JAX را دشوار می‌کند، Kauldron ماژول ktyping را پیاده کرده است. این ماژول بررسی شکل داده‌ها را در زمان اجرا با استفاده از محورهای نام‌گذاری‌شده انجام می‌دهد.

به‌جای مقایسه تاپل‌های بی‌نام مثل (2, 16, 8)، محققان توابع را با محورهای نام‌دار مانند Float['*b n c'] و Float['c d'] حاشیه‌نویسی می‌کنند. دکوراتور مربوطه، هر نام محور را در اولین مشاهده ثبت کرده و این پیوند را در تمام آرگومان‌ها و مقدار بازگشتی اجرا می‌کند.

اگر عدم تطابقی رخ دهد — مثلاً محور c در آرگومان اول ۸ باشد اما در آرگومان دوم ۵ باشد — سیستم فقط خطای شکل نمی‌دهد، بلکه یک بلوک «ابعاد استنتاج‌شده» (Inferred Dims) چاپ می‌کند. این بلوک دقیقاً نام محوری که باعث اختلاف شده را می‌گوید (مثلاً: "c already bound to 8, got 5") و یک جلسه عیب‌یابی طولانی را به یک اصلاح تک‌خطی تبدیل می‌کند. در مدل‌هایی که چندین تنسور همزمان در جریان هستند، این قابلیت نیاز به ردیابی دستی تاپل‌های بی‌نام را از بین می‌برد.

مدیریت وضعیت و Trainer

شیء kd.train.Trainer به‌عنوان چسب بین مدل، خط لوله داده، توابع زیان و بهینه‌ساز عمل می‌کند. این ابزار به‌گونه‌ای طراحی شده است که بسیار سبک باشد و خروجی‌های کمکی (مانند معیارها) را تنها در صورتی که صراحتاً درخواست شده باشد (مثلاً return_losses=True و return_metrics=True) تولید کند تا زمان پردازش در دستگاه کاهش یابد.

پیاده‌سازی تابع زیان و معیارها:

  • توابع زیان: یک تابع زیان سفارشی، مانند پیاده‌سازی LogCosh را می‌توان به صورت یک dataclass منجمد با فیلدهای kontext.Key تعریف کرد. این تابع متد get_values را برای بازگرداندن یک آرایه به ازای هر المان پیاده می‌کند؛ سپس چارچوب Kauldron خودش عملیات کاهش (reduction) و اعمال آرگومان وزن (مثلاً weight=0.5 که نتیجه را دقیقاً نصف می‌کند) را مدیریت می‌کند.
  • معیارها: یک معیار در Kauldron به‌جای یک عدد ساده، یک وضعیت (State) برمی‌گرداند که قابل ادغام است.
  • ادغام وضعیت: با استفاده از kd.metrics.sum_field() برای ردیابی جداگانه صورت و مخرج (مثلاً n_hit و n_total)، نتیجه نهایی فارغ از اندازه دسته‌ها (batch size) دقیق باقی می‌ماند.

این موضوع برای مدیریت دسته‌های «ناهمگون» (ragged) در پایان هر Epoch حیاتی است. اگر یک معیار روی یک دسته ۶ ردیفی و سپس روی یک دسته ۲ ردیفی محاسبه شود، ادغام وضعیت‌ها نتیجه‌ای دقیق می‌دهد، در حالی که میانگین گرفتن ساده از نرخ‌های هر دسته، از نظر ریاضی غلط است. این مکانیزم ادغام تجمعی (associative merge) همچنین اجازه می‌دهد Kauldron معیارها را در چندین دستگاه مختلف بدون نگرانی از ترتیب رسیدن نتایج، تجمیع کند.

سرعت پژوهش در عمل

مزیت عملی این معماری در زمان «جست‌وجوی ابرپارامترها» (Hyperparameter Sweeps) آشکار می‌شود. چون کل آزمایش یک تنظیمات (config) است، یک sweep صرفاً یک حلقه روی تغییرات تنظیمات است.

در یک نمایش اخیر با استفاده از یک مجموعه داده رگرسیون مصنوعی (تولید شده توسط np.random.default_rng)، پنج آزمایش مجزا اجرا شد که شامل موارد زیر بود:
۱. اجرای پایه (Baseline).
۲. کاهش عرض مدل به hidden=4.
۳. افزایش عرض مدل به hidden=128.
۴. افزایش نرخ یادگیری به ۰.۱.
۵. جایگزینی کامل بهینه‌ساز Adam با optax.sgd(0.05).

تمام این موارد بدون تغییر حتی یک کاراکتر در کد مدل MLP یا تابع زیان LogCosh یا کد حلقه آموزش اجرا شدند. هر نسخه با یک ویرایش تک‌خطی در ConfigDict ایجاد شد و سپس به یک Trainer منجمد تبدیل گشت. در خط فرمان، این تغییرات به‌صورت فلگ‌هایی مثل --cfg.model.hidden=128 نوشته می‌شوند.

حفاظ‌ها و پایداری

برای حفظ یکپارچگی، Kauldron تخصیص اشیاء اجراشده (مانند یک ماژول فعال Flax) را درون ConfigDict به‌شدت ممنوع کرده است. اگر محققی این کار را امتحان کند، سیستم بلافاصله یک ValueError صادر می‌کند. این کار تضمین می‌کند که هر تنظیماتی قابل سریال‌سازی، قابل مقایسه (diff) و قابل تغییر از خط فرمان باشد. یک تنظیمات نیمه‌پردازش‌شده (half-resolved) قابل سریال‌سازی نیست، بنابراین سیستم به‌جای شکست در مراحل بعدی که ردیابی‌شان سخت است، کل این وضعیت را از ابتدا رد می‌کند.

این انضباط به زیر-اشیاء نیز تسری می‌یابد. برای مثال، kd.data.InMemoryPipeline و kd.evals.Evaluator فیلدهای بذر (seed) و مجموعه داده (ds) خود را به صورت پیش‌فرض به تنظیمات ریشه (_FakeRootCfg) ارجاع می‌دهند. این فیلدها هنگام ساخت شیء در Trainer پر می‌شوند، اما اگر شیء به‌صورت مستقل ساخته شود، باید صراحتاً مقداردهی شوند.

برای کارهای طولانی‌مدت، Kauldron از Checkpointer و Evaluator استفاده می‌کند. ارزیاب، مدل و توابع زیان را از تنظیمات ریشه به ارث می‌برد و تنها به یک مجموعه داده و زمان‌بندی (مثلاً kd.evals.EveryNSteps(100)) نیاز دارد. اگر یک اجرای موقت (preemptible) متوقف شود، متد train() به‌طور خودکار آخرین نقطه بازرسی را در دایرکتوری کاری (مثلاً /tmp/kauldron_resume) پیدا کرده و دقیقاً از همان گام متوقف‌شده ادامه می‌دهد. در یک تست، مدل آموزش‌دیده تا گام ۲۰۰، برای ۳۰۰ گام بازسازی شد و نوار پیشرفت به‌درستی از ۲۰۰ شروع شد، نه از صفر.

این معماری بار مدیریت آزمایش را از دوش برنامه‌نویس به دوش تنظیمات منتقل می‌کند. گوگل ریسرچ با تبدیل خط لوله ML به یک گراف داده‌محور به‌جای یک اسکریپت سخت‌افزاری، قصد دارد اصطکاک بین یک فرضیه و تست تجربی آن را به حداقل برساند.

گام بعدی شما

  • اگر از JAX یا Flax استفاده می‌کنید، ساختار ConfigDict را برای جایگزینی کلاس‌های تنظیمات سخت‌افزاری بررسی کنید.
  • برای عیب‌یابی سریع‌تر ابعاد تنسورها، سیستم نام‌گذاری محورهای ktyping را در توابع خود پیاده کنید.
  • برای اجرای Sweepهای سریع، تنظیمات مدل خود را به فرمت JSON درآورید تا بتوانید آن‌ها را از خط فرمان مدیریت کنید.

اما داستان سخت‌افزاری این تحول حتی شگفت‌انگیزتر است — به تحلیل ما درباره‌ی تراشه‌های Blackwell مراجعه کنید.

چرا این موضوع مهم است؟

این ابزار با حذف نیاز به بازنویسی کد برای هر تغییر کوچک، سرعت تکرار فرضیات را در محیط‌های پژوهشی به شدت افزایش می‌دهد. اعتبار این رویکرد از تجربه گوگل در مدیریت هزاران آزمایش هم‌زمان در مقیاس صنعتی می‌آید.

تأثیر برای ایران

این کتابخانه ابزاری رایگان و متن‌باز برای پژوهشگران ایرانی است تا بدون نیاز به زیرساخت‌های پیچیده، مدیریت آزمایش‌های ML خود را استاندارد کنند.

·نگاه ما
تحریریه دات‌هوش

Kauldron در واقع تلاش می‌کند «مهندسی نرم‌افزار» را به «پژوهش ML» تزریق کند. با تبدیل کد به داده، گوگل در حال تبدیل مدل‌های یادگیری ماشین به موجوداتی است که می‌توانند بدون بازنویسی کد، توسط سیستم‌های خودکار (AutoML) یا عامل‌های هوش مصنوعی بازپیکربندی شوند. این یک گام بزرگ به سمت حذف دستی‌ترین بخش‌های چرخه پژوهش است.

منابع

این گزارش با خط‌لولهٔ خودکار دات‌هوش از منابع معتبر جهانی تدوین و زیر نظر تحریریه منتشر شده است. روش کار ما

گفتگو

پنج‌شنبه‌های هوش‌محور

بسته‌ی هفتگی دات‌هوش

۵ خبر، ۲ ابزار، ۱ پرامپت در هر شماره. به‌زودی راه‌اندازی می‌شود — هر پنج‌شنبه صبح.

خبر کلیدی
ابزار کاربردی
پرامپت حرفه‌ای
تحلیل پژوهش
به‌زودی
زاویه‌ی ایرانی
به‌زودی
تمرین این هفته
به‌زودی

راهنماهای دات‌هوش

راهنماهای کاربردیِ دات‌هوش برای کار با هوش مصنوعی — از همین‌جا شروع کنید:

دات‌هوش

راهنمای فارسی هوش مصنوعی — با نگاه به ایران

اخبار روزانه، معرفی ابزارها و مدل‌ها، و آموزشِ کار با هوش مصنوعی؛ همیشه با این پرسش که از ایران چه چیزی کار می‌کند و چه چیزی نه.