اخیرا در جوامع آنلاین صحبت هایی در مورد زبان های جایگزین Python برای محاسبات علمی و ماشین لرنیگ مطرح است. در میان انتخابهای پیشنهادی، زبان Julia به ویژه جلب توجه میکند. Julia توسط محققان MIT، جف بزانسون، استفان کارپینسکی، آلن ادلمن و ویرال بی شاه در سال 2009 طراحی و در سال 2012 برای عموم منتشر شد. این زبان تعاملی بودن زبانهایی مانند Python و R را با سرعت زبانهایی مانند C و Fortran ترکیب میکند. این باعث میشود Julia به طور منحصر به فردی برای زمینه هایی مانند ماشین لرنینگ (ML) مناسب باشد. جایی که محققان باید به سرعت آزمون و خطا کنند، اما همچنین میخواهند مدل نهایی آنها سریع اجرا شود.
یکی از هیجان انگیر ترین بخش های زبان Julia، کتابخانه Flux.jl است. Flux یک کتابخانه شبکه عصبی منعطف است که به لطف سینتکس ریاضی مانند Julia استفاده از آن بسیار راحت است، اما میتواند به کدهای سریع کامپایل شود. در نتیجه، Julia قادر است با سرعتی که با زبانهای کامپایل شده و استاتیک رقابت میکنند، سرعت توسعه را در یک زبان دینامیک مانند Python ارائه دهد. در این پست، ما به Flux میپردازیم و خواهیم دید که چگونه یک تجربه عالی از توسعه شبکه های عصبی را ارائه میدهد.
Flux.jl
Flux مجموعهای از ابزارها را برای ساخت و آموزش شبکههای عصبی فراهم میکند که از نقاط قوت Julia (از جمله سرعت، سینتکس شبه ریاضی، داینامیک بودن و پشتیبانی از کامپایلر) بهره میبرد. این کتابخانه تعریف مدلها را با استفاده از آرایهها و ماتریس های Julia و آسان میکند و شما را مجبور به استفاده از ساختارهای داده اختصاصی فریمورک مانند Pytorch و TensorFlow نمیکند. این امر از کپی و الوکیشن غیر ضروری داده ها به مقدار زیادی جلوگیری میکند.
علاوه بر این Flux پشتیبانی از Automatic differentiation (مشتق گیری الگوریتمی و خودکار) را فراهم میکند و شما را قادر میسازد تا انواع لایه ها و تابع های Loss را به راحتی نعریف کنید. همچنین، حلقه آموزش مدل را میتوان با استفاده از لوپ های Julia، بدون نیاز به DSL های خاص، پیاده سازی کرد. به طور کلی، Flux یک روش سبک و جولیایی:) برای ساخت مدل های یادگیری عمیق ارائه میدهد و از قابلیت های Julia را برای سیستم های ML استفاده میکند.
بررسی دیتاست MNIST: ساخت یک شبکه عصبی ساده
برای نشان دادن چگونگی تعریف و آموزش مدل ها با Flux، بیایید تا با استفاده از دیتاست MNIST یک مدل را آموزش دهیم. MNIST یک دیتاست معیار، متشکل از 70000 تصویر سیاه سفید از ارقام به صورت دست نویس است. هدف، آموزش مدلی برای تشخیص رقم موجود در یک تصویر است. در عین سادگی، MNIST بستر خوبی برای ارزیابی فریم ورک های مختلف است. در این مثال ما دیتاست MNIST را لود کرده و پیش پردازش های لازم را انجام میدهیم، یک شبکه عصبی MLP تعریف میکنیم، الگوریتم بهینه سازی را تنظیم میکنیم و حلقه آموزش را پیاده سازی میکنیم. خواهیم دید که Flux علاوه بر ارائه دادن ماکرو ها و توابعی برای سادگی و مختصر بودن کد به خوبی با کد Julia ترکیب میشود. این سادگی API ها به همراه کارایی Julia، به ما امکان پیاده سازی و آموزش سریع مدل را خواهد داد.
حالا وقت آن رسیده که به کد بپردازیم:
نصب و ایمپورت کردن کتابخانه های لازم
ابتدا کتابخانه Flux و MLDatasets را نصب و سپس آن هارا ایمپورت میکنیم. کتابخانه MLDatasets دیتاست های معیار مختلفی مانند MNIST، CIFAR10 و Iris را ارائه میدهد و دانلود و استفاده از دیتاست ها را آسان میکند.
بارگزاری دیتاست MNIST
سپس با اسفاده از MNIST
، دیتاست را بارگزاری میکنیم. این wrapper به ما امکان مشخص کردن مکان دانلود/لود کردن داده، تایپ، و پارتیشن مد نظر از داده را میدهد.
پیش پردازش داده ها
به این دلیل که معماری MLP را برای مدل خود انتخاب کرده ایم، نیاز است که تصاویر را پیش پردازش کنیم. تصاویر بصورت یک ماتریس دو بعدی ارائه میشوند. با استفاده از تابع flatten
این ماتریس ها را به آرایه های تک بعدی تبدیل میکنیم. سپس زمان پیش پردازش لیبل ها است. لیبل هر تصویر که یک عدد از 0 تا 9 است با استفاده از تابع onehotbatch
به نمایش one-hot encoded تبدیل میشود که یکی از مراحل پیش پردازش معمول داده در حل مسائل Classification است.
تعریف مدل MLP
در Flux میتوان با استفاده از Chain
، به راحتی لایه هارا پشت هم قرار داده و شبکه عصبی مد نظر را تعریف کنیم. در اینجا ما یک شبکه عصبی ساده با 3 لایه 128، 64 و 10 نورونی تعریف میکنیم. تابع فعال سازی دو لایه اول ReLU است و بعد از لایه سوم تابع فعال سازی Softmax قرار گرفته که به طور معمول در حل مسائل Multiclass classification مانند مسئله ما استفاده میشود.
تعریف توابع Loss و دقت
در این قسمت با استفاده از تابع crossentropy
و onecold
از Flux و تابع mean
از Statistics دو تابع Loss و دقت را تعریف میکنیم. تابع loss پیش بینی مدل را با لیبل صحیح مقایسه کرده و cross-entropy Loss را خروجی میدهد. تابع accuracy برای بررسی دقت مدل تعریف شده است. این تابع محاسبه میکند که چگونه پیش بینی های یک مدل با لیبل های صحیح برای مجموعه ای از داده های ورودی مطابقت دارد.
انتخاب و تنظیم الگوریتم بهینهسازی
در این قسمت ما الگوریتم بهینهسازی را انتخاب و تنظیم میکنیم. در اینجا مشاهده میکنید که ما Adam را انتخاب کرده ایم و نرخ یادگیری را 0.001 تنظیم کرده ایم. امکان تنظیم دیگر هایپرپارامتر ها نیز وجود که برای حفظ سادگی به آن نمیپردازیم.
ارزیابی اولیه
قبل از آموزش مدل بیاید تا دقت و Loss مدل را چک کنیم:
حلقه آموزش
حالا حلقه آموزش مدل را پیاده سازی میکنیم. در این حلقه ما مدل را برای صد هزار epoch آموزش میدهیم و دقت و Loss مدل را هر ده هزار epoch بررسی میکنیم. مشاهده میکنید که حلقه های آموزش را میتوان بدون کاهش سرعت با اسفاده از لوپ های Julia نوشت. درون حلقه مشاهده میکنید که تمامی مراحل مربوط به آموزش مدل با استفاده از تابع !train
انجام شده است. البته در صورتی نیاز به کنترل بیشتر، Flux دارای توابعی برای کنترل بیشتر و مرحله به مرحله فرایند آموزش است. همچنین امکان استفاده از کتابخانه ProgressMeter برای مشاهده اینکه در epoch چندم هستیم موجود است. همچنین پیگیری آموزش مدل و پارامتر های مختلف میتواند با استفاده از Tensorboard و کتابخانه های TensorBoardLogger و Logging انجام شود.
پیاده سازی شبکه های عصبی پیچیده تر
در حالی که مثال MNIST ما اصول اولیه را نشان میدهد، پتانسیل Flux در ساخت مدل های پیچیده تر دیده میشود. Flux ترکیب لایههای مختلف را با ارائه پیاده سازی هایی برای معماری های پیچیده تر مانند لایه های convolutional، recurrent، LSTM و Multi-Head Attention ساده میکند. اما در عین حال به شما اجازه تعریف لایه های سفارشی خود به صورت توابع Julia را میدهد. Flux با پشتیبانی ذاتی جولیا از Automatic differentiation، به طور خودکار Gradient ها را مدیریت میکند. این به شما امکان میدهد توابع سفارشی Loss، regularizer ها و لایهها پیادهسازی کنید و Flux در پشت صحنه محاسبات خودکار و بهینه سازی های لازم را انجام میدهد. نتیجهی آن یک چارچوب مدلسازی بسیار انعطافپذیر و ترکیبپذیر است که برای معماریهای شبکهی عصبی پیچیده کاملا مناسب است.
محدودیت های Flux
علارغم اینکه کتابخانه Flux هم سن کتابخانه Pytorch است، مستندات و مدل های از پیش آموزش دیده بسیار محدود تری برخوردار است. این مسئله به دلیل کامیونیتی کوچک تر Julia نسبت به کامیونیتی Python و فریمورک های آن زبان است. اخیرا Julia بیش از قبل مورد توجه برنامه نویس ها قرار گرفته که توسعه Flux را به عنوان بخشی از اکوسیستم در حال رشد Julia سرعت میبخشد. با عملکرد عالی و طراحی ای که از نقاط قوت Julia استفاده میکند، Flux پتانسیل تبدیل شدن به یک فریمورک پیشرو در فصل بعدی از تحقیق و توسعه در حوزه یادگیری عمیق را دارد.
جمعبندی
در این پست دیدیم که چگونه Flux ساخت و آموزش شبکه های عصبی را در جولیا ممکن میکند. Flux با استفاده از ویژگیهای Julia مانند multiple dispatch و سینتکس ریاضی مانند، یک تجربه متمایز را ارائه میکند. این باعث میشود که توسعه شبکه های عصبی ساده و قابل درک شود.
مدلهای Flux را میتوان با ترکیب لایهها و توابع تعریف کرد، در حالی که به لطف کامپایلر Julia همچنان به کدهای بهینه شده کامپایل میشوند. Flux از Automatic differentiation پشتیبانی میکند که امکان تعریف لایه های سفارشی، توابع Loss و موارد دیگر را بدون نیاز به محاسبه دستی Gradient هارا فراهم میکند.
ما مراحل لود کردن داده، پیش پردازش داده ها، تعریف مدل و آموزش آن را با استفاده از Flux بررسی کردیم و مشاهده کردیم که API های این کتابخانه به خوبی با لوپ ها و توابع Julia ادغام میشود و یک سیتم مدلینگ روان ایجاد میکند.
در حالی که Flux هنوز در حال بلوغ است، پتانسیل عظیمی به عنوان بخشی از اکوسیستم رو به رشد ماشین لرنیگ در Julia نشان میدهد. طراحی این کتابخانه که از نقاط قوت Julia بهره میبرد، میتواند Julia را به عنوان یک زبان رده اول برای دیپ لرنینگ و ماشین لرنینگ مطرح کند.
در این پست فقط به بخشی از آنچه که با Flux امکان پذیر است پرداختیم. برای کسب اطلاعات بیشتر، مستندات، مثالها و صفحه اکوسیستم Flux را بررسی کنید. انجمن دوستانه Discourse زبان Julia همچنین مکانی عالی برای پرسیدن سوالات و بحث در مورد پروژه های مبتنی بر Julia و Flux است.
آیا از Flux در پروژه های خود استفاده کرده اید؟ تجربه استفاده از Julia و Flux از چه جهاتی با دیگر فریمورک ها متفاوت است؟ تجربیات و نظرات خود را با ما در میان بگذارید!
on Flux.jl، ماشین لرنینگ در زبان Julia