
এই প্রকল্পটি কী করে
self-driving-car হলো সরল JavaScript-এ লেখা একটি компакт স্বয়ংক্রিয়-ড্রাইভিং সিমুলেশন। একটি ছোট নিউরাল নেটওয়ার্ক বিবর্তনের মাধ্যমে শেখে কীভাবে বাঁকানো তিন-লেনের মহাসড়কে চলতে হয়, নিজের লেন ধরে রাখতে হয়, ট্রাফিকের জন্য ব্রেক করতে হয়, সংকেত দিতে হয়, ধীরগতির গাড়িকে ওভারটেক করতে হয় এবং উপযুক্ত সময়ে ডানদিকে ফিরতে হয়।
সঠিক আচরণ দেখানোর জন্য কোনো উদাহরণ ড্রাইভার নেই। এর পরিবর্তে, প্রতিটি প্রজন্ম একই রাস্তায় নিউরাল নেটওয়ার্কের একটি জনসংখ্যা পাঠায়। যে নেটওয়ার্কগুলো সবচেয়ে বেশি দূরত্ব অতিক্রম করে, তারা বেশি ফিটনেস স্কোর পায় এবং পরবর্তী প্রজন্মের অভিভাবক হয়।
প্রকল্পটিতে রাস্তা, গাড়ির পদার্থবিদ্যা, পারসেপশন, ট্রাফিক, নিউরাল নেটওয়ার্ক, জেনেটিক অ্যালগরিদম, প্ল্যানার, রেন্ডারিং এবং ব্যবহারকারী ইন্টারফেস নিয়ে প্রায় ১,৩০০ লাইনের ES মডিউল রয়েছে। রানটাইমে কোনো নির্ভরতা নেই, এবং একই সিমুলেশন মডিউল ব্রাউজার ও Node.js উভয় পরিবেশেই চলে।
প্রশিক্ষিত ড্রাইভার দেখতে, ব্রাউজারে একটি জনসংখ্যার বিবর্তন ঘটাতে অথবা নিজে গাড়ি চালাতে লাইভ ডেমো খুলুন।
ড্রাইভিং সিস্টেম কীভাবে কাজ করে
সিমুলেশনটি প্রতি সেকেন্ডে নির্দিষ্ট ৬০টি ধাপে এগোয়। প্রতিটি ধাপে গাড়িটি কাছাকাছি লেনগুলো স্ক্যান করে, পর্যবেক্ষণগুলোকে নিউরাল নেটওয়ার্কের ১৯টি ইনপুটে রূপান্তর করে এবং দুটি আউটপুট তৈরি করে: একটি প্যাডেল কমান্ড এবং একটি অনুরোধকৃত লেন।
পারসেপশন ও নিউরাল নেটওয়ার্ক
নেটওয়ার্কটি ক্যামেরার পিক্সেল বা কাঁচা দূরত্ব-রশ্মি প্রক্রিয়া করে না। এটি এমন কাঠামোবদ্ধ তথ্য গ্রহণ করে, যা কোনো পারসেপশন স্ট্যাক ড্রাইভিং প্ল্যানারকে দিতে পারে:
- বাম, বর্তমান ও ডান লেন বিদ্যমান কি না।
- প্রাসঙ্গিক প্রতিটি লেনে সামনে ও পেছনে থাকা নিকটতম গাড়ি।
- প্রতিটি ফাঁক কত দ্রুত সংকুচিত হচ্ছে।
- শিক্ষণরত গাড়িটির বর্তমান গতি।
- পরবর্তী ১০০ মিটারে থাকা সবচেয়ে তীক্ষ্ণ বাঁক।
- লেন পরিবর্তন প্ল্যানারের বর্তমান অবস্থা।
আর্কিটেকচারটি 19 · 12 · 8 · 2, tanh অ্যাক্টিভেশন ব্যবহার করে এবং এতে ৩৬২টি ওজন রয়েছে। একটি আউটপুট প্যাডেল নিয়ন্ত্রণ করে। অন্যটি একটি লেন নির্বাচন করে: +0.5-এর বেশি মান বামদিকের লেনের অনুরোধ করে, আর -0.5-এর কম মান ডানদিকের লেনের অনুরোধ করে।
প্ল্যানার ও গাড়ির মডেল
নিউরাল নেটওয়ার্ক সিদ্ধান্ত নেয় কখন এবং কোথায় যেতে হবে, কিন্তু সরাসরি স্টিয়ার করে না। হাতে লেখা একটি প্ল্যানার লেনের অনুরোধকে নিরাপদ ও মসৃণ কৌশলে রূপান্তর করে। এটি ০.৭ সেকেন্ড সংকেত দেয়, লক্ষ্য লেন পরীক্ষা করে, ২.৬ সেকেন্ড ধরে একটি কুইন্টিক S-কার্ভ অনুসরণ করে এবং পরিকল্পিত পথ ধরে চলতে pure-pursuit স্টিয়ারিং ব্যবহার করে।
অন্য কোনো যান গাড়িটির সমান্তরালে থাকলে বা তার ব্লাইন্ড স্পটে ঢোকার পথে থাকলে, প্ল্যানার সংকেত দিতে থাকে এবং ফাঁক তৈরি হওয়ার অপেক্ষা করে। সংকেত দেওয়ার পর্যায়ে অনুরোধ ছেড়ে দিলে কৌশলটি বাতিল হয়।
গাড়িটি নিজে SI এককে একটি কাইনেম্যাটিক বাইসাইকেল মডেল ব্যবহার করে। এর পরামিতিগুলো একটি ফ্যামিলি হ্যাচব্যাকের মতো: দৈর্ঘ্য ৪.৪ মিটার, ০ থেকে ১০০ কিমি/ঘণ্টায় যেতে ৯.৮ সেকেন্ড, সর্বোচ্চ গতি ১১৫ কিমি/ঘণ্টা এবং সর্বোচ্চ ৮ m/s² ব্রেকিং। উপলভ্য কর্নারিং গ্রিপ নির্ধারণ করে এটি কত দ্রুত বাঁক নিতে পারবে।
ট্রাফিক, ফিটনেস ও বিবর্তন
পেছনের ট্রাফিক Intelligent Driver Model অনুসরণ করে। গাড়িগুলোর কাঙ্ক্ষিত গতি ৬১ থেকে ৯৪ কিমি/ঘণ্টার মধ্যে, তারা বামদিক দিয়ে ওভারটেক করে, পাশ কাটানোর পর ডানদিকে ফিরে আসে, লেন পরিবর্তনের আগে সংকেত দেয় এবং শিক্ষণরত গাড়িটির প্রতিক্রিয়া অনুসরণ করে।
ফিটনেস মূলত অতিক্রম করা মিটারের সংখ্যা। কোনো গাড়ি দুর্ঘটনায় পড়লে বা রাস্তা ধরে এগিয়ে আসা ধীরগতির সারির দ্বারা ধরা পড়লে ৩০০ পয়েন্ট হারায়। ডানদিকের লেনটি স্পষ্টভাবে ফাঁকা থাকা অবস্থায় বাম লেনে কাটানো প্রতি সেকেন্ডের জন্য আরও চার মিটার হারায়। সরাসরি ওভারটেক করার কোনো পুরস্কার নেই; ওভারটেক কার্যকর হয় কারণ এর ফলে গাড়িটি বেশি দূরত্ব অতিক্রম করতে পারে।
বিবর্তনে চারটি প্রধান কৌশল ব্যবহার করা হয়:
- এলিটিজম: কমান্ড-লাইন প্রশিক্ষণে সেরা চারটি নেটওয়ার্ক কোনো পরিবর্তন ছাড়াই পরবর্তী প্রজন্মে যায়।
- টুর্নামেন্ট নির্বাচন: শক্তিশালী নেটওয়ার্কগুলোর অভিভাবক হওয়ার সম্ভাবনা বেশি।
- BLX-0.25 ক্রসওভার: সন্তান তৈরির জন্য অভিভাবকদের ওজন মিশ্রিত করা হয়।
- গাউসিয়ান মিউটেশন: ৪০ প্রজন্মের অর্ধ-জীবন অনুযায়ী মিউটেশনের হার ও মাত্রা কমে।
ইনস্টলেশন ও স্থানীয় সেটআপ
রিপোজিটরি ক্লোন করে এর স্থানীয় স্ট্যাটিক সার্ভার চালু করুন:
git clone https://github.com/Stxqq/self-driving-car.git
cd self-driving-car
npm run serve
serve কমান্ডটি ৫১০১ পোর্টে একটি Python HTTP সার্ভার চালু করে। আপনার ব্রাউজারে http://localhost:5101 খুলুন।
কোনো প্যাকেজ ইনস্টল করার প্রয়োজন নেই। যেকোনো স্ট্যাটিক ওয়েব সার্ভার প্রকল্পটি হোস্ট করতে পারে, তবে সরাসরি file:// দিয়ে পৃষ্ঠা খোলা কাজ করবে না, কারণ ব্রাউজার ওই পরিবেশে ES মডিউল সীমাবদ্ধ করে।
টেস্ট ও কমান্ড-লাইন স্ক্রিপ্টের জন্য Node.js 22 বা তার পরের সংস্করণ প্রয়োজন। এই কমান্ড দিয়ে টেস্ট স্যুট চালান:
npm test
ব্রাউজার ইন্টারফেস ব্যবহার
প্রশিক্ষিত ড্রাইভার দেখুন
ট্রাফিকের মধ্যে সরবরাহ করা নেটওয়ার্কটি কীভাবে গাড়ি চালায় তা দেখতে watch অভিজ্ঞতা ব্যবহার করুন। পৃষ্ঠাটি এর ইনপুট, আউটপুট, পরিকল্পিত পথ, লেন পরিবর্তনের অবস্থা এবং গাড়ির পরিসংখ্যান দেখায়। নীল ফিতা প্ল্যানারের তৈরি পথকে নির্দেশ করে।
নিজে গাড়ি চালান
Drive মোডে একই প্ল্যানার রেখে আপনি নিউরাল নেটওয়ার্কটি প্রতিস্থাপন করেন। গাড়িটি ৭০ কিমি/ঘণ্টা ক্রুজ কন্ট্রোল সেটিং দিয়ে শুরু হয়।
- সেট করা গতি বাড়াতে
↑ধরে রাখুন। - ব্রেক করতে ও সেট করা গতি কমাতে
↓চাপুন। - বামদিকে লেন পরিবর্তনের অনুরোধ করতে
←চাপুন। - ডানদিকে লেন পরিবর্তনের অনুরোধ করতে
→চাপুন।
নেটওয়ার্ক কার্ডে প্রশিক্ষিত মস্তিষ্কটি কী করত তা দেখানো চলতে থাকে, ফলে এই মোডে আপনার সিদ্ধান্তের সঙ্গে তার সিদ্ধান্ত তুলনা করা যায়।
ব্রাউজারে প্রশিক্ষণ দিন
ট্রেন মোড এলোমেলো নেটওয়ার্ক ওজনসহ 60টি গাড়ি দিয়ে শুরু হয়। একটি জেনারেশনে সব গাড়ি একই রাস্তা ব্যবহার করে, এবং প্রথম 15টি জেনারেশনে ধীরে ধীরে ট্রাফিক যোগ হয়। প্রাথমিক রাউন্ডগুলো 45 সেকেন্ড থেকে শুরু হয়। কোনো গাড়ি শেষ পর্যন্ত টিকে থাকলে পরবর্তী রাউন্ডগুলোর সময়কাল অর্ধেক করে বাড়ে, যতক্ষণ না সর্বোচ্চ পাঁচ মিনিটে পৌঁছায়।
ব্রাউজার প্রশিক্ষণে দ্রুত লেন ধরে রাখা ও অনুসরণ করার আচরণ দেখা যায়, কিন্তু ওভারটেকিং অনেক কঠিন। প্রকল্পে বর্ণিত পরীক্ষায় দেখা গেছে, এলোমেলোভাবে初始化 করা জনসংখ্যা সাধারণত 15তম জেনারেশন পর্যন্ত প্রতি কিলোমিটারে মাত্র 0.1 থেকে 0.5 বার লেন পরিবর্তন করেছে। মূল প্রি-ট্রেইনড ড্রাইভারের ক্ষেত্রে লেন পরিবর্তন উপকারী হয়ে উঠতে 200টি গাড়ির জনসংখ্যা নিয়ে প্রায় 170টি জেনারেশন প্রয়োজন হয়েছিল।
এলোমেলো ওজন দিয়ে শুরু না করে সরবরাহ করা ব্রেনের মৃদু মিউটেশন বিবর্তিত করতে চাইলে From pretrained বেছে নিন। পৃষ্ঠায় প্রশিক্ষিত ব্রেনগুলো JSON হিসেবে এক্সপোর্ট করা যায় এবং পরে Import নিয়ন্ত্রণ ব্যবহার করে লোড করা যায়।
কমান্ড লাইন থেকে প্রশিক্ষণ
কমান্ড-লাইন প্রশিক্ষণ ওয়ার্কার থ্রেডজুড়ে হেডলেসভাবে চলে। নিচের উদাহরণে 120টি নেটওয়ার্কের একটি জনসংখ্যাকে 10টি জেনারেশনের জন্য প্রশিক্ষণ দেওয়া হয়; প্রতিটি নেটওয়ার্ককে 60-সেকেন্ডের পর্বে তিনটি নির্দিষ্ট সিডযুক্ত রাস্তায় মূল্যায়ন করা হয়:
node scripts/train.mjs --generations 10 --population 120 --seeds 3 --seconds 60
ডিফল্টভাবে, ফলস্বরূপ ব্রেনটি runs/brain.json-এ লেখা হয়। এতে পরীক্ষাগুলো src/brains/pretrained.json-এ থাকা সরবরাহ করা নেটওয়ার্ক থেকে আলাদা থাকে।
ট্রেইনার সেরা ও গড় দূরত্ব, টিকে থাকা গাড়ির সংখ্যা, মিউটেশন হার এবং অতিবাহিত সময়ের মতো পরিসংখ্যান জানায়। জেনারেশন শূন্যতেই এমন গাড়ি থাকতে পারে যারা পুরো ছোট পর্বজুড়ে টিকে থাকে, কারণ প্ল্যানার তাদের লেনের কেন্দ্রে রাখে। তাই একক সেরা ফলাফলের চেয়ে জনসংখ্যার গড়ের বৃদ্ধি দেখে অগ্রগতি বোঝা প্রায়ই সহজ।
উপযোগী প্রশিক্ষণ বিকল্প
--densityট্রাফিকের পরিমাণ পরিবর্তন করে।--resume--outদ্বারা নির্দিষ্ট পথে থাকা ব্রেন থেকে শুরু করে এবং মৃদু মিউটেশন ব্যবহার করে।--generationsবিবর্তনীয় রাউন্ডের সংখ্যা নিয়ন্ত্রণ করে।--populationপ্রতি জেনারেশনে মূল্যায়ন করা ব্রেনের সংখ্যা নিয়ন্ত্রণ করে।--seedsব্যবহৃত রাস্তার সিডের সংখ্যা নিয়ন্ত্রণ করে।--secondsপ্রতিটি পর্বের সময়কাল নির্ধারণ করে।
সরবরাহ করা ব্রেনের জন্য ব্যবহৃত প্রশিক্ষণ প্রক্রিয়াটি scripts/curriculum.sh-এ রেকর্ড করা আছে। এটি পূর্ণ ট্রাফিকে দুই মিনিটের পর্ব দিয়ে শুরু হয়, এরপর আরও বেশি রাস্তায় পাঁচ মিনিটের পর্বে অগ্রসর হয় এবং শেষে ডান পাশে থাকার সূক্ষ্ম-সমন্বয় ধাপ সম্পন্ন করে। প্রকল্পের নথি অনুযায়ী, 14-কোরের একটি ল্যাপটপে এই কারিকুলামে প্রায় এক ঘণ্টা সময় লেগেছিল।
প্রশিক্ষিত ব্রেন মূল্যায়ন
মূল্যায়নে এমন নির্ধারক রাস্তায় একটি ব্রেন পরীক্ষা করা হয়, যেগুলো প্রশিক্ষণের সময় সে দেখেনি। রাস্তার সিডের তালিকা দিয়ে মূল্যায়নকারী চালান:
node scripts/evaluate.mjs --seeds 9001,9002,9003,9004,9005
আউটপুটে দূরত্ব, অতিবাহিত সময়, গড় গতি, লেন পরিবর্তন এবং প্রতিটি রান সময় শেষ হওয়া নাকি গাড়ি দুর্ঘটনায় শেষ হওয়া—এসব জানানো হয়। পাশাপাশি গড় ও মধ্যম দূরত্বের মতো সামগ্রিক মানও গণনা করা হয়।
সরবরাহ করা ব্রেনের পরিবর্তে কোনো এক্সপোর্ট করা বা নতুন প্রশিক্ষিত নেটওয়ার্ক মূল্যায়ন করতে --brain দিয়ে তার JSON ফাইল দিন:
node scripts/evaluate.mjs --brain runs/brain.json --seeds 9001,9002,9003
সরকারি ফলাফল পুনরায় তৈরি করা যায়:
npm run evaluate -- --write
এই কমান্ডটি scripts/results.json লেখে, যা ব্রাউজার ইন্টারফেসও পড়ে।
প্রকাশিত ফলাফল বোঝা
সরবরাহ করা 362-ওজনের নেটওয়ার্কটি পূর্ণ ট্রাফিকে 30টি সংরক্ষিত সিডে পাঁচ মিনিটের জন্য পরীক্ষা করা হয়েছিল। এটি 6.90 কিমি গড় দূরত্ব, 7.23 কিমি মধ্যম দূরত্ব এবং 87 কিমি/ঘণ্টা গড় গতি অর্জন করে। 30টি রানের মধ্যে 28টি পাঁচ মিনিট পরও সক্রিয় ছিল, এবং গাড়িটি প্রতি কিলোমিটারে গড়ে 5.1 বার লেন পরিবর্তন করেছে।
প্রকল্পটি এই সিস্টেমের সঙ্গে 14টি রে সেন্সর থেকে সরাসরি স্টিয়ার করা একটি আগের সংস্করণের তুলনা করে। সেই পুরোনো নেটওয়ার্কের গড় দূরত্ব ছিল 4.05 কিমি এবং গড় গতি 56 কিমি/ঘণ্টা; পাঁচ মিনিট পরও 30টির মধ্যে 20টি রান সক্রিয় ছিল। এই তুলনা নিয়ন্ত্রিত বেঞ্চমার্ক নয়, কারণ ট্রাফিক মডেলও পরিবর্তিত হয়েছিল। তবে এটি দেখায়, শেখা সিদ্ধান্তকে পরিকল্পিত স্টিয়ারিং থেকে আলাদা করায় কেন ওভারটেকিং আবিষ্কার করা সহজ হয়েছে।
নেটওয়ার্ক প্যাডেল ও লক্ষ্য লেন বেছে নেয়; প্ল্যানার সিগন্যালিং, ফাঁক যাচাই এবং মসৃণ স্টিয়ারিং সামলে নেয়।
উন্নত পরামর্শ
ওভারফিটিং কমাতে একাধিক সিড ব্যবহার করুন
একটি রাস্তায় ভালো করা কোনো ব্রেন অন্য রাস্তায় ব্যর্থ হতে পারে। প্রশিক্ষণের সিডের সংখ্যা বাড়ান এবং যাচাই ও চূড়ান্ত মূল্যায়নের জন্য আলাদা সিড সংরক্ষণ করুন। হেডলেস ট্রেইনার প্রতিটি ব্রেনকে তার রাস্তায় একাই মূল্যায়ন করে, কারণ ট্রাফিক শেখার গাড়িটির প্রতিক্রিয়া অনুসরণ করে; এতে একটি প্রার্থীর আচরণ অন্য প্রার্থীর স্কোর পরিবর্তন করতে পারে না।
শুরু থেকে না করে পুনরায় শুরু করুন
কোনো প্রশিক্ষিত ব্রেন যদি ইতিমধ্যে লেন ধরে রাখতে এবং ট্রাফিক এড়াতে পারে, তাহলে --resume অথবা ব্রাউজারের প্রি-ট্রেইনড বিকল্প ব্যবহার করুন। এলোমেলো ওজন থেকে শুরু করা বিবর্তনকে শূন্য থেকে পর্যবেক্ষণের জন্য উপযোগী, কিন্তু উন্নত ওভারটেকিং আচরণের জন্য আরও অনেক জেনারেশন ও বড় জনসংখ্যা প্রয়োজন হতে পারে।
ধীরে ধীরে কঠিনতা বাড়ান
রিপোজিটরির কারিকুলাম পদ্ধতি অনুসরণ করুন: নিয়ন্ত্রণযোগ্য পর্বের দৈর্ঘ্য দিয়ে শুরু করুন, তারপর সময়কাল, রাস্তার বৈচিত্র্য এবং মূল্যায়নের গভীরতা বাড়ান। দীর্ঘ পর্বে দৃঢ় ড্রাইভিংয়ের ভালো প্রমাণ পাওয়া যায়, তবে প্রতিটি জেনারেশন চালাতে বেশি সময় লাগে।
নির্ধারকতা বজায় রাখুন
সিমুলেশনটি নির্দিষ্ট সময়ধাপ পর্যন্ত নির্ধারক: একই সিড ও ব্রেন অভিন্ন গতিপথ তৈরি করে। স্পিড নিয়ন্ত্রণ পদার্থবিদ্যার সময়ধাপ পরিবর্তন না করে প্রতিটি রেন্ডার করা ফ্রেমে আরও বেশি 1/60-সেকেন্ডের সিমুলেশন ধাপ চালায়। ফলে ফলাফল পরিবর্তন না করেই দ্রুত প্রশিক্ষণ সম্ভব হয়।
প্রকল্পে কোথায় পরিবর্তন করতে হবে তা জানুন
src/sim/-এ DOM নির্ভরতা ছাড়াই রাস্তা, গাড়ি, পারসেপশন, প্ল্যানার, ট্রাফিক, বিশ্ব, ব্রেন এবং বিবর্তন-সংক্রান্ত কোড রয়েছে।src/render/-এ ক্যানভাস স্টেজ, নেটওয়ার্ক ভিজ্যুয়ালাইজেশন, অ্যানাটমি ডিসপ্লে এবং চার্ট রয়েছে।src/ui/-এ পর্যবেক্ষণ, প্রশিক্ষণ ও ড্রাইভ সেশন, স্টোরেজ এবং কিবোর্ড ব্যবস্থাপনা রয়েছে।src/brains/-এ প্রাক-প্রশিক্ষিত নেটওয়ার্ক রয়েছে।scripts/-এ প্রশিক্ষণ, কারিকুলাম, মূল্যায়ন এবং ফলাফল-সংক্রান্ত ফাইল রয়েছে।test/-এ Node.js পরীক্ষা রয়েছে, যার মধ্যে সংরক্ষিত রিপ্লে যাচাইও অন্তর্ভুক্ত।
উপসংহার
এই প্রকল্পটি দেখায়, কীভাবে একটি খুব ছোট নিউরাল নেটওয়ার্ক উচ্চ-স্তরের ড্রাইভিং সিদ্ধান্ত শিখতে পারে, যখন একটি প্রচলিত প্ল্যানার নির্ভুল স্টিয়ারিং এবং লেন পরিবর্তনের বাস্তবায়ন পরিচালনা করে। প্রথমে ব্রাউজার ডেমো চালান, ম্যানুয়াল ও নিউরাল সিদ্ধান্তের তুলনা করুন, তারপর Node.js স্ক্রিপ্ট ব্যবহার করে নিজস্ব ব্রেন প্রশিক্ষণ ও মূল্যায়ন করুন। নির্ভরতা-মুক্ত বাস্তবায়ন এবং নির্ধারিত ফলাফল-দেওয়া সিমুলেশন এটিকে বিবর্তনভিত্তিক শিক্ষা, যানবাহনের মডেল, ট্রাফিকের আচরণ এবং পরিকল্পনা অধ্যয়নের জন্য একটি ব্যবহারিক কোডবেসে পরিণত করেছে।
