دیگر لازم نیست بین راحتی هوش مصنوعی آمادهٔ استفاده و انعطافپذیری مدل سفارشی یکی را انتخاب کنید—میتوانید هر دو را در یک برنامه بسیار سبک مستقر کنید، بدون اینکه مگابایتها به حجم باینری اضافه شود.
در این جلسه، نحوه ساختن این معماری پشته دوگانه دقیق را در یک برنامه Android نشان خواهیم داد. خواهید دید که چگونه میتوانید از ML Kit برای کارهای ML کلاسیک آماده استفاده (مانند اسکن سند) در کنار LiteRT مستقل در خدمات Play برای بینایی رایانهای سفارشی یا حجمهای کاری صوتی خود استفاده کنید. بهطور عمیق بررسی خواهیم کرد که چگونه هر دو مسیر پیادهسازی در پشت صحنه متحد میشوند تا از زمان اجرای مدرن LiteRT استفاده کنند و به برنامه شما عملکردی یکپارچه و با شتاب سختافزاری در CPU و GPU با ردپای بارگیری تقریباً صفر بایت ارائه دهند.
نکات کلیدی برای توسعهدهندگان:
-عملکرد بینقص: هر دو مدل آماده و سفارشی بهطور خودکار بااستفاده از CompiledModel API یکپارچه، شتاب سختافزاری میگیرند.
-Micro-APKs: با بار کردن زمانهای اجرای ML Kit و LiteRT در خدمات Play، اندازه بارگیری برنامهتان را بهطور چشمگیری کاهش دهید.
-یکپارچهسازی ترکیبی: اجرای چندین گردش کار یادگیری ماشین بهطور همزمان در تولید بدون تداخل منابع را بیاموزید.
play-services-litert، فراخوانی LiteRt.initialize برای دریافت محیط، و ارسال آن به CompiledModel.create است.آوانویسی
عصر بهخیر، همگی.
درحال شروع گفتگو هستیم.
بنابراین، وقتی امروزه افراد از «هوش مصنوعی دروندستگاهی» صحبت میکنند، اغلب منظورشان مدلهای زبانی بزرگ است.
و امروز صبح، چندین گفتگو درباره Gemini Nano دیدید که با ML Kit، Firebase، و بسیاری از محصولات دیگر Google پوشش داده شده بودند.
این جلسه درباره نیمه دیگر است: یادگیری ماشین کلاسیک و مدلی که خودتان میآورید.
احتمالاً امروز چند بار بدون اینکه بدانید از آن استفاده کردهاید.
به استفاده از هرکدام از برنامههایتان که در آن پسزمینه را محو کردهاید یا از اسکنر رمزینه استفاده کردهاید یا از نوعی ویرایش تصویر استفاده کردهاید فکر کنید.
بخش زیادی از آن بر یادگیری ماشین کلاسیک بوده است و معمولاً حتی در دستگاه اجرا میشود.
و اگر تابهحال هرکدام از این ویژگیها را به برنامه یا APK خودتان اضافه کرده باشید، اغلب با این معاوضه مواجه شدهاید: آیا اساساً از یک میانای برنامهسازی کاربردی آماده استفاده کنم یا مدل خودم را بیاورم؟
تأثیر آن بر اندازه برنامهام چه خواهد بود؟
امروز خواهید دید که لازم نیست بین مدل آماده یا مدل خودتان یکی را انتخاب کنید.
درواقع میتوانید هر دو کار را با یک زمان اجرای سبک انجام دهید.
نام من چیتان پاریخ است.
من مدیر محصول LiteRT هستم و فرگوس، سرپرست مهندسی خدمات یادگیری ماشین Android، نیز همراه من است.
سلام.
و در پایان، خواهید دید که چگونه میتوانید برنامهای بسازید که دو مدل را در هر فریم دوربین با سرعت حدود ۳۰ فریم در ثانیه اجرا کند.
بنابراین، این صحبت چهار بخش دارد.
در بخش اول، درباره راهحلهای هوش مصنوعی دروندستگاهی Google با تمرکز بر یادگیری ماشین کلاسیک، یعنی ML Kit و LiteRT، صحبت خواهیم کرد.
دوم، موارد جدید در LiteRT و خدمات Play را نیز بررسی خواهیم کرد.
این موضوع همچنین شامل API جدید CompiledModel از LiteRT و دستگاههایی که پشتیبانی میکنیم میشود.
سوم، به شما نشان میدهیم که چگونه یک برنامه جدید بسازید.
فرگوس قصد دارد ساختن برنامه با «کیت یادگیری ماشین» و مدل سفارشی را در یک APK بررسی کند.
و درنهایت، به شما نشان خواهیم داد که چگونه بااستفاده از «حالت عامل» برنامه موجود را ارتقا دهید.
و همچنین، حتی میتوانید با پشتیبانی این عامل، یک برنامه جدید را داربستبندی کنید.
بسیار خوب.
پس ابتدا بیایید با این شروع کنیم که LiteRT چیست؟
LiteRT زمان اجرای استنتاج دروندستگاهی Google برای مدلهای خودتان است.
این مدل از همان قالب فایل tflite .استفاده میکند که اگر قبلاً از TensorFlow Lite استفاده کرده باشید، با آن آشنا هستید.
این مدل برای عملکرد بهتر بازمهندسی شده است و از چند چارچوب نیز پشتیبانی میکند.
این یعنی میتوانید مدلها را از PyTorch، TensorFlow، و حتی JAX وارد کنید تا بتوانید آن را به قالب بافر تخت برای LiteRT کاهش دهید.
اکنون، از سال ۲۰۲۲، TensorFlow Lite در خدمات Google Play زمان اجرای رسمی دروندستگاهی Android برای مدلهای سفارشی بوده است.
امروز ارتقای بزرگی دریافت میکند و بخش زیادی از این گفتگو درباره همین موضوع خواهد بود.
این ارتقا جدیدترین LiteRT CompiledModel API را بههمراه خواهد داشت، ازجمله استنتاج GPU بهبودیافته جدید که ۱٫۴ برابر سریعتر خواهد بود و همچنین به شما امکان میدهد برنامههای کوچکتری با اندازه APK بسیار کمحجمتر بسازید.
پس چرا آن را ازطریق خدمات Play ارائه میکنیم؟
چند مزیت وجود دارد و این قطعاً یک چالش عمده است که در بسیاری از گفتگوهایی که میشنوم میبینم که اندازه برنامه و تورم APK به یک چالش واقعی تبدیل شده است، درست است؟
بنابراین، زمان اجرای کوتاهی خواهید داشت.
زمان اجرا در APK شما نیست، بنابراین به کارخواه وابسته متکی هستید و این باعث میشود APK شما حدود ۸ مگابایت کوچکتر شود.
مزیت دوم کارآمدی است.
یک نسخه از زمان اجرا دارید، بنابراین زمان اجرا که زمان اجرای LiteRT است در همه برنامهها همرسانی میشود.
بنابراین، میتوانید تصور کنید که اگر برنامههای متعددی داشته باشید، هرکدام از آنها میتوانند ۸ مگابایت در فضای ذخیرهسازی شما صرفهجویی کنند.
وقتی میخواهید فضای دیسک را ذخیره کنید و برنامه سبکتری داشته باشید، این مقدار خیلی سریع افزایش مییابد.
دوم، نگهداری میشود.
Google رفع اشکالها را ارسال میکند، چالشهای درایور GPU را که شما مجبور به انجام آن نیستید برطرف میکند، و همچنین سایر بهروزرسانیهای امنیتی همگی ازطریق بهروزرسانیهای خودکار ارائه میشوند.
و همانطور که گفتم، واحد پردازش گرافیکی سریعتر است، بنابراین واحد پردازش گرافیکی ۱٫۴ برابر سریعتر دریافت میکنید و در ادامه با جزئیات بیشتری به آن خواهیم پرداخت.
و از دیدگاه پوشش، میتوانیم به دستگاههای Android قدیمیتر ارسال کنیم.
LiteRT در «خدمات Play» از Android 7 (منتشرشده در سال ۲۰۱۶) به بعد را پشتیبانی میکند.
و همانطور که فرگوس به شما نشان خواهد داد، دستگاههای جدید دیگری که در اسلایدهای بعدی به آنها خواهیم پرداخت.
بنابراین، این وسیله تحویل است و بیایید درباره مرحله بعدی، یعنی زمان اجرا، صحبت کنیم.
بنابراین، LiteRT جدید نیست و آزمایشی هم نیست.
امروزه TensorFlow Lite و LiteRT در بیشاز ۲۵۰٬۰۰۰ برنامه اجرا میشوند.
امروزه این سیستمعامل روی بیشاز ۳٫۸ میلیارد دستگاه اجرا میشود.
بنابراین، بسیاری از برنامههایی که ممکن است استفاده کنید، شاید حتی ندانید، همه این را اجرا میکنند.
و این همچنین معادل بیش از یک تریلیون استنتاج در هر روز است، درست است؟
در این مقیاس، ما قطعاً با هر مشکل عجیب مجموعه تراشه مواجه شدهایم، توانستهایم مشکلات ROM یا مشکلات درایور GPU را برطرف کنیم، و راهحل جایگزینی فقط برای شما داریم.
LiteRT همچنین چیزی است که Google در برنامههای پرچمدار خود، در برنامهها، پلاتفرمها، و حتی چندین دستگاه اجرا میکند.
جلوههای «کوتهویدیو YouTube»، بخشبندی پسزمینه Meet، «رفع تاری عکس»، چند نمونه از مواردی هستند که در آنها ویدیو همزمان و مدلهای تصویری سنگین همگی روی LiteRT اجرا میشوند.
این موضوع همچنین بسیار مهم است زیرا ایجاد موارد استفاده سریع و جذاب برای کاربران بسیار حیاتی میشود، درست است؟
بنابراین، این همان زمان اجرایی است که برای این ویژگیهای پرچمدار تقویت کردهایم و این همان چیزی است که ازطریق خدمات Play دریافت میکنید.
بنابراین، بیایید به این موضوع هم بپردازیم که چرا اصلاً باید از هوش مصنوعی دروندستگاهی استفاده کرد.
تأخیر، حریم خصوصی، کار کردن بهصورت آفلاین، یا داشتن هزینههای کم، اگر هرکدام از اینها برایتان مهم است، آن را بهصورت آفلاین اجرا کنید، درست است؟
ممکن است دلایل بیشتری هم وجود داشته باشد، اما اینها برخیاز واضحترین دلایلی هستند که برای اجرا در دستگاه شنیدهایم.
اجرا در دستگاه نیز همیشه رایگان نیست.
البته تفاوتهای ظریف و چالشهایی هم دارد.
بنابراین، ما همچنین برخی از این چالشها را بررسی خواهیم کرد و مسیری را برای شما نیز در پیش خواهیم داشت، درست است؟
بنابراین، عملکرد: همانطور که دیدید، درست است، برخیاز نمونههای برنامههای قبلی، تأخیر و بودجههای حافظه همیشه محدود هستند، درست است؟
ویدیو و صدای همزمان به کارایی بسیار بالایی نیاز دارد.
حتی ویژگیهای تعاملی ساده باید سریع باشند.
درغیراینصورت، تعامل کاربر را ازدست میدهید.
تنوع سختافزار: صدها SoC با پیکربندیهای CPU و GPU مختلف وجود دارد.
نمیتوانید برای همه اینها کد بنویسید، درست است؟
چگونه برای هرکدام از اینها راهحل پیدا میکنید؟
اندازه APK: بستهبندی زمان اجرای بومی همچنین باعث میشود هر بارگیری بزرگتر شود که میتواند بر نرخ تبدیل شما تأثیر بگذارد.
سفارشیسازی: آموزش مدل، کیفیت، اندازه مدل، همه اینها حتی قبلاز استقرار بسیار حیاتی خواهند بود.
بنابراین بله، ساختن یک برنامه عالی در دستگاه میتواند دشوار باشد.
اما در هریک از این موقعیتها، میخواهیم پلاتفرم کار را برای شما انجام دهد و نه برعکس، درست است؟
و مجموعه دروندستگاهی Google برای رسیدگی به این چالشها وجود دارد و در ادامه به آن خواهیم پرداخت.
بنابراین، امروز روی دو راهحل ساده تمرکز خواهیم کرد، درست است؟
دو روش آسان برای افزودن هوش مصنوعی دروندستگاهی ازطریق «خدمات Play» وجود دارد.
مسیر ۱ مسیر آماده استفاده با ML Kit است، درست است؟
اینها میاناهای برنامهسازی کاربردی آماده استفاده برای بینایی و زبان هستند، به تخصص یادگیری ماشین محدودی نیاز دارند، مدلهای زیادی ارائه شده است، و همه ازطریق خدمات Play ارائه میشوند.
و در اسلایدهای بعدی به چند نمونه از این موارد نیز خواهیم پرداخت.
مسیر سفارشی، این ازطریق LiteRT است.
LiteRT به شما امکان میدهد مدل خودتان را بیاورید و آن را در CPU و GPU اجرا کنید.
زمان اجرا نیز از «خدمات Play» میآید.
بنابراین، در-- بنابراین، آن را در APK خود بستهبندی نمیکنید.
اینها یکی از دو گزینه نیستند.
همچنین همیشه میتوانند با هم بهتر باشند.
و این دقیقاً همان چیزی است که امروز در چند دقیقه آینده خواهیم ساخت.
بنابراین، اما ابتدا، بیایید به آنچه ML Kit پوشش میدهد بپردازیم.
در اینجا آنچه ML Kit بهطور پیشفرض پوشش میدهد آورده شده است.
بنابراین، اگر فکر میکنید برخیاز این قابلیتها نیازهای شما را برآورده میکنند، این نقطه شروع عالی است و شما از قبل پیشتاز هستید.
ما پوشش برای بینایی، برای رمزینهها، اسناد، نوشتار، حالت، بسیاری از این قابلیتها، میاناهای برنامهسازی کاربردی زبان مانند ترجمه، پاسخهای هوشمند، و حتی استخراج نهاد داریم، درست است؟
نکته کلیدی این است که بسیاری از این میاناهای برنامهسازی کاربردی بینایی و زبان همگی با LiteRT در پشت صحنه اجرا میشوند.
بنابراین، اگر ML Kit آنچه را نیاز دارید انجام میدهد، میتوانید از اینجا شروع کنید.
و وقتی اینطور نباشد، این فرصت را دارید که مدل خودتان را بیاورید.
و نکته کلیدی این است: «کیت یادگیری ماشین» و مدل سفارشی شما دو زمان اجرا نخواهند بود، درست است، همانطور که اشاره کردم.
این دو API را مثل دو در ورودی درنظر بگیرید که به یک LiteRT منتهی میشوند که در پشت صحنه اجرا میشود.
بنابراین، LiteRT زمان اجرایی خواهد بود که هر دوی این قابلیتها را هماهنگ میکند.
بنابراین، اگر برنامهتان ازقبل از «فروشگاه Play» برای ML Kit استفاده میکند، از آن استفاده کنید.
درغیراینصورت، مسیر LiteRT را نیز بررسی خواهیم کرد.
پس بیایید به موارد جدید LiteRT هم اشاره کنیم.
همانطور که گفتم، LiteRT نسخه تکاملیافته TensorFlow Lite است، درست است؟
بنابراین، بزرگترین بهبودها این است که واحد پردازش گرافیکی سریعتری داریم.
واحد پردازش گرافیکی سریعتر از OpenCL و OpenGL پشتیبانی میکند و همچنین از پشتیبانی چندسکویی حتی برای Metal backends برخوردار است.
بنابراین، قطعاً میتوانید درصورت نیاز از این برای چندین پلاتفرم استفاده کنید.
همچنین سادهتر است.
ما یک گردش کار یکپارچه برای شتابدهی CPU، GPU، و NPU داریم.
درحالحاضر CPU و GPU در «خدمات Play» هستند، درحالیکه NPU امروزه ازطریق LiteRT بستهبندی میشود و این کار درحال انجام است.
بنابراین، قبلاً هر شتابدهنده بهمعنای راهاندازی نماینده متفاوتی بود، درست است؟
اکنون فقط یکبار باید این کار را انجام دهید.
بنابراین یک میانای برنامهسازی کاربردی با بازگشت خودکار به CPU وجود دارد و نیازی به انجام تنظیمات اختصاصی-واگذارشده ندارید.
و میتوانید فقط تماسهای شتابدهنده داشته باشید که میتوانند این کار را بسیار سادهتر و با کد کمتر مدیریت کنند.
همچنین قدرتمند است، همان مدل روی چندین پلتفرم اجرا میشود، همانطور که اشاره کردم.
این بخش انعطافپذیری آن بسیار مهم خواهد بود.
بنابراین قالب tflite .بدون تغییر باقی میماند.
اگر برنامه موجودی داشتید، همچنان میتوانید از این قالب استفاده کنید.
اگر درحال ساختن برنامه جدیدی هستید، میتوانید این قالب فایل را دوباره منتقل کنید.
نکته جالب دیگر این است که ما از Interpreter API پشتیبانی میکنیم که قبلاً در TensorFlow Lite بود.
بنابراین اگر میخواهید بهصورت مرحلهای مهاجرت کنید، Interpreter API نیز بهعنوان بخشی از LiteRT جدید گنجانده شده است تا مهاجرت را برای شما آسان کند.
پس این زمان کاردهی باتری است.
بیایید درباره چیزهایی که میتوانید با این بسازید صحبت کنیم.
بنابراین، آنچه برنامههای Android امروز میسازند این است.
همه چیز از جلوههای دوربین، ویرایش عکس، تایپ هوشمند، بازیها، و چهرهنماها، درست است؟
بسیاری از این برنامهها به قابلیتهای همزمان نیاز خواهند داشت.
واحد پردازش گرافیکی قابها را مستقیماً از دوربین ارسال میکند، بنابراین سریع و همزمان بودن کارها مهم خواهد بود.
برخیاز این مدلهای ویرایش عکس نیز سنگینتر میشوند.
و همینطور قابلیتهای واقعیت افزوده/ واقعیت مجازی که در برخیاز نسخههای نمایشی با عینک دیدهاید، بسیاری از آنها LiteRT را در پسزمینه اجرا میکنند.
این همان زمان اجرایی است که اکنون در پشت ویژگیهای پرچمدار Google و همچنین در خدمات Play قرار دارد، بنابراین شما همه اینها را بدون بستهبندی چیزی به APK خود دریافت میکنید.
حالا چرا برنامهای نسازیم و فرگوس به ما نشان دهد که چگونه این کار را انجام دهیم.
بیایید این کار را انجام دهیم.
متشکرم، چینتان.
بنابراین، میخواهم کمی درباره ویژگیهای جدید LiteRT در خدمات Google Play صحبت کنم.
بنابراین درست قبلاز اینکه بسازیم، یک خبر دیگر، هر چیزی که دیدید اکنون فراتر از تلفن اجرا میشود، LiteRT در خدمات Play نیز در Wear OS و سیستم عامل Android Automotive دردسترس است.
بنابراین میتوانید مدلهای دروندستگاهی را در ساعت یا دستگاه پوشیدنی دیگر، یا در خود خودرو اجرا کنید.
قبلاً امکان استفاده از برنامهای در تلفن وجود داشت که برنامه همراه Wear بود، اما اکنون میتوانید آن را در خود دستگاه پوشیدنی اجرا کنید، و همین امر برای Android Automotive نیز صادق است.
و بنابراین شما همان API، همان مدل tflite.، اما سطوح بیشتری دارید.
نیازی به پیادهسازی جداگانه برای هر فرم فاکتور نیست، میتوانید از همان پیادهسازی برای همه این دستگاههای مختلف استفاده کنید.
و سپس زیبایی الگوی توزیع خدمات Play این است که ما درواقع میتوانیم این را برای اجرا در دستگاههای قدیمیتر سازگار کنیم.
بنابراین برای «سیستمعامل Android Automotive»، تا Android 11 را که در سال ۲۰۲۰ منتشر شد پشتیبانی میکنیم و برای Wear OS، از Wear OS 4 و نسخههای جدیدتر را پشتیبانی میکنیم.
بسیارخوب.
بنابراین، اکنون میخواهم درباره دو مسیر مختلف صحبت کنم: ساختن یک برنامه جدید و ارتقا دادن یک برنامه موجود.
این موضوع بقیه صحبت را پوشش خواهد داد.
بنابراین، با یک برنامه نمونه شروع میکنم که استفاده از ML Kit را با یک مدل GPU سفارشی که روی LiteRT اجرا میشود ترکیب میکند.
و سپس برای ارتقای یک برنامه موجود، سه تغییر کوچک وجود خواهد داشت: تغییر Gradle برای بهروزرسانی وابستگیها، تغییر init برای فعال کردن LiteRT در خدمات Play، و سپس جابهجایی از Interpreter API به CompiledModel API.
اما ابتدا این کار را با برنامه جدید انجام میدهیم، زیرا ارتقا دادن زمانی منطقیتر است که ببینید به چه چیزی ارتقا میدهید.
بنابراین، ساختن یک برنامه جدید.
این برنامهای است که میخواهیم بسازیم.
این حالت نمای دوربین زنده خواهد داشت که در آن شما واضح میمانید و پسزمینه سبک هنری میگیرد.
بنابراین، میخواهیم قاب دوربین را بگیریم.
تصاویر قاب دوربین را ازطریق بخشبندی سلفی ML Kit جاریسازی خواهیم کرد.
این یکی از میاناهای برنامهسازی کاربردی آماده استفاده ML Kit است.
و این یک ماسک پیشزمینه تولید میکند که اساساً میگوید کدام پیکسلها در تصویر با شخص موجود در تصویر مطابقت دارند.
و سپس مدل سفارشیمان را میگیریم که مثل مدل نوع انتقال سبک است و سبکی را روی تصویر اعمال میکند.
و ما آن را روی کل قاب دوربین اعمال میکنیم، اما درواقع فقط بخش پسزمینه است که برای ما مهم است، زیرا درنهایت قاب اصلی دوربین و ماسک و پسزمینه سبک را میگیریم و با کمی منطق ساده آنها را ترکیب میکنیم تا یک قاب ترکیبی داشته باشیم که در آن سوژه را حفظ کردهایم و پسزمینه دارای سبک است.
بنابراین، میخواهیم از میاناهای برنامهسازی کاربردی آماده در جایی که وجود دارند و از میاناهای برنامهسازی کاربردی سفارشی در جایی که برنامه ما را متمایز میکنند استفاده کنیم.
بنابراین، این اولین بخشی است که در آن میانای برنامهسازی کاربردی بخشبندی سلفی ML Kit را فراخوانی میکنیم.
// 1. Configure and create segmenter client
val segmenter = Segmentation.getClient(
SelfieSegmenterOptions.Builder()
.setDetectorMode(
SelfieSegmenterOptions.STREAM_MODE)
.build())
// 2. Prepare image & run inference
fun processFrame(mediaImage: Image) {
val image = InputImage.fromMediaImage(
mediaImage, /* rotationDegrees= */ 0)
segmenter.process(image)
.addOnSuccessListener { mask -> … }
}پس این درست مثل یک میانای برنامهسازی کاربردی معمولی است، درست است؟
این درست مثل نان و کره برای توسعهدهندگان Android است.
میدانید، فقط به اسناد میانای برنامهسازی کاربردی نگاه میکنید یا از Gemini میخواهید آن را برایتان بسازد.
اما، میدانید، نسبتاً ساده است.
شما یک کارخواه میسازید و هنگام ساختن کارخواه، چند گزینه را به آن منتقل میکنید.
در این مورد، حالت جاریسازی را مشخص میکنیم تا بتوانیم جریانی از فریمهای ویدیو را پردازش کنیم.
And then, there's a you call this process method there, and the callback from that is going to get the mask that's is returned, computed by selfie segmentation.
و ورودی، تصویر دوربین است.
و همه این میاناهای برنامهسازی کاربردی از انواع سطح برنامه استفاده میکنند، نه تانسورهای خام، بنابراین شما واقعاً در سطح بسیار بالایی برنامهنویسی میکنید و این واقعاً ساده است.
برای این کار، بخش دوم، مدل سفارشی، ما از مدل PyTorch استفاده خواهیم کرد.
فکر میکنم Chintan این را از یکی از چیزهایی مثل Kaggle یا Hugging Face گرفته است…
راست.
بله، و یا میتوانید خودتان تبدیل کنید، میدانید.
میتوانید مدل خودتان را بسازید.
متأسفم، برمیگردم.
بله، این چیزی است که این نوع پشته به نظر میرسد.
شما یک مدل PyTorch را میگیرید، میتوانید آن را تبدیل و کوانتیزه کنید، و سپس یک مدل LiteRT دریافت میکنید.
سپس آن را با برنامهتان توزیع میکنید، هرطور که دوست دارید.
این مدل میتواند بهعنوان بخشی از برنامه بهصورت دارایی بستهبندی شود یا بهطور جداگانه بارگیری شود.
هر دو روش کار میکند.
و سپس روی زمان اجرای LiteRT در خدمات Play قرار میگیرد.
و سپس، هستههای CPU برای بهینهسازی در CPU وجود دارد، و ML Drift نام شتابدهنده GPU است.
بله، همانطور که گفتم، مدل TFLite را دریافت میکنید و میتوانید خودتان مدل را آموزش دهید، یا مدل موجودی را پیدا کنید، هر دو روش کار میکند.
تبدیل از PyTorch فقط چند خط پایتون است.
import litert_torch
model = my_models.Stylizer().eval()
# Convert with torch.export under the hood
edge_model = litert_torch.convert(
model, sample_inputs)
edge_model.export("stylizer_f32.tflite")بنابراین، LiteRT-Torch را با pip نصب میکنید، litert_torch.convert را فراخوانی میکنید، مقداری sample_inputs به آن میدهید که میتواند ورودیهای تصادفی باشد، و یک فایل TFLite صادر میکنید.
ضمناً، LiteRT-Torch نام جدید ai-edge-torch است، اگر با آن آشنایی دارید.
And then quantization is, again, very straightforward.
# Python
# previously ai_edge_quantizer
from litert_quantizer import quantizer, recipe
qt = quantizer.Quantizer("stylizer_f32.tflite")
# int8 weights, float activations
qt.load_quantization_recipe(
recipe.dynamic_wi8_afp32())
qt.quantize().export_model("stylizer_int8.tflite")کوانتیزهکننده و دستورالعمل را از LiteRT Quantizer وارد میکنید.
وقتی کوانتیزهکننده را میسازید، مدل ممیز شناور اصلی را وارد میکنید، دستورالعملی را وارد میکنید که این همان دستورالعمل استانداردی است که ما برای GPU توصیه میکنیم، که از وزنهای عدد صحیح ۸ بیتی استفاده میکند، اما فعالسازیها را بهعنوان ممیز شناور ۳۲ بیتی نگه میدارد.
And then, you just call quantize and then export_model to save that save the output model.
و این یک مدل کوانتیزهشده خواهد بود که میتوانید آن را اجرا کنید و وزنهای بسیار کوچکتری خواهد داشت و با کارایی بیشتری اجرا خواهد شد.
بسیار خوب، بله، CompiledModel API GPU جایی است که واقعاً میدرخشد.
بنابراین، همانطور که چینتان اشاره کرد، میدانید، سرعت قابلتوجهی در GPU قدیمی TFLite وجود دارد.
اعداد دقیق از مدلی به مدل دیگر کمی متفاوت خواهد بود، اما ۱٫۴ برابر چیزی است که میتوانید بهطور منطقی انتظار داشته باشید.
تا ۱۰ برابر سریعتر از استنتاج CPU، بنابراین، میدانید، این یک پیروزی بزرگ است، درست است؟
اگر شما مو- اکثر شما که امروزه از مدلها استفاده میکنید، احتمالاً آنها را روی CPU اجرا میکنید و از عملکردی که میتوانید از GPU دریافت کنید، حدود ۱۰ برابر عقب میمانید.
بنابراین، این یک انگیزه واقعی است.
چه چیزی آن را سریع میکند؟
بسیار خوب، پس چیزهای زیادی وجود دارد که ما پشتیبانی میکنیم، برای مثال، اجرای ناهمگام تا بتوانید یک AHardwareBuffer بگیرید و آن را مستقیماً ارسال کنید یا یک میانگیر OpenGL از آن خط لوله پردازش دوربین بگیرید و آن را مستقیماً به یک میانگیر تانسور ارسال کنید.
Zero-copy optimize zero-copy we support, so basically you can when you're trying to process things, you know, with a low-latency budget like when you're having to process every frame in a matter of, you know, a few tens of milliseconds, then even just simply copying a memory buffer can be a non-trivial overhead.
بنابراین، برای آن دسته از برنامههایی که نیاز به پردازش همزمان بسیار بالا دارند و میخواهید از بهینهسازی بدون کپی استفاده کنید، ما از آن پشتیبانی میکنیم.
و سپس، همانطور که، همانطور که چینتان اشاره کرد، این یک پلتفرم چندسکویی با پشتیبانی از OpenGL، OpenCL، و Metal بهعنوان پساندهای GPU است.
آخرین مورد که البته کماهمیتترین نیست، بهینهساز ML Drift متنباز است.
این برنامه تحت پروانه Apache دردسترس است.
اخیراً Google آن را متنباز کرده است.
بسیارخوب، و بعد، این، این کد برنامه است.
// Kotlin
// Build once, off the main thread.
private val model: CompiledModel =
CompiledModel.create(
context.assets,
"stylizer_int8.tflite",
// Simple GPU setup!
CompiledModel.Options(Accelerator.GPU),
environment
)
// Reuse buffers across frames.
private val inputBuffers = model.createInputBuffers()
private val outputBuffers = model.createOutputBuffers()
fun stylize(input: FloatArray): FloatArray {
inputBuffers[0].writeFloat(input)
model.run(inputBuffers, outputBuffers) // sync
return outputBuffers[0].readFloat()
}همانطور که میبینید، این فایل بسیار کوچک و ساده است.
بنابراین، شما مدل را یکبار ایجاد میکنید و سپس در هر قاب از آن دوباره استفاده میکنید.
بنابراین، در آنجا، CompiledModel.create در فایل .tflite عبور میکند.
فقط مشخص میکنید که میخواهید روی GPU اجرا شود، و سپس ورودی و outputBuffers را میسازید.
و سپس، در حلقه اصلی، جایی که درواقع هر فریم را پردازش میکنید، این model.run را فراخوانی میکنید و ورودی و خروجی را ارسال میکنید.
پساز نوشتن در inputBuffers، با model.run تماس بگیرید، و سپس از outputBuffers بخوانید.
بسیارخوب.
بله، و سپس در آنجا، اگر فقط GPU را مشخص کنید، روی GPU اجرا خواهد شد.
اگر CPU و GPU را نیز در آنجا مشخص کنید، سعی میکند GPU را اجرا کند.
اگر GPU به هر دلیلی دردسترس نباشد، به CPU برمیگردد.
بنابراین، در برخی موارد، بازگشت به CPU ممکن است برای برنامه شما بهاندازه کافی کارآمد نباشد، و این زمانی است که میخواهید فقط GPU را به این صورت مشخص کنید.
معمولاً میخواهید یک CPU جایگزین داشته باشید.
بسیارخوب.
بنابراین، آن را با LiteRT بستهبندیشده ساختهایم که هنوز از خدمات Play استفاده نمیکند.
بنابراین، اجازه دهید نحوه استفاده از LiteRT در خدمات Play را به شما نشان دهم.
بنابراین، سه تغییر وجود دارد: اولین تغییر، تغییر وابستگی است.
// Easier with CompiledModel API: 3 steps
// 1. app/build.gradle: replace litert with play-services-litert
- implementation 'com.google.ai.edge.litert:litert:...'
+ implementation 'com.google.android.gms:play-services-litert:17.0.0' // also pulls in litert-apiفقط باید آن را در فایل Gradle یا هر جای دیگری که از سیستم ساخت استفاده میکنید، هر جای دیگری که وابستگیهای بسته Maven را مشخص میکنید، جایگزین کنید، این همان چیزی است که قرار است تغییر دهید.
و وابستگی litert یا هرکدام از وابستگیهای بسته قدیمیتر TensorFlow Lite Maven را بردارید و آنها را با این play-services-litert جایگزین کنید.
این کار بسته litert-api را نیز وارد میکند.
اکنون، اگر درحال نوشتن یک لایه میانی هستید که فقط میخواهد به LiteRT وابسته باشد، اما واقعاً برایش مهم نیست که زمان اجرا از برنامه میآید یا از خدمات Play، میتوانید فقط به LiteRT API وابسته باشید و یک محیط را بهعنوان پارامتر ورودی درنظر بگیرید.
بنابراین، مرحله دوم پارامتر محیط است.
That's where you provide the dependency injection, essentially, to specify that you are using, you want to use Play services LiteRT.
بنابراین، gms.litert.LiteRt را وارد میکنید و تابع مقداردهی اولیه را فراخوانی میکنید و زمینه را که فعالیت Android شما است، ارسال میکنید.
// 2. Initialize the LiteRT Environment from Play services (context = your Activity)
- val environment = Environment.create(...)
+ import com.google.android.gms.litert.LiteRt
+ val environment = LiteRt.initialize(context).await()
// 3. Pass environment whenever you call CompiledModel.create
// That's it! The rest of your app uses the normal CompiledModel APIs from litert-api.و این یک چیز غیرهمزمان است، بنابراین باید .await را فراخوانی کنید یا بقیه آن را براساس یک فراخوانی برگشتی داشته باشید.
و سپس، درنهایت، وقتی آن محیط را بهدست آوردید، هروقت CompiledModel.create را فراخوانی میکنید، آن محیط را ارسال میکنید.
و این همان چیزی است که باعث میشود از زمان اجرای LiteRT خدمات Play از خدمات Play استفاده کند.
و همین.
یعنی بقیه برنامهتان دقیقاً از همان LiteRT CompiledModel API از LiteRT API استفاده میکند.
بقیه کد استنتاج شما برای استفاده از خدمات Play تغییر نمیکند.
و درواقع میتوانید این انتقال را بهصورت افزایشی انجام دهید.
لازم نیست همه را یکباره انجام دهید، میتوانید هر بار یک مؤلفه را انتقال دهید.
اگر برنامه بزرگی دارید، منطقی است که هر مؤلفهای را که از LiteRT استفاده میکند منتقل کنید، و سپس میتوانید یکییکی منتقل کنید و یکییکی آزمایش کنید.
تنها نکته این است که فقط ازنظر اندازه برنده میشوید، صرفهجویی در فضا فقط زمانی اتفاق میافتد که آخرین وابستگی به زمان اجرای بستهبندیشده را بردارید.
و اگر این کار را میکنید، هشدار دیگر این است که نباید اشیاء را بین LiteRT در خدمات Play و LiteRT بستهبندیشده ترکیب کنید.
بنابراین، اگر-- اگر تانسورها یا مدلهای کامپایلشده یا مفسرها را از LiteRT در خدمات Play دریافت میکنید، نباید آنها را به LiteRT بستهبندیشده منتقل کنید یا برعکس.
اما درغیراینصورت، ترکیب این موارد بهخوبی کار میکند.
بسیارخوب.
خب، این ساختن یک برنامه جدید بود.
اکنون میخواهم درباره نحوه ارتقا دادن برنامه موجود صحبت کنم.
بنابراین، ممکن است برنامهای داشته باشید که از Interpreter API استفاده میکند.
این همان چیزی است که ما آن را میانای برنامهسازی کاربردی قدیمیتر TFLite مینامیم که از مفسر بهعنوان کلاس اصلی استفاده میکند.
بنابراین، این کد در سمت چپ بااستفاده از Interpreter API است و سپس در سمت راست، کد جدید CompiledModel API را میبینید.
// Dependencies (Gradle):
// play-services-tflite-java and/or litert (bundled)
// Init
TfLite.initialize(context).await()
// Load
val interpreterOptions =
InterpreterApi.Options().apply {
runtime = TfLiteRuntime.FROM_SYSTEM_ONLY
}
val interpreter =
InterpreterApi.create(modelFile, interpreterOptions)
// Prepare inputs/outputs
val inputs = …
val outputs = …
// Execute
interpreter.run(inputs, outputs)// Dependencies (Gradle):
// play-services-litert
// Init
val environment =
LiteRt.initialize(context).await()
// Load
val modelOptions = CompiledModel.Options(Accelerator.CPU)
val model =
CompiledModel.create(modelPath, modelOptions, environment)
// Prepare inputs/outputs
val inputBuffers = model.createInputBuffers()
val outputBuffers = model.createOutputBuffers()
// Execute
model.run(inputBuffers, outputBuffersبنابراین، شما فقط TfLite.initialize را به LiteRt.initialize تغییر میدهید و این اکنون یک محیط را برمیگرداند.
و سپس محیط را به CompiledModel.create منتقل میکنید.
بنابراین، این تغییر کوچکی است و APK بزرگتر نمیشود.
و خواهید دید که در اسلاید بعدی، به شما نشان خواهیم داد که چگونه این کار را با GPU انجام دهید، و این فقط یک گزینه دیگر است.
بنابراین، این کد اضافی است که برای فعال کردن GPU نیاز داشتید.
// Dependencies (Gradle):
// play-services-tflite-java and/or litert (bundled)
// Init
val initOptions = TfLiteInitializationOptions.builder()
.setEnableGpuDelegateSupport(true).build()
TfLite.initialize(context, initOptions).await()
val useGpu =
TfLiteGpu.isGpuDelegateAvailable(context).await()
// Load
val interpreterOptions =
InterpreterApi.Options().apply {
runtime = TfLiteRuntime.FROM_SYSTEM_ONLY
}
if (useGpu) {
interpreterOptions.addDelegateFactory(
GpuDelegateFactory());
}
val interpreter =
InterpreterApi.create(modelFile, interpreterOptions)
// Prepare inputs/outputs
val inputs = …
val outputs = …
// Execute
interpreter.run(inputs, outputs)// Dependencies (Gradle):
// play-services-litert
// Init
val initOptions = LiteRtInitializationOptions.builder()
.setEnableGpu(true).build()
val environment = LiteRt.initialize(context, initOptions).await()
// Load
val modelOptions =
CompiledModel.Options(Accelerator.CPU, Accelerator.GPU)
val model =
CompiledModel.create(modelPath, modelOptions, environment)
// Prepare inputs/outputs
val inputBuffers = model.createInputBuffers()
val outputBuffers = model.createOutputBuffers()
// Execute
model.run(inputBuffers, outputBuffers)همانطور که میبینید، کد در میانای برنامهسازی کاربردی جدید برای فعال کردن GPU کمی سادهتر از کد قبلی است.
بنابراین، اولین فراخوانی به setEnableGpu در گزینههای مقداردهی اولیه LiteRT که سپس به LiteRt.initialize ارسال میکنید، باعث میشود کد شتابدهنده GPU در برنامه شما بارگیری شود.
و سپس، وقتی modelOptions را میسازید و آنها را به CompiledModel.create منتقل میکنید، در آنجا مشخص میکنید که کدام شتابدهنده برای یک مدل خاص استفاده شود، آیا میخواهید مدل دیگر فقط روی GPU اجرا شود، یا GPU با بازگشت به CPU، یا فقط روی CPU.
بسیار خوب.
بله، همانطور که میبینید، فعال کردن GPU با میانای برنامهسازی کاربردی جدید بسیار سادهتر است.
بنابراین، واقعاً چه چیزی بهدست میآورید؟
Chintan به شما خواهد گفت.
بسیار خوب.
بسیارخوب، پس، ممنون فرگوس.
خب، بیایید درباره اینکه همه اینها چه چیزی برای ما بههمراه دارد صحبت کنیم، درست است؟
خب، یادتان هست که گفتیم میخواهیم یک برنامه بسازیم، پس بیایید ببینیم واقعاً چه چیزی ساختهایم، درست است؟
بنابراین، این من هستم، به هر حال، و کاری که ما در اینجا انجام دادهایم این است که اکنون از ML Kit برای پیدا کردن من استفاده کردهایم، بنابراین بخشبندی توسط یک API آماده مانند ML Kit انجام میشود.
بنابراین، این فقط پیدا کردن سر من در آنجا است.
سپس LiteRT از سبکی مشابه انتقال سبک مدل دیگر برای رنگآمیزی پسزمینه استفاده میکند.
و مزایای دیگری که ذکر کردیم این است که حدود ۸ مگابایت در فضا صرفهجویی میکنید، اکنون یک زمان اجرا دارید که بین همه برنامههایتان استفاده میشود، یا حداقل مانند آنچه در اینجا همرسانی شده است، و بهروزرسانیهای خودکار دریافت میکنید، و همچنین یک GPU سریعتر دارید که شما را به حدود ۳۰ فریم در ثانیه میرساند در چیزی که باید برای تجربه کاربری غنی همزمان باشد.
نکته خوب دیگر این است که لازم نیست همه این کارها را بهصورت دستی انجام دهید.
مهارت جدیدی هم وجود دارد که بهتازگی در Android راهاندازی کردهایم، درواقع، مهارت Android LiteRT را منتشر کردهایم که یادگیری ماشین دروندستگاهی شما را ظرف چند دقیقه ارتقا میدهد، درست است؟
بنابراین، میتوانید چند کار با این انجام دهید: میتوانید یک برنامه موجود را ارتقا دهید، میتوانید یک برنامه جدید را داربستبندی کنید، همچنین میتوانید برنامه خود را ارتقا دهید تا از این ادغام جدید خدمات Play نیز استفاده کنید.
بنابراین، همه اینها دردسترس است.
پیوند در اسلاید است، در GitHub هم هست، و در اسناد و وبلاگ ما هم نشان داده خواهد شد.
و بله، بنابراین این باید برای هرکسی که بهدنبال ایجاد تغییر در آینده نزدیک است مفید باشد.
بنابراین، فرگوس به ما خواهد گفت که این موضوع به کجا خواهد رفت.
بنابراین، ما به هوش مصنوعی دروندستگاهی با LiteRT متعهد هستیم.
ما همچنان به سرمایهگذاری قابلتوجهی برای بهبود شتاب GPU و پوشش مدل ادامه میدهیم و بهروزرسانیهای منظمی را برای LiteRT 2.x ارائه میکنیم، هم برای LiteRT متنباز بستهبندیشده و هم برای بسته LiteRT Maven خدمات Play که همان LiteRT در خدمات Play است.
و همچنین به ارائه سازگاری با نسخه قدیمی ادامه خواهیم داد.
زمان اجرای «خدمات Play» همچنان از برنامههای ساختهشده با کیتهای توسعه نرمافزار قدیمیتر پشتیبانی خواهد کرد.
آره.
میدانید که این موضوع برای کاربران ما بسیار مهم است، و برای ما هم بسیار مهم است.
برای کیتهای توسعه نرمافزار LiteRT 1.x، این کیتها اکنون در حالت تعمیر و نگهداری هستند، بنابراین فقط اصلاحات امنیتی حیاتی ارائه میشود.
و NNAPI که در سال ۲۰۲۴ منسوخ کردیم، درحال حذف شدن است و احتمالاً از سال ۲۰۲۷ برداشته خواهد شد.
بنابراین، اگر از NNAPI استفاده میکنید، لطفاً آنها را به استفاده از شتاب GPU یا شتاب NPU با LiteRT همراه تغییر دهید.
بسیارخوب.
آره.
بنابراین، هرچه زودتر به نسخه ۲.x و CompiledModel بروید، بعداً کار کمتری برای انجام دادن خواهید داشت.
بنابراین، سه نکته برای یادآوری.
پس بسازید.
با ML Kit شروع کنید و اگر این کیت نیازهایتان را برآورده میکند، عالی است.
اما اگر اینطور نیست، از LiteRT برای مدلهای سفارشیتان استفاده کنید.
برای صرفهجویی در APK و زمان اجرای مشترک، به LiteRT در «خدمات Google Play» ارتقا دهید.
و برای استنتاج سریعتر و سادهتر GPU، از CompiledModel API استفاده کنید.
آره.
همه چیز در سایت اسناد LiteRT ما در AI Edge در نشانی وب موجود در آنجا مستند شده است.
بنابراین، بله.
از اینکه به ما پیوستید سپاسگزاریم و بیصبرانه منتظریم ببینیم شما چه چیزی میسازید.
// 1. Configure and create segmenter client
val segmenter = Segmentation.getClient(
SelfieSegmenterOptions.Builder()
.setDetectorMode(
SelfieSegmenterOptions.STREAM_MODE)
.build())
// 2. Prepare image & run inference
fun processFrame(mediaImage: Image) {
val image = InputImage.fromMediaImage(
mediaImage, /* rotationDegrees= */ 0)
segmenter.process(image)
.addOnSuccessListener { mask -> … }
}import litert_torch
model = my_models.Stylizer().eval()
# Convert with torch.export under the hood
edge_model = litert_torch.convert(
model, sample_inputs)
edge_model.export("stylizer_f32.tflite")# Python
# previously ai_edge_quantizer
from litert_quantizer import quantizer, recipe
qt = quantizer.Quantizer("stylizer_f32.tflite")
# int8 weights, float activations
qt.load_quantization_recipe(
recipe.dynamic_wi8_afp32())
qt.quantize().export_model("stylizer_int8.tflite")// Kotlin
// Build once, off the main thread.
private val model: CompiledModel =
CompiledModel.create(
context.assets,
"stylizer_int8.tflite",
// Simple GPU setup!
CompiledModel.Options(Accelerator.GPU),
environment
)
// Reuse buffers across frames.
private val inputBuffers = model.createInputBuffers()
private val outputBuffers = model.createOutputBuffers()
fun stylize(input: FloatArray): FloatArray {
inputBuffers[0].writeFloat(input)
model.run(inputBuffers, outputBuffers) // sync
return outputBuffers[0].readFloat()
}// Easier with CompiledModel API: 3 steps
// 1. app/build.gradle: replace litert with play-services-litert
- implementation 'com.google.ai.edge.litert:litert:...'
+ implementation 'com.google.android.gms:play-services-litert:17.0.0' // also pulls in litert-api// 2. Initialize the LiteRT Environment from Play services (context = your Activity)
- val environment = Environment.create(...)
+ import com.google.android.gms.litert.LiteRt
+ val environment = LiteRt.initialize(context).await()
// 3. Pass environment whenever you call CompiledModel.create
// That's it! The rest of your app uses the normal CompiledModel APIs from litert-api.// Dependencies (Gradle):
// play-services-tflite-java and/or litert (bundled)
// Init
TfLite.initialize(context).await()
// Load
val interpreterOptions =
InterpreterApi.Options().apply {
runtime = TfLiteRuntime.FROM_SYSTEM_ONLY
}
val interpreter =
InterpreterApi.create(modelFile, interpreterOptions)
// Prepare inputs/outputs
val inputs = …
val outputs = …
// Execute
interpreter.run(inputs, outputs)// Dependencies (Gradle):
// play-services-litert
// Init
val environment =
LiteRt.initialize(context).await()
// Load
val modelOptions = CompiledModel.Options(Accelerator.CPU)
val model =
CompiledModel.create(modelPath, modelOptions, environment)
// Prepare inputs/outputs
val inputBuffers = model.createInputBuffers()
val outputBuffers = model.createOutputBuffers()
// Execute
model.run(inputBuffers, outputBuffers// Dependencies (Gradle):
// play-services-tflite-java and/or litert (bundled)
// Init
val initOptions = TfLiteInitializationOptions.builder()
.setEnableGpuDelegateSupport(true).build()
TfLite.initialize(context, initOptions).await()
val useGpu =
TfLiteGpu.isGpuDelegateAvailable(context).await()
// Load
val interpreterOptions =
InterpreterApi.Options().apply {
runtime = TfLiteRuntime.FROM_SYSTEM_ONLY
}
if (useGpu) {
interpreterOptions.addDelegateFactory(
GpuDelegateFactory());
}
val interpreter =
InterpreterApi.create(modelFile, interpreterOptions)
// Prepare inputs/outputs
val inputs = …
val outputs = …
// Execute
interpreter.run(inputs, outputs)// Dependencies (Gradle):
// play-services-litert
// Init
val initOptions = LiteRtInitializationOptions.builder()
.setEnableGpu(true).build()
val environment = LiteRt.initialize(context, initOptions).await()
// Load
val modelOptions =
CompiledModel.Options(Accelerator.CPU, Accelerator.GPU)
val model =
CompiledModel.create(modelPath, modelOptions, environment)
// Prepare inputs/outputs
val inputBuffers = model.createInputBuffers()
val outputBuffers = model.createOutputBuffers()
// Execute
model.run(inputBuffers, outputBuffers)